[英]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.