You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

求助:为Core 2.0代码分析器添加自定义规则的示例

嘿,刚上手基于NuGet的代码分析器是吧?既然已经装了Microsoft.CodeAnalysis.FxCopAnalyzers,那自定义规则其实没你想的那么复杂,我给你结合Core 2.0的场景,一步步写个完整的示例,保证你能快速跑起来~

自定义Core 2.0代码分析规则实现示例

一、先搭好项目结构

首先得创建一个类库项目(.NET Standard 2.0)——因为Core 2.0兼容这个版本,这样你的分析器才能在Core 2.0项目里正常工作。然后安装两个必要的NuGet包:

  • Microsoft.CodeAnalysis.Analyzers:代码分析器的基础框架
  • Microsoft.CodeAnalysis.CSharp:提供C#语法分析的支持

二、编写自定义分析器规则

我给你写个简单易懂的规则示例:禁止方法名以下划线开头,既能理解核心逻辑,又能快速验证效果。

1. 核心分析器类实现

创建一个继承自DiagnosticAnalyzer的类,这是自定义规则的核心载体:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class NoUnderscorePrefixMethodAnalyzer : DiagnosticAnalyzer
{
    // 定义诊断的唯一标识、标题、提示信息等
    public const string DiagnosticId = "CS0001";
    private const string Title = "方法名不能以下划线开头";
    private const string MessageFormat = "方法 '{0}' 的名称以下划线开头,不符合编码规范";
    private const string Description = "为保持代码风格一致,禁止方法名使用下划线开头";
    private const string Category = "Naming";

    // 构建诊断规则实例
    private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
        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.EnableConcurrentExecution();
        // 跳过自动生成的代码(比如Designer文件)
        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

        // 注册对方法声明节点的分析逻辑
        context.RegisterSyntaxNodeAction(AnalyzeMethodDeclaration, SyntaxKind.MethodDeclaration);
    }

    // 具体的代码检查逻辑
    private void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
    {
        var methodDeclaration = (MethodDeclarationSyntax)context.Node;
        var methodName = methodDeclaration.Identifier.Text;

        // 判断方法名是否违反规则
        if (methodName.StartsWith("_"))
        {
            // 生成诊断信息并报告
            var diagnostic = Diagnostic.Create(Rule, methodDeclaration.Identifier.GetLocation(), methodName);
            context.ReportDiagnostic(diagnostic);
        }
    }
}

2. 可选:添加自动修复功能

如果想给用户提供一键修复的选项(比如自动去掉下划线),可以写一个CodeFixProvider

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(NoUnderscorePrefixMethodCodeFixProvider)), Shared]
public class NoUnderscorePrefixMethodCodeFixProvider : CodeFixProvider
{
    // 指定当前修复器对应的诊断ID
    public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(NoUnderscorePrefixMethodAnalyzer.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 methodDeclaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<MethodDeclarationSyntax>().First();

        // 添加修复选项
        context.RegisterCodeFix(
            CodeAction.Create(
                title: "移除方法名的下划线前缀",
                createChangedDocument: c => RemoveUnderscorePrefixAsync(context.Document, methodDeclaration, c),
                equivalenceKey: nameof(NoUnderscorePrefixMethodCodeFixProvider)),
            diagnostic);
    }

    // 执行修复的具体逻辑
    private async Task<Document> RemoveUnderscorePrefixAsync(Document document, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken)
    {
        var newMethodName = methodDeclaration.Identifier.Text.TrimStart('_');
        var newMethodDeclaration = methodDeclaration.WithIdentifier(SyntaxFactory.Identifier(newMethodName))
            .WithLeadingTrivia(methodDeclaration.Identifier.LeadingTrivia)
            .WithTrailingTrivia(methodDeclaration.Identifier.TrailingTrivia);

        var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
        var newRoot = root.ReplaceNode(methodDeclaration, newMethodDeclaration);

        return document.WithSyntaxRoot(newRoot);
    }
}

三、打包成NuGet包(供Core 2.0项目引用)

要让自定义规则像FxCopAnalyzers一样通过NuGet安装,需要修改类库项目的.csproj文件:

<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
  <IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>

<ItemGroup>
  <!-- 把编译后的分析器DLL打包到NuGet的指定目录 -->
  <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/csharp" />
</ItemGroup>

配置好后右键项目选择「打包」,就能生成对应的.nupkg文件了。

四、在Core 2.0项目中使用

  • 把生成的NuGet包添加到本地NuGet源,然后在Core 2.0项目中安装这个包。
  • 打开项目的「Analyzer」节点,就能看到你的自定义规则。当代码中出现以下划线开头的方法时,会触发警告,还能点击修复按钮自动移除下划线。

小提示

  • Core 2.0项目一定要确保分析器基于.NET Standard 2.0,否则会有兼容性问题。
  • 如果需要更复杂的规则(比如分析方法的访问权限、返回类型等语义信息),可以用context.RegisterSymbolAction来分析IMethodSymbol,能获取更多代码上下文。

内容的提问来源于stack exchange,提问作者Agrawal Shraddha

火山引擎 最新活动