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); }
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); }
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); }
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 }); } }
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); }