internal static void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
            {
                var invocationExpressionSyntax = (InvocationExpressionSyntax)context.Node;

                CSharpCommonInterest.InspectMemberAccess(
                    context,
                    invocationExpressionSyntax.Expression as MemberAccessExpressionSyntax,
                    Descriptor,
                    CommonInterest.JTFSyncBlockers,
                    ignoreIfInsideAnonymousDelegate: true);
            }
Exemple #2
0
        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);
        }