internal static void AnalyzeInvocation(SyntaxNodeAnalysisContext context) { var invocationExpressionSyntax = (InvocationExpressionSyntax)context.Node; CSharpCommonInterest.InspectMemberAccess( context, invocationExpressionSyntax.Expression as MemberAccessExpressionSyntax, Descriptor, CommonInterest.JTFSyncBlockers, ignoreIfInsideAnonymousDelegate: true); }
private void InspectMemberAccess( SyntaxNodeAnalysisContext context, MemberAccessExpressionSyntax?memberAccessSyntax, IEnumerable <CommonInterest.SyncBlockingMethod> problematicMethods, INamedTypeSymbol taskSymbol) { if (memberAccessSyntax == null) { return; } // Are we in the context of an anonymous function that is passed directly in as an argument to another method? var anonymousFunctionSyntax = context.Node.FirstAncestorOrSelf <AnonymousFunctionExpressionSyntax>(); var anonFuncAsArgument = anonymousFunctionSyntax?.Parent as ArgumentSyntax; var invocationPassingExpression = anonFuncAsArgument?.Parent?.Parent as InvocationExpressionSyntax; var invokedMemberAccess = invocationPassingExpression?.Expression as MemberAccessExpressionSyntax; if (invokedMemberAccess?.Name != null) { // Does the anonymous function appear as the first argument to Task.ContinueWith? var invokedMemberSymbol = context.SemanticModel.GetSymbolInfo(invokedMemberAccess.Name, context.CancellationToken).Symbol as IMethodSymbol; if (invokedMemberSymbol?.Name == nameof(Task.ContinueWith) && Utils.IsEqualToOrDerivedFrom(invokedMemberSymbol?.ContainingType, taskSymbol) && invocationPassingExpression?.ArgumentList?.Arguments.FirstOrDefault() == anonFuncAsArgument) { // Does the member access being analyzed belong to the Task that just completed? var firstParameter = GetFirstParameter(anonymousFunctionSyntax); if (firstParameter != null) { // Are we accessing a member of the completed task? ISymbol invokedObjectSymbol = context.SemanticModel.GetSymbolInfo(memberAccessSyntax.Expression, context.CancellationToken).Symbol; IParameterSymbol completedTask = context.SemanticModel.GetDeclaredSymbol(firstParameter); if (EqualityComparer <ISymbol> .Default.Equals(invokedObjectSymbol, completedTask)) { // Skip analysis since Task.Result (et. al) of a completed Task is fair game. return; } } } } CSharpCommonInterest.InspectMemberAccess(context, memberAccessSyntax, Descriptor, problematicMethods); }