You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Roslyn代码分析器检测Web API控制器方法缺失的Custom属性

解决方案:检测Web API控制器方法缺失Custom属性的Roslyn分析器

一、完善分析器核心判断逻辑

需要在AnalyzeNode方法中完成两个关键校验:确认方法属于Web API控制器类、检查方法是否已标记Custom属性。修改后的完整代码如下:

private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
    var methodDeclaration = (MethodDeclarationSyntax)context.Node;
    
    // 获取方法的语义符号,用于后续类型和属性的语义校验
    var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);
    if (methodSymbol == null) return;

    // 判断方法所在类是否为Web API控制器(兼容ASP.NET Core的ControllerBase和传统Web API的ApiController)
    var containingType = methodSymbol.ContainingType;
    var isApiController = containingType.AllInterfaces.Any(i => i.Name == "IApiController") || 
                          containingType.BaseType?.Name is "ControllerBase" or "ApiController";
    if (!isApiController) return;

    // 检查方法是否已包含Custom属性(用语义分析兼容属性别名、全名称写法)
    var hasCustomAttribute = methodSymbol.GetAttributes().Any(attr => 
        attr.AttributeClass?.Name is "CustomAttribute" or "Custom");
    if (hasCustomAttribute) return;

    // 触发诊断提示
    var diagnostic = Diagnostic.Create(
        Rule, // 提前定义的DiagnosticRule实例
        methodDeclaration.Identifier.GetLocation(),
        methodDeclaration.Identifier.Text);
    context.ReportDiagnostic(diagnostic);
}

二、实现代码修复提供者

为缺失属性的方法自动添加[Custom]的代码修复逻辑:

public sealed class CustomAttributeCodeFixProvider : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds 
        => ImmutableArray.Create(YourAnalyzer.DiagnosticId); // 对应分析器的诊断ID

    public override FixAllProvider GetFixAllProvider() 
        => WellKnownFixAllProviders.BatchFixer;

    public 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: "添加Custom属性",
                createChangedDocument: c => AddCustomAttributeAsync(context.Document, methodDeclaration, c),
                equivalenceKey: "AddCustomAttribute"),
            diagnostic);
    }

    private async Task<Document> AddCustomAttributeAsync(
        Document document, 
        MethodDeclarationSyntax methodDeclaration, 
        CancellationToken cancellationToken)
    {
        // 创建Custom属性语法节点
        var customAttribute = SyntaxFactory.Attribute(
            SyntaxFactory.IdentifierName("Custom"))
            .WithArgumentList(SyntaxFactory.AttributeArgumentList());

        // 将属性添加到方法的属性列表(无属性列表则新建)
        var newMethodDeclaration = methodDeclaration.AttributeLists.Any()
            ? methodDeclaration.WithAttributeLists(
                methodDeclaration.AttributeLists.Insert(0, 
                    SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(customAttribute))))
            : methodDeclaration.WithAttributeLists(
                SyntaxFactory.SingletonList(SyntaxFactory.AttributeList(
                    SyntaxFactory.SingletonSeparatedList(customAttribute))));

        // 更新语法树并返回新文档
        var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
        var newRoot = root.ReplaceNode(methodDeclaration, newMethodDeclaration);
        return document.WithSyntaxRoot(newRoot);
    }
}

关键补充说明

  • 语义分析优先:用符号校验替代纯语法检查,能兼容using Custom = MyNamespace.MyCustomAttribute别名、属性全名称等场景
  • 诊断规则定义:需提前创建DiagnosticRule实例,示例如下:
    public static readonly DiagnosticRule Rule = new DiagnosticRule(
        id: "MY001",
        title: "Web API方法缺失Custom属性",
        messageFormat: "方法 '{0}' 缺少Custom属性",
        category: "Usage",
        defaultSeverity: DiagnosticSeverity.Warning,
        isEnabledByDefault: true);
    

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:45:34