我想制作一个分析器,该代码将为每个出现在代码中的某个特定成员发出一条消息(严重性=信息)。这模仿[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));
}
}
}
可正常工作,但对此我报告的诊断是位置还不完全正确,因为它不仅是调用,而且还是尾随的空白。这是为什么?
你有警告错误吗? –