public void AnalyzeConfigureMethod(OperationBlockStartAnalysisContext context)
    {
        var configureMethod = (IMethodSymbol)context.OwningSymbol;
        var middleware      = ImmutableArray.CreateBuilder <MiddlewareItem>();

        // Note: this is a simple source-order implementation. We don't attempt perform data flow
        // analysis in order to determine the actual order in which middleware are ordered.
        //
        // This can currently be confused by things like Map(...)
        context.RegisterOperationAction(context =>
        {
            // We're looking for usage of extension methods, so we need to look at the 'this' parameter
            // rather than invocation.Instance.
            if (context.Operation is IInvocationOperation invocation &&
                invocation.Instance == null &&
                invocation.Arguments.Length >= 1 &&
                SymbolEqualityComparer.Default.Equals(invocation.Arguments[0].Parameter?.Type, _context.StartupSymbols.IApplicationBuilder))
            {
                middleware.Add(new MiddlewareItem(invocation));
            }
        }, OperationKind.Invocation);

        context.RegisterOperationBlockEndAction(context =>
        {
            _context.ReportAnalysis(new MiddlewareAnalysis(configureMethod, middleware.ToImmutable()));
        });
    }
 private void RegisterAnalyzer(OperationBlockStartAnalysisContext context, CompilationSecurityTypes types, Version frameworkVersion)
 {
     var analyzer = new OperationAnalyzer(types, frameworkVersion);
     context.RegisterOperationAction(
         analyzer.AnalyzeOperation,
         OperationKind.InvocationExpression,
         OperationKind.AssignmentExpression,
         OperationKind.VariableDeclaration,
         OperationKind.ObjectCreationExpression,
         OperationKind.FieldInitializerAtDeclaration
     );
     context.RegisterOperationBlockEndAction(
         analyzer.AnalyzeOperationBlock
     );
 }
Beispiel #3
0
        private void RegisterAnalyzer(OperationBlockStartAnalysisContext context, CompilationSecurityTypes types, Version frameworkVersion)
        {
            var analyzer = new OperationAnalyzer(types, frameworkVersion);

            context.RegisterOperationAction(
                analyzer.AnalyzeOperation,
                OperationKind.Invocation,
                OperationKind.SimpleAssignment,
                OperationKind.VariableDeclaration,
                OperationKind.ObjectCreation,
                OperationKind.FieldInitializer
                );
            context.RegisterOperationBlockEndAction(
                analyzer.AnalyzeOperationBlock
                );
        }
Beispiel #4
0
            internal void AnalyzeMethodBodyStart(OperationBlockStartAnalysisContext context)
            {
                var symbol = context.OwningSymbol as IMethodSymbol;

                if (symbol == null || !CanContainsYield(symbol))
                {
                    return;
                }

                var methodContext = new MethodContext(this, symbol);

                context.RegisterOperationAction(methodContext.AnalyzeYield, OperationKind.YieldReturn);
                context.RegisterOperationAction(methodContext.AnalyzeYield, OperationKind.YieldBreak);
                context.RegisterOperationAction(methodContext.AnalyzeThrow, OperationKind.Throw);
                context.RegisterOperationBlockEndAction(methodContext.OperationBlockEndAction);
            }
                public static void Analyze(OperationBlockStartAnalysisContext context, SymbolStartAnalyzer symbolStartAnalyzer)
                {
                    if (HasSyntaxErrors() || context.OperationBlocks.IsEmpty)
                    {
                        return;
                    }

                    // All operation blocks for a symbol belong to the same tree.
                    var firstBlock = context.OperationBlocks[0];

                    if (!symbolStartAnalyzer._compilationAnalyzer.TryGetOptions(firstBlock.Syntax.SyntaxTree,
                                                                                firstBlock.Language,
                                                                                context.Options,
                                                                                context.CancellationToken,
                                                                                out var options))
                    {
                        return;
                    }

                    var blockAnalyzer = new BlockAnalyzer(symbolStartAnalyzer, options);

                    context.RegisterOperationAction(blockAnalyzer.AnalyzeExpressionStatement, OperationKind.ExpressionStatement);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeDelegateCreationOrAnonymousFunction, OperationKind.DelegateCreation, OperationKind.AnonymousFunction);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeArgument, OperationKind.Argument);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeConversion, OperationKind.Conversion);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeFieldOrPropertyReference, OperationKind.FieldReference, OperationKind.PropertyReference);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeParameterReference, OperationKind.ParameterReference);
                    context.RegisterOperationBlockEndAction(blockAnalyzer.AnalyzeOperationBlockEnd);

                    return;

                    // Local Functions.
                    bool HasSyntaxErrors()
                    {
                        foreach (var operationBlock in context.OperationBlocks)
                        {
                            if (operationBlock.Syntax.GetDiagnostics().ToImmutableArrayOrEmpty().HasAnyErrors())
                            {
                                return(true);
                            }
                        }

                        return(false);
                    }
                }
