簡體   English   中英

SyntaxNode.ContainsDiagnostics無法與您自己的診斷一起使用?

[英]SyntaxNode.ContainsDiagnostics not working with your own diagnostics?

我正在嘗試編寫一個分析器,以防止用戶提供自動提供的參數(例如:使用[CallerMemberName]的編譯器),並且當您提供了不應提供的參數時,我希望分析器使您出錯。告訴不應該提供的參數我創建了一個屬性: DontProvideAttribute )。

事情是這樣的,自動提供的參數必須是可選的(否則,用戶提供的值將覆蓋自動提供的參數),因此我進行了第二次分析,以防止用戶對非可選參數使用[DontProvide]

隨之而來的問題是,我只希望在參數聲明沒有[DontProvide] should only be used on optional parameters方法調用錯誤,而該錯誤[DontProvide] should only be used on optional parameters error

foreach (SyntaxReference parameterDefinition in parameter.DeclaringSyntaxReferences)
{
    if (parameterDefinition.GetSyntax().ContainsDiagnostics)
    {
        return;
    }
}

應該完成此操作,但似乎不考慮您報告的診斷信息。

我試過的

-在方法調用之前更改診斷順序以對聲明進行分析

-使用.GetDiagnostics().Count() > 0代替

-更改分析文檔中文本的順序以使方法聲明位於方法調用之上

分析儀:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSymbolAction(AnalyzeParametersDeclaration, SymbolKind.Parameter);
    context.RegisterOperationAction(AnalyzeArguments, OperationKind.Argument);
}

private void AnalyzeArguments(OperationAnalysisContext context)
{
    IArgumentOperation reference = (IArgumentOperation)context.Operation;
    IParameterSymbol parameter = reference.Parameter;
    foreach (SyntaxReference parameterDefinition in parameter.DeclaringSyntaxReferences)
    {
        if (parameterDefinition.GetSyntax().ContainsDiagnostics)
            return;
    }
    foreach (AttributeData attribute in parameter.GetAttributes())
    {
        if (attribute.AttributeClass.Name == "DontProvideAttribute")
        {
            context.ReportDiagnostic(Diagnostic.Create(DontProvide, reference.Syntax.GetLocation(), parameter.Name));
        }
    }
}

private void AnalyzeParametersDeclaration(SymbolAnalysisContext context)
{
    IParameterSymbol parameter = (IParameterSymbol)context.Symbol;
    if (parameter.GetAttributes().Any(a => a.AttributeClass.Name == "DontProvideAttribute") && !parameter.IsOptional)
    {
        context.ReportDiagnostic(Diagnostic.Create(DontProvideOnlyForOptional, parameter.Locations[0]))         
    }
}

一些測試代碼以供分析:

using System;

namespace test
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            MyClass.MyMethod(null);
        }
    }

    internal class MyClass
    {
        public static void MyMethod([DontProvide] object parameter)
        {

        }
    }

    [AttributeUsage(AttributeTargets.Parameter)]
    public class DontProvideAttribute : Attribute
    {

    } 
}

PS :編譯器可能會告訴您,不支持與SymbolKind.Parameter使用的context.RegisterSymbolAction() ,這是錯誤的( 在此處查看更多信息

這里的討論和@Kris Vandermotten的評論

ContainsDiagnostics僅用於語法診斷(即,語法樹內部的診斷),不適用於后續遍歷報告的診斷(即,語義診斷或您自己的分析器診斷)。 這就是為什么:由於roslyn能夠分叉和推測事物,因此特定的語法樹可能包含在許多不同的語義上下文中,因此在一個上下文中該語法可能在語義上是正確的,而在另一上下文中則不是這樣,診斷信息不會存儲在樹本身上。

實際上,對於我而言,解決方案非常簡單:我只需要刪除

foreach (SyntaxReference parameterDefinition in parameter.DeclaringSyntaxReferences)
{
    if (parameterDefinition.GetSyntax().ContainsDiagnostics)
        return;
}

並在if語句中添加&& parameter.IsOptionnal

foreach (AttributeData attribute in parameter.GetAttributes())
{
    if (attribute.AttributeClass.Name == "DontProvideAttribute")
    {
        context.ReportDiagnostic(Diagnostic.Create(DontProvide, reference.Syntax.GetLocation(), parameter.Name));
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM