private void FindInvokedMethods(SemanticModel semanticModel, MethodInformation parentMethodInformation) { var parentDeclaration = parentMethodInformation.Declaration; var invocationExpressions = parentDeclaration.DescendantNodes().OfType <InvocationExpressionSyntax>(); foreach (var invocation in invocationExpressions) { if (SyntaxNodeUtils.TryGetDeclaredSyntaxNode(semanticModel, invocation, out SyntaxNode invokedMethodDeclaration) && invokedMethodDeclaration is MethodDeclarationSyntax && SyntaxNodeUtils.TryGetISymbol(semanticModel, invocation, out ISymbol invokedSymbol)) { if (this.orchestratorMethodDeclarations.TryGetValue(invokedSymbol, out MethodInformation existingMethodInformation)) { existingMethodInformation.Invocations.Add(invocation); if (!existingMethodInformation.Equals(parentMethodInformation)) { existingMethodInformation.Parents.Add(parentMethodInformation); } } else { var invokedMethodInformation = new MethodInformation() { SemanticModel = semanticModel, Declaration = invokedMethodDeclaration, DeclarationSymbol = invokedSymbol, Invocations = new List <InvocationExpressionSyntax>() { invocation }, Parents = new HashSet <MethodInformation>(new List <MethodInformation>() { parentMethodInformation }), }; this.orchestratorMethodDeclarations.Add(invokedSymbol, invokedMethodInformation); FindInvokedMethods(semanticModel, invokedMethodInformation); } } } }
/// <summary> /// Method used to collect orchestrator methods and methods used in orchestrators that are defined in /// the solution. Call this on a DiagnosticAnalyzer by registering actions on SyntaxKind.MethodDeclaration. /// </summary> /// <param name="context"></param> public void FindOrchestratorMethods(SyntaxNodeAnalysisContext context) { var semanticModel = context.SemanticModel; var symbol = context.ContainingSymbol; if (symbol != null && context.Node is MethodDeclarationSyntax declaration && SyntaxNodeUtils.IsInsideOrchestratorFunction(semanticModel, declaration)) { var methodInformation = new MethodInformation() { SemanticModel = semanticModel, Declaration = declaration, DeclarationSymbol = symbol, }; if (!this.orchestratorMethodDeclarations.ContainsKey(symbol)) { this.orchestratorMethodDeclarations.Add(symbol, methodInformation); this.FindInvokedMethods(semanticModel, methodInformation); } } }
private void RegisterDiagnosticsOnInvocations(CompilationAnalysisContext context, MethodInformation methodInformation, HashSet <MethodInformation> methodsVisited) { methodsVisited.Add(methodInformation); var methodInvocations = methodInformation?.Invocations; if (methodInvocations != null && methodInvocations.Any()) { foreach (InvocationExpressionSyntax invocation in methodInvocations) { var diagnostic = Diagnostic.Create(Rule, invocation.GetLocation(), invocation); context.ReportDiagnostic(diagnostic); } RegisterDiagnosticsOnParents(context, methodInformation, methodsVisited); } }
private void RegisterDiagnosticsOnParents(CompilationAnalysisContext context, MethodInformation methodInformation, HashSet <MethodInformation> methodsVisited) { var parents = methodInformation.Parents; if (parents != null && parents.Any()) { foreach (MethodInformation parent in parents) { if (!methodsVisited.Contains(parent)) { RegisterDiagnosticsOnInvocations(context, parent, methodsVisited); } } } }
public void RegisterDiagnostics(CompilationAnalysisContext context, MethodInformation methodInformation) { RegisterDiagnosticsOnInvocations(context, methodInformation, methodsVisited); }