Beispiel #6
0
    public void AnalyzeConfigureServices(OperationBlockStartAnalysisContext context)
    {
        var configureServicesMethod = (IMethodSymbol)context.OwningSymbol;
        var options = ImmutableArray.CreateBuilder <OptionsItem>();

        context.RegisterOperationAction(context =>
        {
            if (context.Operation is ISimpleAssignmentOperation operation &&
                operation.Value.ConstantValue.HasValue &&
                operation.Target is IPropertyReferenceOperation property &&
                property.Property?.ContainingType?.Name != null &&
                property.Property.ContainingType.Name.EndsWith("Options", StringComparison.Ordinal))
            {
                options.Add(new OptionsItem(property.Property, operation.Value.ConstantValue.Value));
            }
        }, OperationKind.SimpleAssignment);

        context.RegisterOperationBlockEndAction(context =>
        {
            _context.ReportAnalysis(new OptionsAnalysis(configureServicesMethod, options.ToImmutable()));
        });
    }
        public void AnalyzeConfigureServices(OperationBlockStartAnalysisContext context)
        {
            var configureServicesMethod = (IMethodSymbol)context.OwningSymbol;
            var services = ImmutableArray.CreateBuilder <ServicesItem>();

            context.RegisterOperationAction(context =>
            {
                // We're looking for usage of extension methods, so we need to look at the 'this' parameter
                // rather than invocation.Instance.
                if (context.Operation is IInvocationOperation invocation &&
                    invocation.Instance == null &&
                    invocation.Arguments.Length >= 1 &&
                    invocation.Arguments[0].Parameter?.Type == _context.StartupSymbols.IServiceCollection)
                {
                    services.Add(new ServicesItem(invocation));
                }
            }, OperationKind.Invocation);

            context.RegisterOperationBlockEndAction(context =>
            {
                _context.ReportAnalysis(new ServicesAnalysis(configureServicesMethod, services.ToImmutable()));
            });
        }
