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

增加对 if/else try/catch 组合语句的命令递归解析 #347

Merged
merged 1 commit into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Natasha.CSharp.HotExecutor.Component.SyntaxUtils
{
internal static class MethodTriviaRewriter
{
public static CompilationUnitSyntax Handle(CompilationUnitSyntax root, Func<string,string?> replaceFunc)
public static CompilationUnitSyntax Handle(CompilationUnitSyntax root, Func<string, string?> replaceFunc)
{

var methodDeclarations = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
Expand All @@ -20,7 +20,7 @@ public static CompilationUnitSyntax Handle(CompilationUnitSyntax root, Func<stri
ConcurrentDictionary<BlockSyntax, BlockSyntax> replaceBodyCache = [];
foreach (var methodDeclaration in methodDeclarations)
{

var bodyNode = methodDeclaration.Body;
if (bodyNode != null)
{
Expand All @@ -32,16 +32,22 @@ public static CompilationUnitSyntax Handle(CompilationUnitSyntax root, Func<stri
.Where(item => item.Parent != null);
if (tempDict.Any())
{
blockCache = new(tempDict.ToDictionary(item => {
blockCache = new(tempDict.ToDictionary(item =>
{

SyntaxNode parent = item.Parent!;
while (!parent.IsKind(SyntaxKind.MethodDeclaration) && parent is not StatementSyntax)
while (
!parent.IsKind(SyntaxKind.MethodDeclaration) &&
parent is not StatementSyntax &&
parent is not CatchClauseSyntax &&
parent is not FinallyClauseSyntax &&
parent is not ElseClauseSyntax)
{
parent = parent.Parent!;
parent = parent.Parent!;
}
return parent;

} , item => item));
}, item => item));
}

var newBody = GetNewBlockSyntax(bodyNode, replaceFunc, blockCache);
Expand All @@ -62,44 +68,44 @@ public static CompilationUnitSyntax Handle(CompilationUnitSyntax root, Func<stri
}

private static BlockSyntax? GetNewBlockSyntax(
BlockSyntax methodBodySyntax,
BlockSyntax bodySyntax,
Func<string, string?> replaceFunc,
ConcurrentDictionary<SyntaxNode, BlockSyntax>? blockCache
)
{
var removeIndexs = new HashSet<int>();
// 获取方法体
Dictionary<int, List<StatementSyntax>> addStatementCache = [];
if (methodBodySyntax.OpenBraceToken.HasLeadingTrivia)
if (bodySyntax.OpenBraceToken.HasLeadingTrivia)
{
var (needDelete, newStatements) = HandleTriviaComment(methodBodySyntax.OpenBraceToken.LeadingTrivia, false, replaceFunc);
if (newStatements.Count>0)
var (needDelete, newStatements) = HandleTriviaComment(bodySyntax.OpenBraceToken.LeadingTrivia, false, replaceFunc);
if (newStatements.Count > 0)
{
addStatementCache[-1] = newStatements;
}
}
var statementCount = methodBodySyntax.Statements.Count;
var statementCount = bodySyntax.Statements.Count;
// 遍历方法体中的语句
for (int i = 0; i < statementCount; i++)
{

// 获取当前语句
var statement = methodBodySyntax.Statements[i];
var statement = bodySyntax.Statements[i];

var (needDelete, newStatements) = GetNewStatmentSyntax(statement, replaceFunc, blockCache);
if (needDelete)
{
removeIndexs.Add(i);
}
if (newStatements.Count>0)
if (newStatements.Count > 0)
{
addStatementCache[i] = newStatements;
}

}

if (methodBodySyntax.CloseBraceToken.HasLeadingTrivia)
if (bodySyntax.CloseBraceToken.HasLeadingTrivia)
{
var (needDelete, newStatements) = HandleTriviaComment(methodBodySyntax.CloseBraceToken.LeadingTrivia, false, replaceFunc);
var (needDelete, newStatements) = HandleTriviaComment(bodySyntax.CloseBraceToken.LeadingTrivia, false, replaceFunc);
if (newStatements.Count > 0)
{
addStatementCache[-2] = newStatements;
Expand All @@ -109,7 +115,7 @@ public static CompilationUnitSyntax Handle(CompilationUnitSyntax root, Func<stri
// 如果找到,创建新的方法体列表并排除该语句
if (removeIndexs.Count > 0 || addStatementCache.Count > 0)
{
var statements = methodBodySyntax.Statements;
var statements = bodySyntax.Statements;
List<StatementSyntax> newStatments = [];
if (addStatementCache.TryGetValue(-1, out var headList))
{
Expand Down Expand Up @@ -137,10 +143,10 @@ public static CompilationUnitSyntax Handle(CompilationUnitSyntax root, Func<stri
}

return null;

}

private static (bool needDelete,List<StatementSyntax> newStatements) GetNewStatmentSyntax(
private static (bool needDelete, List<StatementSyntax> newStatements) GetNewStatmentSyntax(
StatementSyntax statement,
Func<string, string?> replaceFunc,
ConcurrentDictionary<SyntaxNode, BlockSyntax>? blockCache)
Expand All @@ -154,14 +160,99 @@ private static (bool needDelete,List<StatementSyntax> newStatements) GetNewStatm
}
if (!shouldDelete)
{
if (blockCache != null && blockCache.TryGetValue(statement, out var subBlock))
if (blockCache != null)
{
var newBlock = GetNewBlockSyntax(subBlock, replaceFunc, blockCache);
if (newBlock != null)
if (statement is TryStatementSyntax trySyntax)
{
statementList.Add(statement.ReplaceNode(subBlock, newBlock));
BlockSyntax newTryBlock = trySyntax.Block;
if (blockCache.TryGetValue(trySyntax, out var subBlock))
{
var newTempTryBlock = GetNewBlockSyntax(trySyntax.Block, replaceFunc, blockCache);
if (newTempTryBlock != null)
{
newTryBlock = newTempTryBlock;
}
}
SyntaxList<CatchClauseSyntax> newCatchList = [];
foreach (var catchStatement in trySyntax.Catches)
{
if (blockCache.TryGetValue(catchStatement, out var subCacheBlock))
{
var newBlock = GetNewBlockSyntax(subCacheBlock, replaceFunc, blockCache);
if (newBlock != null)
{
newCatchList = newCatchList.Add(catchStatement.ReplaceNode(subCacheBlock, newBlock));
}
else
{
newCatchList = newCatchList.Add(catchStatement);
}
}
}
FinallyClauseSyntax? newFinally = trySyntax.Finally;
if (trySyntax.Finally != null && blockCache.TryGetValue(trySyntax.Finally, out var subFinallyBlock))
{
var newBlock = GetNewBlockSyntax(subFinallyBlock, replaceFunc, blockCache);
if (newBlock != null)
{
newFinally = SyntaxFactory.FinallyClause(newBlock);
}
}
trySyntax = SyntaxFactory.TryStatement(newTryBlock, newCatchList, newFinally);
statementList.Add(trySyntax);
shouldDelete = true;
}
else if (statement is IfStatementSyntax ifSyntax && blockCache.TryGetValue(statement, out var subIfBlock))
{
StatementSyntax newIfStatmentBlock = subIfBlock;
ElseClauseSyntax? newElseClause = ifSyntax.Else;
var newIfBlock = GetNewBlockSyntax(subIfBlock, replaceFunc, blockCache);
if (newIfBlock != null)
{
newIfStatmentBlock = newIfBlock;
}
if (ifSyntax.Else != null)
{
if (ifSyntax.Else.Statement is IfStatementSyntax elseIfSyntax)
{
var tempElseResult = GetNewStatmentSyntax(
elseIfSyntax
, replaceFunc, blockCache);
if (tempElseResult.needDelete)
{
var newTempIfStatementSyntax = (tempElseResult.newStatements[0] as IfStatementSyntax)!;
newElseClause = SyntaxFactory.ElseClause(newTempIfStatementSyntax);
}

}
else if (ifSyntax.Else.Statement is BlockSyntax elseBlockSyntax && blockCache.TryGetValue(ifSyntax.Else, out var subElseIfBlock))
{
var newElseBlockSyntax = GetNewBlockSyntax(
subElseIfBlock
, replaceFunc, blockCache);
if (newElseBlockSyntax != null) {

newElseClause = SyntaxFactory.ElseClause(newElseBlockSyntax);
}

}
}

statementList.Add(SyntaxFactory.IfStatement(ifSyntax.Condition, newIfStatmentBlock, newElseClause));
shouldDelete = true;
}
else
{
if (blockCache.TryGetValue(statement, out var subBlock))
{
var newBlock = GetNewBlockSyntax(subBlock, replaceFunc, blockCache);
if (newBlock != null)
{
statementList.Add(statement.ReplaceNode(subBlock, newBlock));
shouldDelete = true;
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ static VSCSharpProjectInfomation()
var currentDirectoryInfo = new DirectoryInfo(ExecutePath);
MainCsprojPath = FindFileDirectory(currentDirectoryInfo,"*.csproj");
HEOutputPath = Path.Combine(MainCsprojPath, "HEOutput");
if (!Directory.Exists(HEOutputPath))
{
Directory.CreateDirectory(HEOutputPath);
}
Comment on lines +34 to +37
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add exception handling for directory creation.

To ensure robustness, handle potential exceptions that might occur during directory creation.

if (!Directory.Exists(HEOutputPath))
{
    try
    {
        Directory.CreateDirectory(HEOutputPath);
    }
    catch (Exception ex)
    {
        // Handle the exception, e.g., log the error or rethrow
        Console.WriteLine($"Failed to create directory {HEOutputPath}: {ex.Message}");
    }
}

var files = Directory.GetFiles(MainCsprojPath,"*.csproj");
CSProjFilePath = files[0];
BinPath = Path.Combine(MainCsprojPath, "bin");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,15 @@ public static void Run()
private static bool _isFirstCompile = true;
private static async Task HotExecute()
{
try
{
CleanErrorFiles();
}
catch (Exception ex)
{
ShowMessage("清除 HEOutput 文件夹时出错:"+ ex.Message);
}

try
{
if (_isFirstCompile)
Expand Down Expand Up @@ -399,14 +408,6 @@ private static async Task HotExecute()
}
}
ShowMessage($"Error during hot execution: {errorBuilder}");
var files = Directory.GetFiles(VSCSharpProjectInfomation.HEOutputPath);
foreach (var file in files)
{
if (file.StartsWith("error."))
{
File.Delete(file);
}
}
File.WriteAllText(Path.Combine(VSCSharpProjectInfomation.HEOutputPath, "error." + Guid.NewGuid().ToString("N") + ".txt"), nex.Formatter);
}
else
Expand All @@ -420,6 +421,18 @@ private static async Task HotExecute()
return;
}
#region 辅助方法区

private static void CleanErrorFiles()
{
var files = Directory.GetFiles(VSCSharpProjectInfomation.HEOutputPath);
foreach (var file in files)
{
if (Path.GetFileName(file).StartsWith("error."))
{
File.Delete(file);
}
}
Comment on lines +425 to +434
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add exception handling for file deletion.

To ensure robustness, handle potential exceptions that might occur during file deletion.

var files = Directory.GetFiles(VSCSharpProjectInfomation.HEOutputPath);
foreach (var file in files)
{
    if (Path.GetFileName(file).StartsWith("error."))
    {
        try
        {
            File.Delete(file);
        }
        catch (Exception ex)
        {
            // Handle the exception, e.g., log the error or rethrow
            Console.WriteLine($"Failed to delete file {file}: {ex.Message}");
        }
    }
}

}
private async static Task ReAnalysisFiles()
{
#if DEBUG
Expand Down
Loading