当前位置:首页 > C# > 正文

打造你的专属C#代码修复器(手把手教你用Roslyn开发自定义代码分析与修复工具)

在现代C#开发中,C#代码修复器(Code Fixer)是一种强大的工具,它能自动检测并修复代码中的常见问题。借助微软的Roslyn编译器平台,开发者可以轻松创建自己的自定义代码分析器和修复器。本教程将带你从零开始,一步步构建一个简单的C#代码修复器,即使你是编程小白也能看懂!

什么是Roslyn?

Roslyn 是 .NET 编译器平台,它不仅负责将 C# 代码编译成 IL,还提供了丰富的 API,让开发者能够分析、修改甚至生成代码。通过 Roslyn,我们可以创建:

  • 代码分析器(Analyzer):用于检测代码中的潜在问题。
  • Roslyn代码修复(Code Fix):提供一键修复建议。
打造你的专属C#代码修复器(手把手教你用Roslyn开发自定义代码分析与修复工具) C#代码修复器 自定义代码分析器 Roslyn代码修复 C#开发教程 第1张

准备工作

你需要安装以下工具:

  • Visual Studio 2022(或更高版本)
  • .NET SDK 6.0 或更高版本
  • “Visual Studio extension development” 工作负载(用于调试扩展)

步骤一:创建分析器项目

打开 Visual Studio,选择 “创建新项目”,搜索 “Analyzer”,然后选择 “Analyzer with Code Fix (.NET Standard)” 模板。

命名项目为 MyFirstCodeFixer,点击创建。Visual Studio 会自动生成三个项目:

  • MyFirstCodeFixer:包含分析器和修复器逻辑
  • MyFirstCodeFixer.Test:单元测试项目
  • MyFirstCodeFixer.Vsix:用于在 VS 中调试的扩展包

步骤二:编写一个简单的分析器

我们来实现一个功能:当类名以小写字母开头时,提示用户并提供修复建议(改为大写)。

打开 MyFirstCodeFixer/MyFirstCodeFixerAnalyzer.cs,替换为以下代码:

using Microsoft.CodeAnalysis;using Microsoft.CodeAnalysis.Diagnostics;using System.Collections.Immutable;namespace MyFirstCodeFixer{    [DiagnosticAnalyzer(LanguageNames.CSharp)]    public class MyFirstCodeFixerAnalyzer : DiagnosticAnalyzer    {        public const string DiagnosticId = "MyFirstCodeFixer";        private static readonly LocalizableString Title = "Class name should start with uppercase";        private static readonly LocalizableString MessageFormat = "Class '{0}' should start with an uppercase letter";        private static readonly LocalizableString Description = "Class names must begin with an uppercase letter by convention.";        private const string Category = "Naming";        private static readonly DiagnosticDescriptor Rule = new(            DiagnosticId,            Title,            MessageFormat,            Category,            DiagnosticSeverity.Warning,            isEnabledByDefault: true,            description: Description);        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);        public override void Initialize(AnalysisContext context)        {            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);            context.EnableConcurrentExecution();            context.RegisterSyntaxNodeAction(AnalyzeClassDeclaration, SyntaxKind.ClassDeclaration);        }        private static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context)        {            var classDeclaration = (Microsoft.CodeAnalysis.CSharp.Syntax.ClassDeclarationSyntax)context.Node;            var className = classDeclaration.Identifier.Text;            if (!string.IsNullOrEmpty(className) && char.IsLower(className[0]))            {                var diagnostic = Diagnostic.Create(Rule, classDeclaration.Identifier.GetLocation(), className);                context.ReportDiagnostic(diagnostic);            }        }    }}

步骤三:实现对应的代码修复器

现在,我们来编写修复逻辑。打开 MyFirstCodeFixer/MyFirstCodeFixerCodeFixProvider.cs,替换为:

using Microsoft.CodeAnalysis;using Microsoft.CodeAnalysis.CodeActions;using Microsoft.CodeAnalysis.CodeFixes;using Microsoft.CodeAnalysis.CSharp;using Microsoft.CodeAnalysis.CSharp.Syntax;using Microsoft.CodeAnalysis.Formatting;using System.Collections.Immutable;using System.Composition;using System.Linq;using System.Threading;using System.Threading.Tasks;namespace MyFirstCodeFixer{    [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(MyFirstCodeFixerCodeFixProvider)), Shared]    public class MyFirstCodeFixerCodeFixProvider : CodeFixProvider    {        private const string title = "Make class name uppercase";        public sealed override ImmutableArray<string> FixableDiagnosticIds =>            ImmutableArray.Create(MyFirstCodeFixerAnalyzer.DiagnosticId);        public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)        {            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);            var diagnostic = context.Diagnostics.First();            var diagnosticSpan = diagnostic.Location.SourceSpan;            var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf()                .OfType<ClassDeclarationSyntax>().FirstOrDefault();            if (declaration != null)            {                context.RegisterCodeFix(                    CodeAction.Create(                        title: title,                        createChangedDocument: c => MakeUppercaseAsync(context.Document, declaration, c),                        equivalenceKey: title),                    diagnostic);            }        }        private async Task<Document> MakeUppercaseAsync(Document document, ClassDeclarationSyntax classDecl, CancellationToken cancellationToken)        {            var newName = char.ToUpper(classDecl.Identifier.Text[0]) + classDecl.Identifier.Text.Substring(1);            var newIdentifier = SyntaxFactory.Identifier(newName)                .WithAdditionalAnnotations(Formatter.Annotation);            var newClassDecl = classDecl.WithIdentifier(newIdentifier);            var root = await document.GetSyntaxRootAsync(cancellationToken);            var newRoot = root.ReplaceNode(classDecl, newClassDecl);            return document.WithSyntaxRoot(newRoot);        }    }}

步骤四:测试你的修复器

按 F5 启动调试,Visual Studio 会打开一个新的实验实例。在新实例中创建一个控制台项目,输入以下代码:

class myClass{    static void Main()    {    }}

你会看到 myClass 下方出现波浪线,并提示警告。将鼠标悬停,点击灯泡图标,选择 “Make class name uppercase”,类名就会自动变成 MyClass

总结

通过本教程,你已经掌握了如何使用 Roslyn 平台开发一个简单的 C#代码修复器。这项技能不仅能提升你的 C#开发教程 实践能力,还能帮助团队统一代码风格、减少低级错误。

你可以在此基础上扩展更多规则,比如方法命名、变量命名、空检查等。Roslyn 的强大之处在于它让你像“操作文本”一样操作代码结构,安全又高效。

赶快动手试试吧!如果你喜欢这个教程,欢迎分享给其他 C# 开发者~