我想製作一個分析器,該代碼將爲每個出現在代碼中的某個特定成員發出一條消息(嚴重性=信息)。這模仿[Obsolete(...)]
的行爲,但只是拋出一條消息。查找引用某個特定屬性的符號的所有引用
屬性定義會是這樣的
public class ThrowsMessageAttribute : Attribute
{
// ...
}
我想拋出一個消息,然後將它歸因員:
public class Foo
{
[ThrowsMessage]
public void Bar() { }
}
對於每個Bar()
我在代碼中使用,我現在會在錯誤列表的消息選項卡中獲得一個條目。
我的出發點是一個空DiagnosticAnalyzer類:
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class MyDiagnosticAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Info, true, Description, HelpLink);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
// how to go on from here?
}
}
具有AnalysisContext
我怎麼前進?我需要在ordner中實現哪些邏輯以找到所有以特殊方式歸因的符號參考?
也許我完全在錯誤的軌道上,解決這個問題不應該通過分析儀來完成。還有哪些其他選項可用?
編輯
基於@陶的建議,我得到了它與下面的代碼幾乎工作:
public override void Initialize(AnalysisContext context)
{
context.RegisterSemanticModelAction(Analyze);
}
private static void Analyze(SemanticModelAnalysisContext context)
{
var semanticModel = context.SemanticModel;
var step2 = GetSymbolsOfAttributedMethods(semanticModel, "ThrowsMessage");
Step3(context, list2, semanticModel);
}
private static List<ISymbol> GetSymbolsOfAttributedMethods(SemanticModel semanticModel, string attributeName)
{
var methodDeclarations = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>();
var symbolList = new List<ISymbol>();
foreach (var declaration in methodDeclarations)
{
foreach (var attributeList in declaration.AttributeLists)
{
if (attributeList.Attributes.Any(a => (a.Name as IdentifierNameSyntax)?.Identifier.Text == attributeName))
{
symbolList.Add(semanticModel.GetDeclaredSymbol(declaration));
break;
}
}
}
return symbolList;
}
private static void Step3(SemanticModelAnalysisContext context, List<ISymbol> attributedSymbols, SemanticModel semanticModel)
{
var invocationExpressions = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>();
foreach (var invocation in invocationExpressions)
{
var symbol = semanticModel.GetSymbolInfo(invocation).Symbol;
if (attributedSymbols.Contains(symbol))
{
var l = Location.Create(context.SemanticModel.SyntaxTree, invocation.FullSpan);
context.ReportDiagnostic(Diagnostic.Create(Rule, l));
}
}
}
可正常工作,但對此我報告的診斷是位置還不完全正確,因爲它不僅是調用,而且還是尾隨的空白。這是爲什麼?
你有警告錯誤嗎? –