Beispiel #8
0
        private static void AnalyzeMethod(
            IMethodSymbol method,
            OperationBlockStartAnalysisContext startOperationBlockContext,
            UnusedParameterDictionary unusedMethodParameters,
            INamedTypeSymbol eventsArgSymbol,
            ISet <IMethodSymbol> methodsUsedAsDelegates,
            ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore)
        {
            // We only care about methods with parameters.
            if (method.Parameters.IsEmpty)
            {
                return;
            }

            // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat).
            if (method.IsImplicitlyDeclared ||
                method.IsExtern ||
                method.IsAbstract ||
                method.IsVirtual ||
                method.IsOverride ||
                method.IsImplementationOfAnyInterfaceMember() ||
                method.IsFinalizer())
            {
                return;
            }

            // Ignore property accessors.
            if (method.IsPropertyAccessor())
            {
                return;
            }

            // Ignore event handler methods "Handler(object, MyEventArgs)"
            if (eventsArgSymbol != null &&
                method.Parameters.Length == 2 &&
                method.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                method.Parameters[1].Type.Inherits(eventsArgSymbol))
            {
                return;
            }

            // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'.
            if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass)))
            {
                return;
            }

            // Ignore methods that were used as delegates
            if (methodsUsedAsDelegates.Contains(method))
            {
                return;
            }

            // Initialize local mutable state in the start action.
            var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters);

            // Register an intermediate non-end action that accesses and modifies the state.
            startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeParameterReference, OperationKind.ParameterReference);

            // Register an end action to add unused parameters to the unusedMethodParameters dictionary
            startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction);
        }
        private static void AnalyzeMethod(
            IMethodSymbol method,
            OperationBlockStartAnalysisContext startOperationBlockContext,
            UnusedParameterDictionary unusedMethodParameters,
            INamedTypeSymbol?eventsArgSymbol,
            ISet <IMethodSymbol> methodsUsedAsDelegates,
            ImmutableHashSet <INamedTypeSymbol?> attributeSetForMethodsToIgnore)
        {
            // We only care about methods with parameters.
            if (method.Parameters.IsEmpty)
            {
                return;
            }

            // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat).
            if (method.IsImplicitlyDeclared ||
                method.IsExtern ||
                method.IsAbstract ||
                method.IsVirtual ||
                method.IsOverride ||
                method.IsImplementationOfAnyInterfaceMember() ||
                method.IsFinalizer())
            {
                return;
            }

            // Ignore property accessors.
            if (method.IsPropertyAccessor())
            {
                return;
            }

            // Ignore event handler methods "Handler(object, MyEventArgs)"
            if (method.Parameters.Length == 2 &&
                method.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                // UWP has specific EventArgs not inheriting from System.EventArgs. It was decided to go for a suffix match rather than a whitelist.
                (method.Parameters[1].Type.Inherits(eventsArgSymbol) || method.Parameters[1].Type.Name.EndsWith("EventArgs", StringComparison.Ordinal)))
            {
                return;
            }

            // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'.
            if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass)))
            {
                return;
            }

            // Ignore methods that were used as delegates
            if (methodsUsedAsDelegates.Contains(method))
            {
                return;
            }

            // Bail out if user has configured to skip analysis for the method.
            if (!method.MatchesConfiguredVisibility(
                    startOperationBlockContext.Options,
                    Rule,
                    startOperationBlockContext.CancellationToken,
                    defaultRequiredVisibility: SymbolVisibilityGroup.All))
            {
                return;
            }

            // Initialize local mutable state in the start action.
            var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters);

            // Register an intermediate non-end action that accesses and modifies the state.
            startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeParameterReference, OperationKind.ParameterReference);

            // Register an end action to add unused parameters to the unusedMethodParameters dictionary
            startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction);
        }
                public static void Analyze(OperationBlockStartAnalysisContext context, SymbolStartAnalyzer symbolStartAnalyzer)
                {
                    if (HasSyntaxErrors() || context.OperationBlocks.IsEmpty)
                    {
                        return;
                    }

                    // Bail out in presence of conditional directives
                    // This is a workaround for https://github.com/dotnet/roslyn/issues/31820
                    // Issue https://github.com/dotnet/roslyn/issues/31821 tracks
                    // reverting this workaround.
                    if (HasConditionalDirectives())
                    {
                        return;
                    }

                    // All operation blocks for a symbol belong to the same tree.
                    var firstBlock = context.OperationBlocks[0];

                    if (!symbolStartAnalyzer._compilationAnalyzer.TryGetOptions(firstBlock.Syntax.SyntaxTree,
                                                                                firstBlock.Language,
                                                                                context.Options,
                                                                                context.CancellationToken,
                                                                                out var options))
                    {
                        return;
                    }

                    var blockAnalyzer = new BlockAnalyzer(symbolStartAnalyzer, options);

                    context.RegisterOperationAction(blockAnalyzer.AnalyzeExpressionStatement, OperationKind.ExpressionStatement);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeDelegateCreationOrAnonymousFunction, OperationKind.DelegateCreation, OperationKind.AnonymousFunction);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeLocalOrParameterReference, OperationKind.LocalReference, OperationKind.ParameterReference);
                    context.RegisterOperationAction(_ => blockAnalyzer._hasInvalidOperation = true, OperationKind.Invalid);
                    context.RegisterOperationBlockEndAction(blockAnalyzer.AnalyzeOperationBlockEnd);

                    return;

                    // Local Functions.
                    bool HasSyntaxErrors()
                    {
                        foreach (var operationBlock in context.OperationBlocks)
                        {
                            if (operationBlock.Syntax.GetDiagnostics().ToImmutableArrayOrEmpty().HasAnyErrors())
                            {
                                return(true);
                            }
                        }

                        return(false);
                    }

                    bool HasConditionalDirectives()
                    {
                        foreach (var operationBlock in context.OperationBlocks)
                        {
                            if (operationBlock.Syntax.DescendantNodes(descendIntoTrivia: true)
                                .Any(n => symbolStartAnalyzer._compilationAnalyzer.IsIfConditionalDirective(n)))
                            {
                                return(true);
                            }
                        }

                        return(false);
                    }
                }
                public static void Analyze(OperationBlockStartAnalysisContext context, SymbolStartAnalyzer symbolStartAnalyzer)
                {
                    if (HasSyntaxErrors() || context.OperationBlocks.IsEmpty)
                    {
                        return;
                    }

                    // Bail out in presence of conditional directives
                    // This is a workaround for https://github.com/dotnet/roslyn/issues/31820
                    // Issue https://github.com/dotnet/roslyn/issues/31821 tracks
                    // reverting this workaround.
                    if (HasConditionalDirectives())
                    {
                        return;
                    }

                    // All operation blocks for a symbol belong to the same tree.
                    var firstBlock = context.OperationBlocks[0];

                    if (!symbolStartAnalyzer._compilationAnalyzer.TryGetOptions(firstBlock.Syntax.SyntaxTree,
                                                                                context.Options,
                                                                                out var options))
                    {
                        return;
                    }

                    // Ignore methods that are just a single-throw method.  These are often
                    // in-progress pieces of work and we don't want to force the user to fixup other
                    // issues before they've even gotten around to writing their code.
                    if (IsSingleThrowNotImplementedOperation(firstBlock))
                    {
                        return;
                    }

                    var blockAnalyzer = new BlockAnalyzer(symbolStartAnalyzer, options);

                    context.RegisterOperationAction(blockAnalyzer.AnalyzeExpressionStatement, OperationKind.ExpressionStatement);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeDelegateCreationOrAnonymousFunction, OperationKind.DelegateCreation, OperationKind.AnonymousFunction);
                    context.RegisterOperationAction(blockAnalyzer.AnalyzeLocalOrParameterReference, OperationKind.LocalReference, OperationKind.ParameterReference);
                    context.RegisterOperationAction(_ => blockAnalyzer._hasInvalidOperation = true, OperationKind.Invalid);
                    context.RegisterOperationBlockEndAction(blockAnalyzer.AnalyzeOperationBlockEnd);

                    return;

                    // Local Functions.
                    bool HasSyntaxErrors()
                    {
                        foreach (var operationBlock in context.OperationBlocks)
                        {
                            if (operationBlock.Syntax.GetDiagnostics().ToImmutableArrayOrEmpty().HasAnyErrors())
                            {
                                return(true);
                            }
                        }

                        return(false);
                    }

                    bool HasConditionalDirectives()
                    {
                        foreach (var operationBlock in context.OperationBlocks)
                        {
                            if (operationBlock.Syntax.DescendantNodes(descendIntoTrivia: true)
                                .Any(n => symbolStartAnalyzer._compilationAnalyzer.IsIfConditionalDirective(n)))
                            {
                                return(true);
                            }
                        }

                        return(false);
                    }