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 ); }
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 ); }
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); } }
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())); }); }
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); }