-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
分离功能,减少侵入 #309
Conversation
WalkthroughThe recent updates introduce several new classes and methods to the Changes
Sequence DiagramsHot Execution ProcesssequenceDiagram
participant User
participant ProjectDynamicProxy
participant HECompiler
participant VSCSharpMainFileWatcher
User ->> ProjectDynamicProxy: Run()
ProjectDynamicProxy ->> VSCSharpMainFileWatcher: StartMonitor()
VSCSharpMainFileWatcher ->> ProjectDynamicProxy: Notify file change
ProjectDynamicProxy ->> HECompiler: ReCompile(trees, isRelease)
HECompiler -->> ProjectDynamicProxy: Assembly
ProjectDynamicProxy ->> User: Execute Assembly
File MonitoringsequenceDiagram
participant VSCSharpMainFileWatcher
participant FileSystem
FileSystem ->> VSCSharpMainFileWatcher: File Created/Deleted/Renamed
VSCSharpMainFileWatcher ->> VSCSharpMainFileWatcher: PreFunction()
VSCSharpMainFileWatcher ->> VSCSharpMainFileWatcher: ExecuteAfterFunction()
VSCSharpMainFileWatcher ->> VSCSharpMainFileWatcher: DeleteFileAction/CreateFileAction/ChangeFileAction
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
@coderabbitai review |
Actions performedReview triggered.
|
未检测到合适的 ISSUE 推荐给您。感谢您的反馈!
|
UT Test - Ubuntu1 tests 1 ✅ 0s ⏱️ Results for commit 01d17c4. |
UT Test - Windows1 tests 1 ✅ 0s ⏱️ Results for commit 01d17c4. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Outside diff range and nitpick comments (3)
src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/VSCSharpProcessor.cs (1)
Line range hint
90-121
: Refactor the process management to ensure that resources are properly released and to handle potential exceptions more gracefully.src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.cs (2)
18-18
: Consider initializing_proxyMethodName
with a default value directly in its declaration.This can improve readability and ensure that the variable is always initialized to a known state.
Line range hint
49-95
: Refactor the nested conditional and loop logic for clarity and maintainability.The method inside
_csprojWatcher
initialization is complex and hard to follow. Consider breaking it down into smaller, more manageable methods.
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (5)
- src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/HECompiler.cs (1 hunks)
- src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/HESpinLock.cs (1 hunks)
- src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.cs (7 hunks)
- src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/VSCSharpMainFileWatcher.cs (1 hunks)
- src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/VSCSharpProcessor.cs (4 hunks)
Additional comments not posted (9)
src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/HESpinLock.cs (2)
9-14
: The implementation ofGetLock
usingInterlocked.CompareExchange
is efficient and thread-safe.
25-31
: TheReleaseLock
method correctly resets the lock state.src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/HECompiler.cs (2)
12-26
: The static constructor appropriately configures theAssemblyCSharpBuilder
for dynamic compilation scenarios.
28-42
: Ensure robust error handling inReCompile
to manage potential compilation failures.src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/VSCSharpProcessor.cs (1)
16-16
: The constructor is well-organized and sets up the process environment effectively.src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/VSCSharpMainFileWatcher.cs (1)
18-27
: The constructor effectively sets up theFileSystemWatcher
and default actions, ensuring readiness for file monitoring.src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.cs (3)
21-31
: Initialization of static fields is done correctly.All static fields are initialized properly, ensuring thread safety and correct behavior during concurrent access.
110-117
: Simplify the lambda expression for better readability.
[REFACTOR_SUGGESTion]- _mainWatcher.PreFunction = () => - { - if (_isFaildBuild) - { - _csprojWatcher.Notify(); - return true; - } - return false; - }; + _mainWatcher.PreFunction = () => _isFaildBuild && _csprojWatcher.Notify();This change makes the code more concise and easier to understand.
184-218
: Review the logic in theRun
method to ensure it behaves as expected.This script checks the implementation of the
Run
method to ensure it handles the first run and subsequent runs correctly.Verification successful
The
Run
method inProjectDynamicProxy.cs
correctly handles the first run by initializing necessary components and setting_isFirstRun
tofalse
. Subsequent runs are handled by theelse
block, which outputs a debug message indicating that initialization has already occurred.
- The method checks
_isFirstRun
and uses a lock to ensure thread safety during initialization.- It processes source code files and caches their syntax trees.
The logic appears to be sound and should behave as expected.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the behavior of the `Run` method under different conditions. # Test: Check if the method correctly handles the first run and subsequent runs. ast-grep --lang csharp --pattern $'public static void Run($_, $_) { $$$ if ($_) { $$$ } $$$ }'Length of output: 109
Script:
#!/bin/bash # Description: Verify the presence and logic of the `Run` method in the `ProjectDynamicProxy.cs` file. # Step 1: Locate the `Run` method in the `ProjectDynamicProxy.cs` file. ast-grep --lang csharp --pattern $'public static void Run($_) { $$$ }' src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.cs # Step 2: Verify the logic inside the `Run` method to ensure it handles the first run and subsequent runs correctly. ast-grep --lang csharp --pattern $'public static void Run(string? argumentsMethodName = "ProxyMainArguments") { if ($_isFirstRun) { lock ($_runLock) { if ($_isFirstRun) { $_isFirstRun = false; $_argumentsMethodName = $_; var $_ = Directory.GetFiles($_, "*.cs", SearchOption.AllDirectories); foreach (var $_ in $_) { if ($_mainWatcher.CheckFileAvailiable($_)) { var $_ = ReadFile($_); var $_ = HandleTree($_); var $_ = $_.GetRoot(); _fileCache[$_] = $_.SyntaxTree; } } //HotExecute(); } } } #if DEBUG else { Console.WriteLine("已经初始化过了!"); } #endif }' src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.csLength of output: 984
Script:
#!/bin/bash # Description: Verify the presence and logic of the `Run` method in the `ProjectDynamicProxy.cs` file. # Step 1: Locate the `Run` method in the `ProjectDynamicProxy.cs` file. ast-grep --lang csharp --pattern $'public static void Run(string? argumentsMethodName = "ProxyMainArguments") { $$$ }' src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.cs # Step 2: Verify the logic inside the `Run` method to ensure it handles the first run and subsequent runs correctly. ast-grep --lang csharp --pattern $'public static void Run(string? argumentsMethodName = "ProxyMainArguments") { if ($_isFirstRun) { lock ($_runLock) { if ($_isFirstRun) { $_isFirstRun = false; $_argumentsMethodName = $_; var $_ = Directory.GetFiles($_, "*.cs", SearchOption.AllDirectories); foreach (var $_ in $_) { if ($_mainWatcher.CheckFileAvailiable($_)) { var $_ = ReadFile($_); var $_ = HandleTree($_); var $_ = $_.GetRoot(); _fileCache[$_] = $_.SyntaxTree; } } //HotExecute(); } } } #if DEBUG else { Console.WriteLine("已经初始化过了!"); } #endif }' src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.csLength of output: 1032
Script:
#!/bin/bash # Description: Verify the presence and logic of the `Run` method in the `ProjectDynamicProxy.cs` file. # Step 1: Locate the `Run` method in the `ProjectDynamicProxy.cs` file. rg 'public static void Run' src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.cs # Step 2: Verify the logic inside the `Run` method to ensure it handles the first run and subsequent runs correctly. rg -A 20 'public static void Run' src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.csLength of output: 1177
} | ||
public static void ClearArgs() | ||
{ | ||
_args.Clear(); | ||
} | ||
public static void Run(string proxyMethodName = "ProxyMain", string? argumentsMethodName= "ProxyMainArguments") | ||
{ | ||
_proxyMethodName = proxyMethodName; | ||
_argumentsMethodName = argumentsMethodName; | ||
var srcCodeFiles = Directory.GetFiles(VSCSharpFolder.MainCsprojPath, "*.cs", SearchOption.AllDirectories); | ||
var tree = NatashaCSharpSyntax.ParseTree(content, _debugOptions); | ||
var root = tree.GetRoot(); | ||
|
||
foreach (var file in srcCodeFiles) | ||
var methodDeclarations = root.DescendantNodes().OfType<MethodDeclarationSyntax>(); | ||
Dictionary<MethodDeclarationSyntax, MethodDeclarationSyntax> replaceMethodCache = []; | ||
foreach (var methodDeclaration in methodDeclarations) | ||
{ | ||
if (CheckFileAvailiable(file)) | ||
var removeIndexs = new HashSet<int>(); | ||
// 获取方法体 | ||
var methodBody = methodDeclaration.Body; | ||
if (methodBody == null) | ||
{ | ||
continue; | ||
} | ||
// 遍历方法体中的语句 | ||
for (int i = 0; i < methodBody.Statements.Count; i++) | ||
{ | ||
var content = ReadFile(file); | ||
//Console.WriteLine(file); | ||
//Console.WriteLine(content); | ||
//Console.WriteLine("------------"); | ||
var tree = NatashaCSharpSyntax.ParseTree(content, null); | ||
var mainMethod = tree.GetRoot().DescendantNodes() | ||
.OfType<MethodDeclarationSyntax>() | ||
.FirstOrDefault(m => m.Identifier.Text == "Main"); | ||
|
||
if (mainMethod != null) | ||
// 获取当前语句 | ||
var statement = methodBody.Statements[i]; | ||
if (statement is ExpressionStatementSyntax) | ||
{ | ||
ClassDeclarationSyntax? parentClass = mainMethod.Parent as ClassDeclarationSyntax ?? throw new Exception("获取 Main 方法类名出现错误!"); | ||
_className = parentClass.Identifier.Text; | ||
|
||
var proxyMethod = tree.GetRoot().DescendantNodes() | ||
.OfType<MethodDeclarationSyntax>() | ||
.FirstOrDefault(m => m.Identifier.Text == proxyMethodName); | ||
|
||
if (proxyMethod == null) | ||
var trivias = statement.GetLeadingTrivia(); | ||
foreach (var trivia in trivias) | ||
{ | ||
throw new Exception($"{_className} 中未找到 {proxyMethodName} 代理方法!"); | ||
if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) && trivia.ToString().Trim().StartsWith("//Once")) | ||
{ | ||
removeIndexs.Add(i); | ||
break; | ||
} | ||
} | ||
_mainFile = file; | ||
} | ||
_fileCache[file] = tree; | ||
} | ||
|
||
// 如果找到,创建新的方法体列表并排除该语句 | ||
if (removeIndexs.Count > 0) | ||
{ | ||
var newMethodBody = new List<StatementSyntax>(methodBody.Statements.Where((s, index) => !removeIndexs.Contains(index))); | ||
replaceMethodCache[methodDeclaration] = methodDeclaration.WithBody(SyntaxFactory.Block(newMethodBody)); | ||
} | ||
} | ||
|
||
HotExecute(); | ||
} | ||
foreach (var item in replaceMethodCache) | ||
{ | ||
//#if DEBUG | ||
// Console.WriteLine(); | ||
// Console.WriteLine("方法:"); | ||
// Console.WriteLine(item.Key.ToFullString()); | ||
// Console.WriteLine("替换为:"); | ||
// Console.WriteLine(item.Value.ToFullString()); | ||
// Console.WriteLine(); | ||
//#endif | ||
root = root.ReplaceNode(item.Key, item.Value); | ||
tree = root.SyntaxTree; | ||
} | ||
|
||
var mainMethod = root.DescendantNodes() | ||
.OfType<MethodDeclarationSyntax>() | ||
.FirstOrDefault(m => m.Identifier.Text == "Main"); | ||
|
||
if (mainMethod != null) | ||
{ | ||
ClassDeclarationSyntax? parentClass = mainMethod.Parent as ClassDeclarationSyntax ?? throw new Exception("获取 Main 方法类名出现错误!"); | ||
_className = parentClass.Identifier.Text; | ||
} | ||
return tree; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor the HandleTree
method to improve readability and maintainability.
The method is lengthy and performs multiple operations. Consider breaking it down into smaller, more focused methods.
_mainWatcher.ChangeFileAction = file => { | ||
var content = ReadFile(file); | ||
if (file == _mainFile) | ||
{ | ||
return; | ||
} | ||
var tree = NatashaCSharpSyntax.ParseTree(content, _debugOptions); | ||
var tree = HandleTree(content); | ||
_fileCache[file] = tree; | ||
} | ||
}; | ||
|
||
static void DeleteFile(string file) | ||
{ | ||
_mainWatcher.DeleteFileAction = file => { | ||
_fileCache.TryRemove(file, out _); | ||
} | ||
}; | ||
|
||
static void ChangeFile(string file) | ||
_mainWatcher.CreateFileAction = file => | ||
{ | ||
var content = ReadFile(file); | ||
var tree = NatashaCSharpSyntax.ParseTree(content, _debugOptions); | ||
var tree = HandleTree(content); | ||
_fileCache[file] = tree; | ||
} | ||
|
||
static void RenameFile(string file) | ||
{ | ||
DeleteFile(file); | ||
CreateFile(file); | ||
} | ||
|
||
|
||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimize file handling in the ChangeFileAction
and CreateFileAction
.
Consider abstracting the common logic into a separate method to avoid code duplication.
+ private static void ProcessFile(string file) {
+ var content = ReadFile(file);
+ var tree = HandleTree(content);
+ _fileCache[file] = tree;
+ }
- _mainWatcher.ChangeFileAction = file => {
- var content = ReadFile(file);
- var tree = HandleTree(content);
- _fileCache[file] = tree;
- };
- _mainWatcher.CreateFileAction = file =>
- {
- var content = ReadFile(file);
- var tree = HandleTree(content);
- _fileCache[file] = tree;
- };
+ _mainWatcher.ChangeFileAction = ProcessFile;
+ _mainWatcher.CreateFileAction = ProcessFile;
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
_mainWatcher.ChangeFileAction = file => { | |
var content = ReadFile(file); | |
if (file == _mainFile) | |
{ | |
return; | |
} | |
var tree = NatashaCSharpSyntax.ParseTree(content, _debugOptions); | |
var tree = HandleTree(content); | |
_fileCache[file] = tree; | |
} | |
}; | |
static void DeleteFile(string file) | |
{ | |
_mainWatcher.DeleteFileAction = file => { | |
_fileCache.TryRemove(file, out _); | |
} | |
}; | |
static void ChangeFile(string file) | |
_mainWatcher.CreateFileAction = file => | |
{ | |
var content = ReadFile(file); | |
var tree = NatashaCSharpSyntax.ParseTree(content, _debugOptions); | |
var tree = HandleTree(content); | |
_fileCache[file] = tree; | |
} | |
static void RenameFile(string file) | |
{ | |
DeleteFile(file); | |
CreateFile(file); | |
} | |
}; | |
private static void ProcessFile(string file) { | |
var content = ReadFile(file); | |
var tree = HandleTree(content); | |
_fileCache[file] = tree; | |
} | |
_mainWatcher.ChangeFileAction = ProcessFile; | |
_mainWatcher.DeleteFileAction = file => { | |
_fileCache.TryRemove(file, out _); | |
}; | |
_mainWatcher.CreateFileAction = ProcessFile; |
NatashaManagement.Preheating(true, true); | ||
_debugOptions = new CSharpParseOptions(LanguageVersion.Preview, preprocessorSymbols: ["DEBUG", "RELEASE"]); | ||
// var emptyTreeScript = @"internal class Program{ | ||
// static void Main(){ } | ||
//}"; | ||
// _emptyMainTree = CSharpSyntaxTree.ParseText(emptyTreeScript).GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First(); | ||
_buildLock = new(); | ||
_mainWatcher = new(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper exception handling in the static constructor.
+ try {
NatashaManagement.Preheating(true, true);
_debugOptions = new CSharpParseOptions(LanguageVersion.Preview, preprocessorSymbols: ["DEBUG", "RELEASE"]);
_buildLock = new();
_mainWatcher = new();
_processor = new();
_csprojWatcher = new(VSCSharpFolder.CSProjFilePath, async () => {
+ } catch (Exception ex) {
+ // Handle initialization exceptions
+ }
Adding a try-catch block can prevent the static constructor from throwing exceptions, which could lead to type initialization failures.
Committable suggestion was skipped due to low confidence.
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public void GetAndWaitLock() | ||
{ | ||
while (Interlocked.CompareExchange(ref _lockCount, 1, 0) != 0) | ||
{ | ||
Thread.Sleep(20); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider replacing Thread.Sleep
with a more efficient waiting mechanism, such as SpinWait.SpinUntil
, to reduce CPU usage during lock contention.
public static void AppendArgs(string arg) | ||
{ | ||
while (Interlocked.CompareExchange(ref _lockCount, 1, 0) != 0) | ||
{ | ||
Thread.Sleep(20); | ||
} | ||
_args.Add(arg); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static void ReleaseLock() | ||
public static void AppendArgs(params string[] args) | ||
{ | ||
|
||
_lockCount = 0; | ||
|
||
_args.AddRange(args); | ||
} | ||
private static void CurrentDomain_ProcessExit(object sender, EventArgs e) | ||
public static void ClearArgs() | ||
{ | ||
_delAndCreateAndRenameWatcher.Dispose(); | ||
_args.Clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure consistent method naming and consider using more descriptive names.
The methods AppendArgs
and ClearArgs
could be renamed to reflect their actions more clearly.
- public static void AppendArgs(string arg)
+ public static void AddArgument(string arg)
- public static void AppendArgs(params string[] args)
+ public static void AddArguments(params string[] args)
- public static void ClearArgs()
+ public static void ClearArguments()
This change enhances readability and makes the API more intuitive.
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public static void AppendArgs(string arg) | |
{ | |
while (Interlocked.CompareExchange(ref _lockCount, 1, 0) != 0) | |
{ | |
Thread.Sleep(20); | |
} | |
_args.Add(arg); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
private static void ReleaseLock() | |
public static void AppendArgs(params string[] args) | |
{ | |
_lockCount = 0; | |
_args.AddRange(args); | |
} | |
private static void CurrentDomain_ProcessExit(object sender, EventArgs e) | |
public static void ClearArgs() | |
{ | |
_delAndCreateAndRenameWatcher.Dispose(); | |
_args.Clear(); | |
public static void AddArgument(string arg) | |
{ | |
_args.Add(arg); | |
} | |
public static void AddArguments(params string[] args) | |
{ | |
_args.AddRange(args); | |
} | |
public static void ClearArguments() | |
{ | |
_args.Clear(); |
} | ||
|
||
}; | ||
|
||
_mainWatcher.Deleted += async (sender, e) => | ||
{ | ||
if (PreFunction()) | ||
{ | ||
return; | ||
} | ||
#if DEBUG | ||
Console.WriteLine($"Deleted: {e.FullPath}"); | ||
#endif | ||
if (CheckFileAvailiable(e.FullPath)) | ||
{ | ||
_compileLock.GetAndWaitLock(); | ||
DeleteFileAction(e.FullPath); | ||
_compileLock.ReleaseLock(); | ||
await ExecuteAfterFunction(); | ||
} | ||
|
||
}; | ||
|
||
_mainWatcher.Renamed += async (sender, e) => | ||
{ | ||
if (PreFunction()) | ||
{ | ||
return; | ||
} | ||
#if DEBUG | ||
Console.WriteLine($"Renamed: {e.OldFullPath} -> {e.FullPath}"); | ||
#endif | ||
if (e.OldFullPath.EndsWith(".cs")) | ||
{ | ||
if (e.FullPath.EndsWith(".cs")) | ||
{ | ||
_compileLock.GetAndWaitLock(); | ||
if (CheckFileAvailiable(e.FullPath)) | ||
{ | ||
CreateFileAction(e.FullPath); | ||
} | ||
if (CheckFileAvailiable(e.OldFullPath)) | ||
{ | ||
DeleteFileAction(e.OldFullPath); | ||
} | ||
_compileLock.ReleaseLock(); | ||
await ExecuteAfterFunction(); | ||
} | ||
else if (e.FullPath.StartsWith(e.OldFullPath) && e.FullPath.EndsWith(".TMP")) | ||
{ | ||
|
||
if (CheckFileAvailiable(e.OldFullPath)) | ||
{ | ||
_compileLock.GetAndWaitLock(); | ||
ChangeFileAction(e.OldFullPath); | ||
_compileLock.ReleaseLock(); | ||
await ExecuteAfterFunction(); | ||
} | ||
} | ||
|
||
} | ||
}; | ||
_mainWatcher.Error += Error; | ||
} | ||
private async Task ExecuteAfterFunction() | ||
{ | ||
if (_compileLock.GetLock()) | ||
{ | ||
await AfterFunction(); | ||
_compileLock.ReleaseLock(); | ||
} | ||
#if DEBUG | ||
else{ | ||
Console.WriteLine($"争抢编译,做出让步!"); | ||
} | ||
#endif | ||
} | ||
public bool CheckFileAvailiable(string file) | ||
{ | ||
if (file.StartsWith(VSCSharpFolder.ObjPath) || file.StartsWith(VSCSharpFolder.BinPath)) | ||
{ | ||
return false; | ||
} | ||
return true; | ||
} | ||
private static void Error(object sender, ErrorEventArgs e) | ||
{ | ||
PrintException(e.GetException()); | ||
} | ||
private static void PrintException(Exception? ex) | ||
{ | ||
if (ex != null) | ||
{ | ||
Console.WriteLine($"Message: {ex.Message}"); | ||
Console.WriteLine("Stacktrace:"); | ||
Console.WriteLine(ex.StackTrace); | ||
Console.WriteLine(); | ||
PrintException(ex.InnerException); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The event handlers are well-implemented, ensuring actions are taken based on file changes. Consider adding more detailed logging to aid in debugging and monitoring.
Summary by CodeRabbit
New Features
HECompiler
class.HESpinLock
class.VSCSharpMainFileWatcher
class.Enhancements
ProjectDynamicProxy
to improve hot execution and file handling.VSCSharpProcessor
to enhance process handling and initialization logic.Bug Fixes
VSCSharpMainFileWatcher
.