private void AddToCallerCalleeMap(OperationAnalysisContext context, Dictionary <IMethodSymbol, List <CallInfo> > callerToCalleeMap)
        {
            if (CSharpUtils.IsWithinNameOf(context.Operation.Syntax))
            {
                return;
            }

            IMethodSymbol?GetPropertyAccessor(IPropertySymbol?propertySymbol)
            {
                if (propertySymbol is object)
                {
                    return(CSharpUtils.IsOnLeftHandOfAssignment(context.Operation.Syntax)
                        ? propertySymbol.SetMethod
                        : propertySymbol.GetMethod);
                }

                return(null);
            }

            ISymbol?   targetMethod    = null;
            SyntaxNode locationToBlame = context.Operation.Syntax;

            switch (context.Operation)
            {
            case IInvocationOperation invocationOperation:
                targetMethod    = invocationOperation.TargetMethod;
                locationToBlame = this.languageUtils.IsolateMethodName(invocationOperation);
                break;

            case IPropertyReferenceOperation propertyReference:
                targetMethod = GetPropertyAccessor(propertyReference.Property);
                break;

            case IEventAssignmentOperation eventAssignmentOperation:
                IOperation eventReferenceOp = eventAssignmentOperation.EventReference;
                if (eventReferenceOp is IEventReferenceOperation eventReference)
                {
                    targetMethod = eventAssignmentOperation.Adds
                            ? eventReference.Event.AddMethod
                            : eventReference.Event.RemoveMethod;
                    locationToBlame = eventReference.Syntax;
                }

                break;
            }

            if (context.ContainingSymbol is IMethodSymbol caller && targetMethod is IMethodSymbol callee)
            {
                lock (callerToCalleeMap)
                {
                    if (!callerToCalleeMap.TryGetValue(caller, out List <CallInfo> callees))
                    {
                        callerToCalleeMap[caller] = callees = new List <CallInfo>();
                    }

                    callees.Add(new CallInfo(methodSymbol: callee, invocationSyntax: locationToBlame));
                }
            }
        }
        internal static void InspectMemberAccess(
            SyntaxNodeAnalysisContext context,
            MemberAccessExpressionSyntax?memberAccessSyntax,
            DiagnosticDescriptor descriptor,
            IEnumerable <CommonInterest.SyncBlockingMethod> problematicMethods,
            bool ignoreIfInsideAnonymousDelegate = false)
        {
            if (descriptor is null)
            {
                throw new ArgumentNullException(nameof(descriptor));
            }

            if (memberAccessSyntax is null)
            {
                return;
            }

            if (ShouldIgnoreContext(context))
            {
                return;
            }

            if (ignoreIfInsideAnonymousDelegate && context.Node.FirstAncestorOrSelf <AnonymousFunctionExpressionSyntax>() is object)
            {
                // We do not analyze JTF.Run inside anonymous functions because
                // they are so often used as callbacks where the signature is constrained.
                return;
            }

            if (CSharpUtils.IsWithinNameOf(context.Node as ExpressionSyntax))
            {
                // We do not consider arguments to nameof( ) because they do not represent invocations of code.
                return;
            }

            ITypeSymbol?typeReceiver = context.SemanticModel.GetTypeInfo(memberAccessSyntax.Expression).Type;

            if (typeReceiver is object)
            {
                foreach (CommonInterest.SyncBlockingMethod item in problematicMethods)
                {
                    if (memberAccessSyntax.Name.Identifier.Text == item.Method.Name &&
                        typeReceiver.Name == item.Method.ContainingType.Name &&
                        typeReceiver.BelongsToNamespace(item.Method.ContainingType.Namespace))
                    {
                        if (HasTaskCompleted(context, memberAccessSyntax))
                        {
                            return;
                        }

                        Location?location = memberAccessSyntax.Name.GetLocation();
                        context.ReportDiagnostic(Diagnostic.Create(descriptor, location));
                    }
                }
            }
        }
Beispiel #3
0
        private static void AddToCallerCalleeMap(SyntaxNodeAnalysisContext context, Dictionary <IMethodSymbol, List <CallInfo> > callerToCalleeMap)
        {
            if (CSharpUtils.IsWithinNameOf(context.Node))
            {
                return;
            }

            IMethodSymbol?GetPropertyAccessor(IPropertySymbol?propertySymbol)
            {
                if (propertySymbol is object)
                {
                    return(CSharpUtils.IsOnLeftHandOfAssignment(context.Node)
                        ? propertySymbol.SetMethod
                        : propertySymbol.GetMethod);
                }

                return(null);
            }

            ISymbol?   targetMethod    = null;
            SyntaxNode locationToBlame = context.Node;

            switch (context.Node)
            {
            case InvocationExpressionSyntax invocationExpressionSyntax:
                targetMethod    = context.SemanticModel.GetSymbolInfo(invocationExpressionSyntax.Expression, context.CancellationToken).Symbol;
                locationToBlame = invocationExpressionSyntax.Expression;
                break;

            case MemberAccessExpressionSyntax memberAccessExpressionSyntax:
                targetMethod = GetPropertyAccessor(context.SemanticModel.GetSymbolInfo(memberAccessExpressionSyntax.Name, context.CancellationToken).Symbol as IPropertySymbol);
                break;

            case IdentifierNameSyntax identifierNameSyntax:
                targetMethod = GetPropertyAccessor(context.SemanticModel.GetSymbolInfo(identifierNameSyntax, context.CancellationToken).Symbol as IPropertySymbol);
                break;
            }

            if (context.ContainingSymbol is IMethodSymbol caller && targetMethod is IMethodSymbol callee)
            {
                lock (callerToCalleeMap)
                {
                    if (!callerToCalleeMap.TryGetValue(caller, out List <CallInfo> callees))
                    {
                        callerToCalleeMap[caller] = callees = new List <CallInfo>();
                    }

                    callees.Add(new CallInfo(methodSymbol: callee, invocationSyntax: locationToBlame));
                }
            }
        }
Beispiel #4
0
            private void InspectMemberAccess(SyntaxNodeAnalysisContext context, MemberAccessExpressionSyntax?memberAccessSyntax, IEnumerable <CommonInterest.SyncBlockingMethod> problematicMethods)
            {
                if (memberAccessSyntax is null)
                {
                    return;
                }

                if (this.diagnosticReported)
                {
                    // Don't report more than once per method.
                    return;
                }

                if (context.Node.FirstAncestorOrSelf <AnonymousFunctionExpressionSyntax>() is object)
                {
                    // We do not analyze JTF.Run inside anonymous functions because
                    // they are so often used as callbacks where the signature is constrained.
                    return;
                }

                if (CSharpUtils.IsWithinNameOf(context.Node as ExpressionSyntax))
                {
                    // We do not consider arguments to nameof( ) because they do not represent invocations of code.
                    return;
                }

                ISymbol?invokedMember = context.SemanticModel.GetSymbolInfo(memberAccessSyntax, context.CancellationToken).Symbol;

                if (invokedMember is object)
                {
                    foreach (CommonInterest.SyncBlockingMethod item in problematicMethods)
                    {
                        if (item.Method.IsMatch(invokedMember))
                        {
                            Location?location = memberAccessSyntax.Name.GetLocation();
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, location));
                            this.diagnosticReported = true;
                        }
                    }
                }
            }