Exemplo n.º 1
0
        private static bool AnalyzeIdentifierThread(SyntaxNode method, CompilationAnalysisContext context, SemanticModel semanticModel)
        {
            var diagnosedIssue = false;

            foreach (SyntaxNode descendant in method.DescendantNodes())
            {
                if (descendant is IdentifierNameSyntax identifierName)
                {
                    var identifierText = identifierName.Identifier.ValueText;
                    if (identifierText == "Start")
                    {
                        var memberAccessExpression = identifierName.Parent;
                        if (SyntaxNodeUtils.TryGetISymbol(semanticModel, memberAccessExpression, out ISymbol memberSymbol))
                        {
                            if (memberSymbol != null && memberSymbol.ToString().StartsWith("System.Threading.Thread"))
                            {
                                var diagnostic = Diagnostic.Create(Rule, memberAccessExpression.GetLocation(), memberAccessExpression);

                                context.ReportDiagnostic(diagnostic);

                                diagnosedIssue = true;
                            }
                        }
                    }
                }
            }

            return(diagnosedIssue);
        }
Exemplo n.º 2
0
        private static bool TryGetDurableActivityContextExpression(SemanticModel semanticModel, SyntaxNode node, out SyntaxNode durableContextExpression)
        {
            if (SyntaxNodeUtils.TryGetMethodDeclaration(node, out SyntaxNode methodDeclaration))
            {
                var memberAccessExpressionList = methodDeclaration.DescendantNodes().Where(x => x.IsKind(SyntaxKind.SimpleMemberAccessExpression));
                foreach (var memberAccessExpression in memberAccessExpressionList)
                {
                    var identifierName = memberAccessExpression.ChildNodes().FirstOrDefault(x => x.IsKind(SyntaxKind.IdentifierName));
                    if (identifierName != null)
                    {
                        if (SyntaxNodeUtils.TryGetITypeSymbol(semanticModel, identifierName, out ITypeSymbol typeSymbol))
                        {
                            if (SyntaxNodeUtils.IsDurableActivityContext(typeSymbol))
                            {
                                durableContextExpression = memberAccessExpression;
                                return(true);
                            }
                        }
                    }
                }
            }

            durableContextExpression = null;
            return(false);
        }
