Skip to content
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

Merged
merged 1 commit into from
Jun 12, 2024
Merged

分离功能,减少侵入 #309

merged 1 commit into from
Jun 12, 2024

Conversation

NMSAzulX
Copy link
Collaborator

@NMSAzulX NMSAzulX commented Jun 11, 2024

Summary by CodeRabbit

  • New Features

    • Introduced dynamic recompilation of assemblies with the new HECompiler class.
    • Added spin lock management with the HESpinLock class.
    • Implemented file monitoring for C# files via the new VSCSharpMainFileWatcher class.
  • Enhancements

    • Updated ProjectDynamicProxy to improve hot execution and file handling.
    • Refactored VSCSharpProcessor to enhance process handling and initialization logic.
  • Bug Fixes

    • Improved handling of file creation, deletion, and renaming events in VSCSharpMainFileWatcher.

Copy link

coderabbitai bot commented Jun 11, 2024

Walkthrough

The recent updates introduce several new classes and methods to the Natasha.CSharp.Extension.HotExecutor namespace, enhancing dynamic recompilation, file monitoring, and process handling functionalities. Key additions include the HECompiler for recompiling assemblies, HESpinLock for spin lock operations, VSCSharpMainFileWatcher for file monitoring, and significant updates to ProjectDynamicProxy and VSCSharpProcessor to refine hot execution processes.

Changes

File Path Change Summary
src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/HECompiler.cs Introduced HECompiler class for recompiling assemblies. Added ReCompile method.
src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/HESpinLock.cs Introduced HESpinLock class with methods for acquiring, waiting for, and releasing a spin lock.
src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/ProjectDynamicProxy.cs Added new fields for managing hot execution. Updated methods for handling initialization, file processing, and dynamic recompilation.
src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/VSCSharpMainFileWatcher.cs Introduced VSCSharpMainFileWatcher class for monitoring C# files with actions for file creation, deletion, and renaming.
src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/VSCSharpProcessor.cs Updated VSCSharpProcessor class to refactor process handling and initialization logic.

Sequence Diagrams

Hot Execution Process

sequenceDiagram
    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
Loading

File Monitoring

sequenceDiagram
    participant VSCSharpMainFileWatcher
    participant FileSystem

    FileSystem ->> VSCSharpMainFileWatcher: File Created/Deleted/Renamed
    VSCSharpMainFileWatcher ->> VSCSharpMainFileWatcher: PreFunction()
    VSCSharpMainFileWatcher ->> VSCSharpMainFileWatcher: ExecuteAfterFunction()
    VSCSharpMainFileWatcher ->> VSCSharpMainFileWatcher: DeleteFileAction/CreateFileAction/ChangeFileAction
Loading

Poem

In code's embrace, we weave anew,
With locks and trees, our dreams come true.
Files that watch, and processes dance,
Dynamic change, a coder's trance.
Recompile, and swiftly run,
Our journey's just begun.
🌟✨


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?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@NMSAzulX
Copy link
Collaborator Author

@coderabbitai review

Copy link

coderabbitai bot commented Jun 11, 2024

Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@NMSAzulX
Copy link
Collaborator Author

未检测到合适的 ISSUE 推荐给您。感谢您的反馈!

该条自动推荐信息来自于 nms-bot.

Copy link

UT Test - Ubuntu

1 tests   1 ✅  0s ⏱️
1 suites  0 💤
1 files    0 ❌

Results for commit 01d17c4.

Copy link

UT Test - Windows

1 tests   1 ✅  0s ⏱️
1 suites  0 💤
1 files    0 ❌

Results for commit 01d17c4.

Copy link

@coderabbitai coderabbitai bot left a 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

Commits

Files that changed from the base of the PR and between fd17462 and 01d17c4.

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 of GetLock using Interlocked.CompareExchange is efficient and thread-safe.


25-31: The ReleaseLock method correctly resets the lock state.

src/Natasha.CSharp/Extension/Natasha.CSharp.Extension.HotExecutor/HECompiler.cs (2)

12-26: The static constructor appropriately configures the AssemblyCSharpBuilder for dynamic compilation scenarios.


28-42: Ensure robust error handling in ReCompile 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 the FileSystemWatcher 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 the Run 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 in ProjectDynamicProxy.cs correctly handles the first run by initializing necessary components and setting _isFirstRun to false. Subsequent runs are handled by the else 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.cs

Length 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.cs

Length 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.cs

Length of output: 1177

Comment on lines +221 to +287
}
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;
Copy link

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.

Comment on lines +122 to +137
_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);
}


};
Copy link

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.

Suggested change
_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;

Comment on lines +36 to +44
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();

Copy link

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.

Comment on lines +16 to +23
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void GetAndWaitLock()
{
while (Interlocked.CompareExchange(ref _lockCount, 1, 0) != 0)
{
Thread.Sleep(20);
}
}
Copy link

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.

Comment on lines +171 to +181
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();
Copy link

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.

Suggested change
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();

Comment on lines +29 to +160
}

};

_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);
}
}
Copy link

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.

@NMSAzulX NMSAzulX merged commit ad8ff7e into dev.next Jun 12, 2024
8 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

1 participant