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);
                }
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
                    }
                }
            }
        }
예제 #5
0
 public void RegisterDiagnostics(CompilationAnalysisContext context, MethodInformation methodInformation)
 {
     RegisterDiagnosticsOnInvocations(context, methodInformation, methodsVisited);
 }