public override TAbstractAnalysisValue VisitAwait(IAwaitOperation operation, object argument) { var value = base.VisitAwait(operation, argument); PointsToAbstractValue instanceLocation = GetPointsToAbstractValue(operation); return(HandleInstanceCreation(operation, instanceLocation, value)); }
private static bool ShouldAnalyze( IAwaitOperation awaitOperation, IMethodSymbol configureAwaitMethod, IMethodSymbol genericConfigureAwaitMethod, INamedTypeSymbol streamType, out IMethodSymbol?actualMethod) { actualMethod = null; // The await should have a known operation child, check its kind if (!(awaitOperation.Operation is IInvocationOperation invocation)) { return(false); } IMethodSymbol method = invocation.TargetMethod; // Check if the child operation of the await is ConfigureAwait // in which case we should analyze the grandchild operation if (method.OriginalDefinition.Equals(configureAwaitMethod) || method.OriginalDefinition.Equals(genericConfigureAwaitMethod)) { if (invocation.Instance is IInvocationOperation instanceInvocation) { method = instanceInvocation.TargetMethod; } else { return(false); } } // Verify if the current method's type is or inherits from Stream return(IsDefinedBy(method, streamType, out actualMethod)); }
private static void AnalyzeOperation(OperationAnalysisContext context, ImmutableArray <INamedTypeSymbol> taskTypes) { IAwaitOperation awaitExpression = context.Operation as IAwaitOperation; // Get the type of the expression being awaited and check it's a task type. ITypeSymbol typeOfAwaitedExpression = awaitExpression?.Operation?.Type; if (typeOfAwaitedExpression != null && taskTypes.Contains(typeOfAwaitedExpression.OriginalDefinition)) { context.ReportDiagnostic(awaitExpression.Operation.Syntax.CreateDiagnostic(Rule)); } }
private static void AnalyzeAwait( OperationAnalysisContext context, ImmutableHashSet <INamedTypeSymbol> configuredTaskTypes, IAwaitOperation operation ) { IOperation rhs = operation.Operation; ITypeSymbol awaitedType = rhs.Type.OriginalDefinition; if (configuredTaskTypes.Contains(awaitedType)) { return; } context.ReportDiagnostic(Diagnostic.Create( Diagnostics.AwaitedTaskNotConfigured, operation.Syntax.GetLocation() )); }
private void AnalyzeCompilationStart(CompilationStartAnalysisContext context) { // Find the essential type for this analysis if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIOStream, out INamedTypeSymbol? streamType)) { return; } // Find the types for the rule message, available since .NET Standard 2.1 if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemReadOnlyMemory1, out INamedTypeSymbol? readOnlyMemoryType)) { return; } if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemMemory1, out INamedTypeSymbol? memoryType)) { return; } // Find the additional types for this analysis if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingCancellationToken, out INamedTypeSymbol? cancellationTokenType)) { return; } INamedTypeSymbol byteType = context.Compilation.GetSpecialType(SpecialType.System_Byte); if (byteType == null) { return; } INamedTypeSymbol int32Type = context.Compilation.GetSpecialType(SpecialType.System_Int32); if (int32Type == null) { return; } // Create the arrays with the exact parameter order of the undesired methods var undesiredParameters = new[] { ParameterInfo.GetParameterInfo(byteType, isArray: true, arrayRank: 1), // byte[] buffer ParameterInfo.GetParameterInfo(int32Type), // int offset ParameterInfo.GetParameterInfo(int32Type), // int count }; var undesiredParametersWithCancellationToken = new[] { ParameterInfo.GetParameterInfo(byteType, isArray: true, arrayRank: 1), ParameterInfo.GetParameterInfo(int32Type), ParameterInfo.GetParameterInfo(int32Type), ParameterInfo.GetParameterInfo(cancellationTokenType) }; // Retrieve the ReadAsync/WriteSync methods available in Stream IEnumerable <IMethodSymbol> readAsyncMethodGroup = streamType.GetMembers("ReadAsync").OfType <IMethodSymbol>(); IEnumerable <IMethodSymbol> writeAsyncMethodGroup = streamType.GetMembers("WriteAsync").OfType <IMethodSymbol>(); // Retrieve the undesired methods IMethodSymbol?undesiredReadAsyncMethod = readAsyncMethodGroup.GetFirstOrDefaultMemberWithParameterInfos(undesiredParameters); if (undesiredReadAsyncMethod == null) { return; } IMethodSymbol?undesiredWriteAsyncMethod = writeAsyncMethodGroup.GetFirstOrDefaultMemberWithParameterInfos(undesiredParameters); if (undesiredWriteAsyncMethod == null) { return; } IMethodSymbol?undesiredReadAsyncMethodWithCancellationToken = readAsyncMethodGroup.GetFirstOrDefaultMemberWithParameterInfos(undesiredParametersWithCancellationToken); if (undesiredReadAsyncMethodWithCancellationToken == null) { return; } IMethodSymbol?undesiredWriteAsyncMethodWithCancellationToken = writeAsyncMethodGroup.GetFirstOrDefaultMemberWithParameterInfos(undesiredParametersWithCancellationToken); if (undesiredWriteAsyncMethodWithCancellationToken == null) { return; } // Retrieve the preferred methods, which are used for constructing the rule message IMethodSymbol?preferredReadAsyncMethod = readAsyncMethodGroup.FirstOrDefault(x => x.Parameters.Count() == 2 && x.Parameters[0].Type is INamedTypeSymbol type && type.ConstructedFrom.Equals(memoryType)); if (preferredReadAsyncMethod == null) { return; } IMethodSymbol?preferredWriteAsyncMethod = writeAsyncMethodGroup.FirstOrDefault(x => x.Parameters.Count() == 2 && x.Parameters[0].Type is INamedTypeSymbol type && type.ConstructedFrom.Equals(readOnlyMemoryType)); if (preferredWriteAsyncMethod == null) { return; } // Retrieve the ConfigureAwait methods that could also be detected: // - The undesired WriteAsync methods return a Task // - The preferred WriteAsync method returns a ValueTask // - The undesired ReadAsync methods return a Task<int> // - The preferred ReadAsync method returns a ValueTask<int> if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask, out INamedTypeSymbol? taskType)) { return; } if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask1, out INamedTypeSymbol? genericTaskType)) { return; } IMethodSymbol?configureAwaitMethod = taskType.GetMembers("ConfigureAwait").OfType <IMethodSymbol>().FirstOrDefault(); if (configureAwaitMethod == null) { return; } IMethodSymbol?genericConfigureAwaitMethod = genericTaskType.GetMembers("ConfigureAwait").OfType <IMethodSymbol>().FirstOrDefault(); if (genericConfigureAwaitMethod == null) { return; } context.RegisterOperationAction(context => { IAwaitOperation awaitOperation = (IAwaitOperation)context.Operation; if (ShouldAnalyze( awaitOperation, configureAwaitMethod, genericConfigureAwaitMethod, streamType, out IInvocationOperation? invocation, out IMethodSymbol? method) && invocation != null && method != null) { DiagnosticDescriptor rule; string ruleMessageMethod; string ruleMessagePreferredMethod; // Verify if the method is an undesired Async overload if (method.Equals(undesiredReadAsyncMethod) || method.Equals(undesiredReadAsyncMethodWithCancellationToken)) { rule = PreferStreamReadAsyncMemoryOverloadsRule; ruleMessageMethod = undesiredReadAsyncMethod.Name; ruleMessagePreferredMethod = preferredReadAsyncMethod.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat); } else if (method.Equals(undesiredWriteAsyncMethod) || method.Equals(undesiredWriteAsyncMethodWithCancellationToken)) { rule = PreferStreamWriteAsyncMemoryOverloadsRule; ruleMessageMethod = undesiredWriteAsyncMethod.Name; ruleMessagePreferredMethod = preferredWriteAsyncMethod.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat); } else { // Prevent use of unassigned variables error return; } context.ReportDiagnostic(invocation.CreateDiagnostic(rule, ruleMessageMethod, ruleMessagePreferredMethod)); } }, OperationKind.Await); }
public override PointsToAbstractValue VisitAwait(IAwaitOperation operation, object argument) { var _ = base.VisitAwait(operation, argument); return(PointsToAbstractValue.Unknown); }
public override NullAbstractValue VisitAwait(IAwaitOperation operation, object argument) { var _ = base.VisitAwait(operation, argument); return(NullAbstractValue.NotNull); }
public override IOperation VisitAwait(IAwaitOperation operation, object argument) { return(new AwaitExpression(Visit(operation.Operation), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)); }
public override void VisitAwait(IAwaitOperation operation) { Assert.Equal(OperationKind.Await, operation.Kind); Assert.Same(operation.Operation, operation.Children.Single()); }
public virtual void VisitAwait(IAwaitOperation operation) { DefaultVisit(operation); }
public override void VisitAwait([NotNull] IAwaitOperation operation) { base.VisitAwait(operation); }
private static AbstractExpression ReadAwait(IAwaitOperation op) { return(new AwaitExpression { Expression = ReadExpression(op.Operation) }); }
public override bool VisitAwait([NotNull] IAwaitOperation operation1, [CanBeNull] IOperation argument) { return(argument is IAwaitOperation operation2 && AreBaseOperationsEqual(operation1, operation2)); }
private void MethodSummary(ImmutableArray <BasicBlock> bb, List <string> sharedFields) { foreach (BasicBlock b in bb) { var a = b.GetType(); var c = b.BranchValue; if (b.Operations != null) { foreach (IOperation inst in b.Operations) { //Console.WriteLine($"inst.Syntax.ToSring() '{inst.Syntax.ToString()}'"); if (inst.Kind.ToString() == "ExpressionStatement") { IExpressionStatementOperation exprInst = (IExpressionStatementOperation)inst; if (exprInst.Operation != null) { //if (exprInst.Operation.Kind.ToString() == Kind = SimpleAssignment) //if (exprInst.Operation.Kind.ToString() == Kind = SimpleAssignment) if (exprInst.Operation.Kind.ToString() == "SimpleAssignment") { ISimpleAssignmentOperation assignInst = (ISimpleAssignmentOperation)exprInst.Operation; ProcessSimpleAssignmentOper(assignInst, sharedFields, inst); } else if (exprInst.Operation.Kind.ToString() == "Await") { IAwaitOperation awaitInst = (IAwaitOperation)exprInst.Operation; if (awaitInst.Operation.Kind.ToString() == "Invocation") { IInvocationOperation invocInst = (IInvocationOperation)awaitInst.Operation; string leftOperand = ""; ProcessInvocationOper(invocInst, inst, leftOperand); isAsync = true; //conflictUnit.Add(new Tuple<Accesses, string, IOperation>(Accesses.Invocation, "", inst)); } else if (awaitInst.Operation.Kind.ToString() == "Invalid") { ExpressionSyntax localvar = (ExpressionSyntax)awaitInst.Operation.Syntax; //var v = localvar.Kind().ToString(); if (localvar.Kind().ToString() == "InvocationExpression") { InvocationExpressionSyntax invocInst = (InvocationExpressionSyntax)localvar; string leftOperand = ""; ProcessInvocationExpr(invocInst, inst, leftOperand); isAsync = true; } } else if (awaitInst.Operation.Kind.ToString() == "IdentifierName") { //IdentifierNameSyntax indentInst = (IdentifierNameSyntax)awaitInst.Operation; isAsync = true; //rightOperand = indentInst.Identifier.ValueText; //awaitInvocRel.Add(new Tuple<string, string>(rightOperand, leftOperand)); } conflictUnit.Add(new Tuple <Accesses, string, IOperation>(Accesses.Await, invocSuffix, inst)); } else if (exprInst.Operation.Kind.ToString() == "Invocation") { IInvocationOperation invocInst = (IInvocationOperation)exprInst.Operation; string leftOperand = ""; ProcessInvocationOper(invocInst, inst, leftOperand); //conflictUnit.Add(new Tuple<Accesses, string, IOperation>(Accesses.Invocation, "", inst)); // invocSyntax = Regex.Replace(invocSyntax, @"(\w.*)(\.Wait\(\))$", "$1"); //invocSyntax = Regex.Replace(invocSyntax, @"(\w.*)(\.)(\w.*)$", "$3"); } } } else if (inst.Kind.ToString() == "SimpleAssignment") { ISimpleAssignmentOperation exprInst = (ISimpleAssignmentOperation)inst; ProcessSimpleAssignmentOper(exprInst, sharedFields, inst); } } } } }
public override Location VisitAwait([NotNull] IAwaitOperation operation, [CanBeNull] object argument) { var syntax = (AwaitExpressionSyntax)operation.Syntax; return(syntax.AwaitKeyword.GetLocation()); }