Exemplo n.º 3
0
        private static bool HasExecuteSynchronously(SyntaxNode node)
        {
            if (!SyntaxNodeUtils.TryGetInvocationExpression(node, out SyntaxNode invocationExpression))
            {
                return(false);
            }

            var argumentList = invocationExpression.ChildNodes().FirstOrDefault(x => x.IsKind(SyntaxKind.ArgumentList));

            if (argumentList != null)
            {
                foreach (SyntaxNode argument in argumentList.ChildNodes())
                {
                    var simpleMemberAccessExpression = argument.ChildNodes().FirstOrDefault(x => x.IsKind(SyntaxKind.SimpleMemberAccessExpression));

                    if (simpleMemberAccessExpression != null)
                    {
                        var identifierNames = simpleMemberAccessExpression.ChildNodes().Where(x => x.IsKind(SyntaxKind.IdentifierName));
                        foreach (SyntaxNode identifier in identifierNames)
                        {
                            if (identifier.ToString().Equals("ExecuteSynchronously"))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
        private static bool TryGetInputNodeFromCallActivityInvocation(SemanticModel semanticModel, InvocationExpressionSyntax invocationExpression, out SyntaxNode inputNode)
        {
            // If method invocation is a custom CallActivity extension method defined in user code
            if (SyntaxNodeUtils.TryGetDeclaredSyntaxNode(semanticModel, invocationExpression, out SyntaxNode declaration))
            {
                if (TryGetSpecificParameterIndex(declaration, "object input", out int inputParameterIndex))
                {
                    if (TryGetInvocationArguments(invocationExpression, out IEnumerable <ArgumentSyntax> arguments))
                    {
                        var argumentNode = arguments.ElementAt(inputParameterIndex);
                        inputNode = argumentNode.ChildNodes().First();
                        return(true);
                    }
                }
            }
            // else assume CallActivity is a DurableFunctions method
            else
            {
                if (TryGetInvocationArguments(invocationExpression, out IEnumerable <ArgumentSyntax> arguments))
                {
                    // Input node is currently the last argument on CallActivity* methods. If this is changed, this will not be sufficient to
                    // determine which argument is meant to represent the input.
                    var argumentNode = arguments.Last();
                    inputNode = argumentNode.ChildNodes().First();
                    return(true);
                }
            }

            inputNode = null;
            return(false);
        }
Exemplo n.º 5
0
        public void FindActivityFunction(SyntaxNodeAnalysisContext context)
        {
            var semanticModel = context.SemanticModel;

            if (context.Node is AttributeSyntax attribute &&
                SyntaxNodeUtils.IsActivityTriggerAttribute(attribute))
            {
                if (!SyntaxNodeUtils.TryGetFunctionName(semanticModel, attribute, out string functionName))
                {
                    //Do not store ActivityFunctionDefinition if there is no function name
                    return;
                }

                if (!SyntaxNodeUtils.TryGetMethodReturnTypeNode(attribute, out SyntaxNode returnTypeNode))
                {
                    //Do not store ActivityFunctionDefinition if there is no return type
                    return;
                }

                SyntaxNodeUtils.TryGetITypeSymbol(semanticModel, returnTypeNode, out ITypeSymbol returnType);

                SyntaxNodeUtils.TryGetParameterNodeNextToAttribute(context, attribute, out SyntaxNode parameterNode);

                TryGetDefinitionInputType(semanticModel, parameterNode, out ITypeSymbol inputType);

                availableFunctions.Add(new ActivityFunctionDefinition
                {
                    FunctionName   = functionName,
                    ParameterNode  = parameterNode,
                    InputType      = inputType,
                    ReturnTypeNode = returnTypeNode,
                    ReturnType     = returnType
                });
            }
        }
Exemplo n.º 6
0
        public void FindActivityCall(SyntaxNodeAnalysisContext context)
        {
            SetSemanticModel(context);

            var semanticModel = context.SemanticModel;

            if (context.Node is InvocationExpressionSyntax invocationExpression &&
                SyntaxNodeUtils.IsInsideFunction(semanticModel, invocationExpression) &&
                IsActivityInvocation(invocationExpression))
            {
                if (!TryGetFunctionNameFromActivityInvocation(invocationExpression, out SyntaxNode functionNameNode, out string functionName))
                {
                    //Do not store ActivityFunctionCall if there is no function name
                    return;
                }

                SyntaxNodeUtils.TryGetTypeArgumentIdentifier((MemberAccessExpressionSyntax)invocationExpression.Expression, out SyntaxNode returnTypeNode);

                TryGetInputNodeFromCallActivityInvocation(invocationExpression, out SyntaxNode inputNode);

                calledFunctions.Add(new ActivityFunctionCall
                {
                    FunctionName         = functionName,
                    NameNode             = functionNameNode,
                    ArgumentNode         = inputNode,
                    ReturnTypeNode       = returnTypeNode,
                    InvocationExpression = invocationExpression
                });
            }
        }
        private static bool TryGetInputFromDurableContextCall(SemanticModel semanticModel, SyntaxNode definitionInput, out SyntaxNode inputFromContext)
        {
            if (SyntaxNodeUtils.TryGetMethodDeclaration(definitionInput, out SyntaxNode methodDeclaration))
            {
                var memberAccessExpressionList = methodDeclaration.DescendantNodes().Where(x => x.IsKind(SyntaxKind.SimpleMemberAccessExpression));
                foreach (var memberAccessExpression in memberAccessExpressionList)
                {
                    var identifierName = memberAccessExpression.ChildNodes().Where(x => x.IsKind(SyntaxKind.IdentifierName)).FirstOrDefault();
                    if (identifierName != null)
                    {
                        var identifierNameType = SyntaxNodeUtils.GetSyntaxTreeSemanticModel(semanticModel, identifierName).GetTypeInfo(identifierName).Type.Name;
                        if (identifierNameType.Equals("IDurableActivityContext") || identifierNameType.Equals("DurableActivityContext") || identifierNameType.Equals("DurableActivityContextBase"))
                        {
                            var genericName = memberAccessExpression.ChildNodes().Where(x => x.IsKind(SyntaxKind.GenericName)).FirstOrDefault();
                            if (genericName != null)
                            {
                                var typeArgumentList = genericName.ChildNodes().Where(x => x.IsKind(SyntaxKind.TypeArgumentList)).FirstOrDefault();
                                if (typeArgumentList != null)
                                {
                                    inputFromContext = typeArgumentList.ChildNodes().First();
                                    return(true);
                                }
                            }
                        }
                    }
                }
            }

            inputFromContext = null;
            return(false);
        }
        public static void ReportProblems(
            CompilationAnalysisContext context,
            SemanticModel semanticModel,
            IEnumerable <ActivityFunctionDefinition> availableFunctions,
            IEnumerable <ActivityFunctionCall> calledFunctions)
        {
            foreach (var activityInvocation in calledFunctions)
            {
                var functionDefinition = availableFunctions.Where(x => x.FunctionName == activityInvocation.Name).FirstOrDefault();
                if (functionDefinition != null)
                {
                    var isInvokedWithNonNullInput   = TryGetInvocationInputType(semanticModel, activityInvocation, out ITypeSymbol invocationInputType);
                    var functionDefinitionUsesInput = TryGetDefinitionInputType(semanticModel, functionDefinition, out ITypeSymbol definitionInputType);

                    if (!functionDefinitionUsesInput)
                    {
                        if (isInvokedWithNonNullInput)
                        {
                            var diagnostic = Diagnostic.Create(InputNotUsedRule, activityInvocation.ParameterNode.GetLocation(), activityInvocation.Name);

                            context.ReportDiagnostic(diagnostic);
                        }
                    }
                    else if (!SyntaxNodeUtils.InputMatchesOrCompatibleType(invocationInputType, definitionInputType))
                    {
                        var invocationTypeName = SyntaxNodeUtils.GetQualifiedTypeName(invocationInputType);
                        var definitionTypeName = SyntaxNodeUtils.GetQualifiedTypeName(definitionInputType);

                        var diagnostic = Diagnostic.Create(MismatchRule, activityInvocation.ParameterNode.GetLocation(), activityInvocation.Name, definitionTypeName, invocationTypeName);

                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
        }
        internal static bool RegisterDiagnostic(SyntaxNode method, CompilationAnalysisContext context, SemanticModel semanticModel)
        {
            var diagnosedIssue = false;

            foreach (SyntaxNode descendant in method.DescendantNodes())
            {
                if (descendant is IdentifierNameSyntax identifierName)
                {
                    if (identifierName.Identifier.ValueText == "NewGuid")
                    {
                        var memberAccessExpression = identifierName.Parent;
                        var invocationExpression   = memberAccessExpression.Parent;
                        var memberSymbol           = SyntaxNodeUtils.GetSyntaxTreeSemanticModel(semanticModel, memberAccessExpression).GetSymbolInfo(memberAccessExpression).Symbol;

                        if (memberSymbol != null && memberSymbol.ToString().StartsWith("System.Guid"))
                        {
                            var diagnostic = Diagnostic.Create(Rule, invocationExpression.GetLocation(), memberAccessExpression);

                            context.ReportDiagnostic(diagnostic);

                            diagnosedIssue = true;
                        }
                    }
                }
            }

            return(diagnosedIssue);
        }
        private static bool TryGetInvocationInputType(SemanticModel semanticModel, ActivityFunctionCall activityInvocation, out ITypeSymbol invocationInputType)
        {
            var invocationInput = activityInvocation.ParameterNode;

            invocationInputType = SyntaxNodeUtils.GetSyntaxTreeSemanticModel(semanticModel, invocationInput).GetTypeInfo(invocationInput).Type;

            return(invocationInputType != null);
        }