如何在C# Roslyn分析器中查找Update方法内的GetComponent调用
Roslyn分析器实现Update方法内GetComponent调用检查
需求
需要查找所有Update()方法声明的实例,检查其方法体内是否调用了GetComponent方法。目前已实现Update方法声明的定位,但不清楚后续检查内部调用的逻辑。
已有基础代码
分析器初始化代码
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSyntaxNodeAction(Analyze, SyntaxKind.MethodDeclaration); }
Update方法定位代码
private static void Analyze(SyntaxNodeAnalysisContext context) { if (context.Node is not MethodDeclarationSyntax method) return; var symbolname = context.SemanticModel.GetDeclaredSymbol(method); var node = context.Node; if (symbolname.Name != "Update") return; context.ReportDiagnostic(Diagnostic.Create(Rule, node.GetLocation())); }
语法树遍历逻辑
原定需要遍历的语法树路径为:MethodDeclaration -> Block -> ExpressionStatement -> InvocationExpression -> IdentifierToken
最终优化实现
后续发现从调用表达式向上溯源的实现方式更简单,直接监听调用表达式节点,先判断是否为GetComponent调用,再向上溯源是否位于Update方法内,完整实现代码如下:
private static void Analyze(SyntaxNodeAnalysisContext context) { var invocation = (InvocationExpressionSyntax)context.Node; var name = invocation.GetMethodNameSyntax(); if (name == null) return; if (name.Identifier.Text != "GetComponent") return; var parent = invocation.Expression.FirstAncestorOrSelf<MethodDeclarationSyntax>(); var classDeclaration = parent.FirstAncestorOrSelf<ClassDeclarationSyntax>(); if (classDeclaration == null) return; var symbolname = context.SemanticModel.GetDeclaredSymbol(parent); if (symbolname.Name != "Update" ) return; context.ReportDiagnostic(Diagnostic.Create(Rule, invocation.GetLocation())); }
该实现相比原思路的优势是不需要手动遍历Update方法内的所有语法节点,且可以直接定位到GetComponent的调用位置上报诊断,定位精度更高。
内容的提问来源于stack exchange,提问作者Jurg Puila
相关产品推荐
相关产品推荐

