Roslyn 识别修改源代码

2023年11月21日 690点热度 0人点赞 0条评论
内容纲要

新建一个项目,项目只能使用 netstandard2。
其 csproj 文件完整内容如下:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
        <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
        <IsRoslynComponent>true</IsRoslynComponent>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" PrivateAssets="all" />
        <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
    </ItemGroup>

</Project>

然后创建一个 实现了 ISourceGenerator 的类型。

[Generator]
public class AOPSourceGenerator : ISourceGenerator
{
    public void Initialize(GeneratorInitializationContext context)
    {
    }

    public void Execute(GeneratorExecutionContext context)
    {
        Debugger.Launch();
        SyntaxTree syntaxTree = context.Compilation.SyntaxTrees.FirstOrDefault();
        if (syntaxTree != null)
        {
            var root = syntaxTree.GetCompilationUnitRoot();
            var rewriter = new AOPRewriter();
            var newRoot = rewriter.Visit(root);

            // 生成文件添加到编译中,文件是临时文件
            context.AddSource("AAA.cs", newRoot.GetText());

            var updatedDoc = syntaxTree.WithChangedText(newRoot.GetText());

            // 持久化保存文件
            using (var fileStream = new FileStream("BBB.cs", FileMode.Truncate))
            {
                updatedDoc.GetTextAsync().Result.Write(new StreamWriter(fileStream));
            }
        }
    }

    // 负责修改代码
    class AOPRewriter : CSharpSyntaxRewriter
    {
        public override SyntaxNode VisitBinaryExpression(BinaryExpressionSyntax node)
        {
            if (node.OperatorToken.IsKind( SyntaxKind.AsteriskToken))
            {
            // 将  x * x 替换为 x + x
                var newNode =  node.WithOperatorToken(SyntaxFactory.Token(SyntaxKind.PlusToken));
                return newNode;
            }
            return base.VisitBinaryExpression(node);
        }
    }
}

痴者工良

高级程序员劝退师

文章评论