public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationAction(AnalyzeCompilation); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxTreeAction(SyntaxTreeAction); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSyntaxNodeAction( (nodeContext) => { Diagnostic diagnostic; if (TryGetDiagnostic(nodeContext, out diagnostic)) { nodeContext.ReportDiagnostic(diagnostic); } }, new SyntaxKind[] { SyntaxKind.MethodDeclaration, SyntaxKind.FieldDeclaration, SyntaxKind.PropertyDeclaration, SyntaxKind.IndexerDeclaration, SyntaxKind.EventDeclaration, SyntaxKind.ConstructorDeclaration, SyntaxKind.OperatorDeclaration, SyntaxKind.ClassDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.EnumDeclaration, SyntaxKind.DelegateDeclaration } ); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { var exportAttributes = new List<INamedTypeSymbol>(); foreach (var mefNamespace in s_mefNamespaces) { var exportAttribute = compilationContext.Compilation.GetTypeByMetadataName(mefNamespace + ".ExportAttribute"); if (exportAttribute == null) { // We don't need to check assemblies unless they're referencing both versions of MEF, so we're done return; } exportAttributes.Add(exportAttribute); } compilationContext.RegisterSymbolAction(c => AnalyzeSymbol(c, exportAttributes), SymbolKind.NamedType); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { var exportAttribute = compilationContext.Compilation.GetTypeByMetadataName("System.Composition.ExportAttribute"); if (exportAttribute == null) { // We don't need to check assemblies unless they're referencing both MEFv2, so we're done return; } compilationContext.RegisterSymbolAction(symbolContext => { var namedType = (INamedTypeSymbol)symbolContext.Symbol; var namedTypeAttributes = namedType.GetApplicableAttributes(); var exportAttributeApplication = namedTypeAttributes.FirstOrDefault(ad => ad.AttributeClass.DerivesFrom(exportAttribute)); if (exportAttributeApplication != null) { if (!namedTypeAttributes.Any(ad => ad.AttributeClass.Name == "SharedAttribute" && ad.AttributeClass.ContainingNamespace.Equals(exportAttribute.ContainingNamespace))) { // '{0}' is exported with MEFv2 and hence must be marked as Shared symbolContext.ReportDiagnostic(Diagnostic.Create(Rule, exportAttributeApplication.ApplicationSyntaxReference.GetSyntax().GetLocation(), namedType.Name)); } } }, SymbolKind.NamedType); }); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(DoStatementAction, SyntaxKind.DoStatement); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(OnCompilationStart); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterSymbolAction( symbolAnalysisContext => { ISymbol symbol = symbolAnalysisContext.Symbol; if (!symbol.ContainingType.IsGenericType || symbol.DeclaredAccessibility != Accessibility.Public || !symbol.IsStatic) { return; } var methodSymbol = symbol as IMethodSymbol; if (methodSymbol != null && (methodSymbol.IsAccessorMethod() || (methodSymbol.MethodKind == MethodKind.UserDefinedOperator && (methodSymbol.Name == WellKnownMemberNames.EqualityOperatorName || methodSymbol.Name == WellKnownMemberNames.InequalityOperatorName)))) { return; } symbolAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(Rule, symbol.Name)); }, SymbolKind.Method, SymbolKind.Property); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(DocumentationTriviaAction, SyntaxKind.SingleLineDocumentationCommentTrivia); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(RegionDirectiveTriviaAction, SyntaxKind.RegionDirectiveTrivia); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSymbolAction(Analyzer.HandleFieldDeclaration, SymbolKind.Field); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSyntaxNodeAction( nodeContext => { GetDiagnostics(nodeContext, ((InvocationExpressionSyntax)nodeContext.Node).ArgumentList?.Arguments); }, new SyntaxKind[] { SyntaxKind.InvocationExpression } ); context.RegisterSyntaxNodeAction( nodeContext => { GetDiagnostics(nodeContext, ((ElementAccessExpressionSyntax)nodeContext.Node).ArgumentList?.Arguments); }, new SyntaxKind[] { SyntaxKind.ElementAccessExpression } ); context.RegisterSyntaxNodeAction( nodeContext => { GetDiagnostics(nodeContext, ((ObjectCreationExpressionSyntax)nodeContext.Node).ArgumentList?.Arguments); }, new SyntaxKind[] { SyntaxKind.ObjectCreationExpression } ); context.RegisterSyntaxNodeAction( nodeContext => { GetDiagnostics(nodeContext, ((AttributeSyntax)nodeContext.Node).ArgumentList?.Arguments); }, new SyntaxKind[] { SyntaxKind.Attribute } ); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterSyntaxNodeAction<SyntaxKind>(AnalyzeNode, SyntaxKind.ThrowStatement); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(AnonymousMethodExpressionAction, SyntaxKind.AnonymousMethodExpression); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction( (context) => { INamedTypeSymbol eventHandler = WellKnownTypes.EventHandler(context.Compilation); if (eventHandler == null) { return; } INamedTypeSymbol genericEventHandler = WellKnownTypes.GenericEventHandler(context.Compilation); if (genericEventHandler == null) { return; } INamedTypeSymbol eventArgs = WellKnownTypes.EventArgs(context.Compilation); if (eventArgs == null) { return; } INamedTypeSymbol comSourceInterfacesAttribute = WellKnownTypes.ComSourceInterfaceAttribute(context.Compilation); if (comSourceInterfacesAttribute == null) { return; } context.RegisterSymbolAction(GetAnalyzer(context.Compilation, eventHandler, genericEventHandler, eventArgs, comSourceInterfacesAttribute).AnalyzeSymbol, SymbolKind.Event); }); }
/// <inheritdoc/> public override void Initialize(AnalysisContext analysisContext) { analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.EnableConcurrentExecution(); analysisContext.RegisterSymbolAction(AnalyzeMethodSymbol, SymbolKind.Method); }
public override void Initialize(AnalysisContext analysisContext) { // this is stateless analyzer, can run concurrently analysisContext.EnableConcurrentExecution(); // this has no meaning on running on generated code which user can't control analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(c => { INamedTypeSymbol @string = WellKnownTypes.String(c.Compilation); INamedTypeSymbol uri = WellKnownTypes.Uri(c.Compilation); if (@string == null || uri == null) { // we don't have required types return; } var analyzer = new Analyzer(c.Compilation, @string, uri, GetInvocationExpression); // REVIEW: I need to do this thing because OperationAnalysisContext doesn't give me OwningSymbol c.RegisterOperationBlockStartAction(sc => { sc.RegisterOperationAction(oc => analyzer.Analyze(oc, sc.OwningSymbol), OperationKind.InvocationExpression); }); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSyntaxNodeAction( nodeContext => { Diagnostic diagnostic; if (TryGetDiagnostic(nodeContext, out diagnostic)) { nodeContext.ReportDiagnostic(diagnostic); } }, new SyntaxKind[] { SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression, SyntaxKind.LessThanExpression, SyntaxKind.LessThanOrEqualExpression, SyntaxKind.GreaterThanExpression, SyntaxKind.GreaterThanOrEqualExpression } ); context.RegisterSyntaxNodeAction( nodeContext => { Diagnostic diagnostic; if (TryGetDiagnostic2(nodeContext, out diagnostic)) { nodeContext.ReportDiagnostic(diagnostic); } }, new SyntaxKind[] { SyntaxKind.LogicalNotExpression } ); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationStartContext => { var immutableArrayType = compilationStartContext.Compilation.GetTypeByMetadataName(ImmutableArrayMetadataName); if (immutableArrayType == null) { return; } compilationStartContext.RegisterOperationAction(operationContext => { var invocation = (IInvocationExpression)operationContext.Operation; if (invocation.IsInvalid || invocation.TargetMethod?.Name != "ToImmutableArray") { return; } var receiverType = invocation.GetReceiverType(operationContext.Compilation, beforeConversion: true, cancellationToken: operationContext.CancellationToken); if (receiverType != null && receiverType.DerivesFromOrImplementsAnyConstructionOf(immutableArrayType)) { operationContext.ReportDiagnostic(Diagnostic.Create(Rule, invocation.Syntax.GetLocation())); } }, OperationKind.InvocationExpression); }); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(BinaryExpressionAction, HandledBinaryExpressionKinds); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSymbolAction( (symbol) => { Diagnostic diagnostic; if (TryGetDiagnostic(symbol, out diagnostic)) { symbol.ReportDiagnostic(diagnostic); } }, new SymbolKind[] { SymbolKind.Method } ); context.RegisterSyntaxNodeAction( (nodeContext) => { Diagnostic diagnostic; if (TryGetDiagnostic(nodeContext, out diagnostic)) { nodeContext.ReportDiagnostic(diagnostic); } }, new SyntaxKind[] { SyntaxKind.AnonymousMethodExpression, SyntaxKind.ParenthesizedLambdaExpression, SyntaxKind.SimpleLambdaExpression } ); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(EnumMemberDeclarationAction, SyntaxKind.EnumMemberDeclaration); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationContext.Compilation); compilationContext.RegisterOperationBlockAction(context => { var method = context.OwningSymbol as IMethodSymbol; if (method == null) { return; } if (!method.IsFinalizer()) { return; } if (IsEmptyFinalizer(context.OperationBlocks, conditionalAttributeSymbol)) { context.ReportDiagnostic(context.OwningSymbol.CreateDiagnostic(Rule)); } }); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSyntaxNodeAction(AnalyzeXmlAttribute, SyntaxKind.XmlTextAttribute); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterSymbolAction(symbolContext => { var method = (IMethodSymbol)symbolContext.Symbol; if (!IsEventLikeNameCandidate(method.Name)) { Debug.Assert(!HasEventLikeName(method), "fast check failed but eventual check succeeds?"); return; } // Bail out for implicitly declared methods, overridden methods, interface implementations, constructors and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsConstructor() || method.IsFinalizer()) { return; } if (HasEventLikeName(method)) { // Consider making '{0}' an event. var diagnostic = method.CreateDiagnostic(Rule, method.Name); symbolContext.ReportDiagnostic(diagnostic); } }, SymbolKind.Method); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction( compilationContext => { Compilation compilation = compilationContext.Compilation; ITypeSymbol argumentExceptionType = compilation.GetTypeByMetadataName("System.ArgumentException"); if (argumentExceptionType == null) { return; } compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { operationBlockStartContext.RegisterOperationAction( operationContext => AnalyzeObjectCreation( operationContext, operationBlockStartContext.OwningSymbol, argumentExceptionType), OperationKind.ObjectCreationExpression); }); }); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(TypeParameterConstraintClauseAction, SyntaxKind.TypeParameterConstraintClause); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction( (context) => { INamedTypeSymbol iCollectionType = WellKnownTypes.ICollection(context.Compilation); INamedTypeSymbol genericICollectionType = WellKnownTypes.GenericICollection(context.Compilation); INamedTypeSymbol iEnumerableType = WellKnownTypes.IEnumerable(context.Compilation); INamedTypeSymbol genericIEnumerableType = WellKnownTypes.GenericIEnumerable(context.Compilation); INamedTypeSymbol iListType = WellKnownTypes.IList(context.Compilation); INamedTypeSymbol genericIListType = WellKnownTypes.GenericIList(context.Compilation); if (iCollectionType == null && genericICollectionType == null && iEnumerableType == null && genericIEnumerableType == null && iListType == null && genericIListType == null) { return; } context.RegisterSymbolAction(c => AnalyzeSymbol(c, iCollectionType, genericICollectionType, iEnumerableType, genericIEnumerableType, iListType, genericIListType), SymbolKind.NamedType); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction( (context) => { INamedTypeSymbol dllImportType = context.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.DllImportAttribute"); if (dllImportType == null) { return; } INamedTypeSymbol marshalAsType = context.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.MarshalAsAttribute"); if (marshalAsType == null) { return; } INamedTypeSymbol stringBuilderType = context.Compilation.GetTypeByMetadataName("System.Text.StringBuilder"); if (stringBuilderType == null) { return; } INamedTypeSymbol unmanagedType = context.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedType"); if (unmanagedType == null) { return; } context.RegisterSymbolAction(new SymbolAnalyzer(dllImportType, marshalAsType, stringBuilderType, unmanagedType).AnalyzeSymbol, SymbolKind.Method); }); }
/// <inheritdoc /> public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze); context.RegisterCompilationStartAction(compilationStartContext => { var mainThreadAssertingMethods = CommonInterest.ReadMethods(compilationStartContext.Options, CommonInterest.FileNamePatternForMethodsThatAssertMainThread, compilationStartContext.CancellationToken).ToImmutableArray(); var mainThreadSwitchingMethods = CommonInterest.ReadMethods(compilationStartContext.Options, CommonInterest.FileNamePatternForMethodsThatSwitchToMainThread, compilationStartContext.CancellationToken).ToImmutableArray(); var membersRequiringMainThread = CommonInterest.ReadTypesAndMembers(compilationStartContext.Options, CommonInterest.FileNamePatternForMembersRequiringMainThread, compilationStartContext.CancellationToken).ToImmutableArray(); var diagnosticProperties = ImmutableDictionary <string, string> .Empty .Add(CommonInterest.FileNamePatternForMethodsThatAssertMainThread.ToString(), string.Join("\n", mainThreadAssertingMethods)) .Add(CommonInterest.FileNamePatternForMethodsThatSwitchToMainThread.ToString(), string.Join("\n", mainThreadSwitchingMethods)); var methodsDeclaringUIThreadRequirement = new HashSet <IMethodSymbol>(); var methodsAssertingUIThreadRequirement = new HashSet <IMethodSymbol>(); var callerToCalleeMap = new Dictionary <IMethodSymbol, List <CallInfo> >(); compilationStartContext.RegisterCodeBlockStartAction <SyntaxKind>(codeBlockStartContext => { var methodAnalyzer = new MethodAnalyzer { MainThreadAssertingMethods = mainThreadAssertingMethods, MainThreadSwitchingMethods = mainThreadSwitchingMethods, MembersRequiringMainThread = membersRequiringMainThread, MethodsDeclaringUIThreadRequirement = methodsDeclaringUIThreadRequirement, MethodsAssertingUIThreadRequirement = methodsAssertingUIThreadRequirement, DiagnosticProperties = diagnosticProperties, }; codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeInvocation), SyntaxKind.InvocationExpression); codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeMemberAccess), SyntaxKind.SimpleMemberAccessExpression); codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeCast), SyntaxKind.CastExpression); codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeAs), SyntaxKind.AsExpression); codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeAs), SyntaxKind.IsExpression); codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeIsPattern), SyntaxKind.IsPatternExpression); }); compilationStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(c => AddToCallerCalleeMap(c, callerToCalleeMap)), SyntaxKind.InvocationExpression); compilationStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(c => AddToCallerCalleeMap(c, callerToCalleeMap)), SyntaxKind.SimpleMemberAccessExpression); compilationStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(c => AddToCallerCalleeMap(c, callerToCalleeMap)), SyntaxKind.IdentifierName); compilationStartContext.RegisterCompilationEndAction(compilationEndContext => { var calleeToCallerMap = CreateCalleeToCallerMap(callerToCalleeMap); var transitiveClosureOfMainThreadRequiringMethods = GetTransitiveClosureOfMainThreadRequiringMethods(methodsAssertingUIThreadRequirement, calleeToCallerMap); foreach (var implicitUserMethod in transitiveClosureOfMainThreadRequiringMethods.Except(methodsDeclaringUIThreadRequirement)) { var reportSites = from info in callerToCalleeMap[implicitUserMethod] where transitiveClosureOfMainThreadRequiringMethods.Contains(info.MethodSymbol) group info by info.MethodSymbol into bySymbol select new { Location = bySymbol.First().InvocationSyntax.GetLocation(), CalleeMethod = bySymbol.Key }; foreach (var site in reportSites) { bool isAsync = Utils.IsAsyncReady(implicitUserMethod); var descriptor = isAsync ? DescriptorAsync : DescriptorSync; string calleeName = Utils.GetFullName(site.CalleeMethod); var formattingArgs = isAsync ? new object[] { calleeName } : new object[] { calleeName, mainThreadAssertingMethods.FirstOrDefault() }; Diagnostic diagnostic = Diagnostic.Create( descriptor, site.Location, diagnosticProperties, formattingArgs); compilationEndContext.ReportDiagnostic(diagnostic); } } }); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationAction(compilationContext => { if (compilationContext.Compilation.SyntaxTrees.FirstOrDefault() is not SyntaxTree tree) { return; } // Try read the additional file containing the code metrics configuration. if (!TryGetRuleIdToThresholdMap( compilationContext.Options.AdditionalFiles, compilationContext.CancellationToken, out AdditionalText? additionalTextOpt, out ImmutableDictionary <string, IReadOnlyList <(SymbolKind?, uint)> >?ruleIdToThresholdMap, out List <Diagnostic>?invalidFileDiagnostics) && invalidFileDiagnostics != null) { // Report any invalid additional file diagnostics. foreach (var diagnostic in invalidFileDiagnostics) { compilationContext.ReportDiagnostic(diagnostic); } return; } var metricsAnalysisContext = new CodeMetricsAnalysisContext(compilationContext.Compilation, compilationContext.CancellationToken, namedType => IsConfiguredToSkipFromInheritanceCount(namedType, compilationContext, tree)); var computeTask = CodeAnalysisMetricData.ComputeAsync(metricsAnalysisContext); computeTask.Wait(compilationContext.CancellationToken); // Analyze code metrics tree and report diagnostics. analyzeMetricsData(computeTask.Result); void analyzeMetricsData(CodeAnalysisMetricData codeAnalysisMetricData) { var symbol = codeAnalysisMetricData.Symbol; // CA1501: Avoid excessive inheritance if (symbol.Kind == SymbolKind.NamedType && codeAnalysisMetricData.DepthOfInheritance.HasValue) { uint?inheritanceThreshold = getThreshold(CA1501RuleId, symbol.Kind); if (inheritanceThreshold.HasValue && codeAnalysisMetricData.DepthOfInheritance.Value > inheritanceThreshold.Value) { // '{0}' has an object hierarchy '{1}' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '{2}': '{3}' var arg1 = symbol.Name; var arg2 = codeAnalysisMetricData.DepthOfInheritance; var arg3 = inheritanceThreshold + 1; var arg4 = string.Join(", ", ((INamedTypeSymbol)symbol).GetBaseTypes(t => !IsConfiguredToSkipFromInheritanceCount(t, compilationContext, tree)).Select(t => t.Name)); var diagnostic = symbol.CreateDiagnostic(CA1501Rule, arg1, arg2, arg3, arg4); compilationContext.ReportDiagnostic(diagnostic); } } // CA1502: Avoid excessive complexity uint?complexityThreshold = getThreshold(CA1502RuleId, symbol.Kind); if (complexityThreshold.HasValue && codeAnalysisMetricData.CyclomaticComplexity > complexityThreshold.Value) { // '{0}' has a cyclomatic complexity of '{1}'. Rewrite or refactor the code to decrease its complexity below '{2}'. var arg1 = symbol.Name; var arg2 = codeAnalysisMetricData.CyclomaticComplexity; var arg3 = complexityThreshold.Value + 1; var diagnostic = symbol.CreateDiagnostic(CA1502Rule, arg1, arg2, arg3); compilationContext.ReportDiagnostic(diagnostic); } // CA1505: Avoid unmaintainable code uint?maintainabilityIndexThreshold = getThreshold(CA1505RuleId, symbol.Kind); if (maintainabilityIndexThreshold.HasValue && maintainabilityIndexThreshold.Value > codeAnalysisMetricData.MaintainabilityIndex) { // '{0}' has a maintainability index of '{1}'. Rewrite or refactor the code to increase its maintainability index (MI) above '{2}'. var arg1 = symbol.Name; var arg2 = codeAnalysisMetricData.MaintainabilityIndex; var arg3 = maintainabilityIndexThreshold.Value - 1; var diagnostic = symbol.CreateDiagnostic(CA1505Rule, arg1, arg2, arg3); compilationContext.ReportDiagnostic(diagnostic); } // CA1506: Avoid excessive class coupling uint?classCouplingThreshold = getThreshold(CA1506RuleId, symbol.Kind); if (classCouplingThreshold.HasValue && codeAnalysisMetricData.CoupledNamedTypes.Count > classCouplingThreshold.Value) { // '{0}' is coupled with '{1}' different types from '{2}' different namespaces. Rewrite or refactor the code to decrease its class coupling below '{3}'. var arg1 = symbol.Name; var arg2 = codeAnalysisMetricData.CoupledNamedTypes.Count; var arg3 = GetDistinctContainingNamespacesCount(codeAnalysisMetricData.CoupledNamedTypes); var arg4 = classCouplingThreshold.Value + 1; var diagnostic = symbol.CreateDiagnostic(CA1506Rule, arg1, arg2, arg3, arg4); compilationContext.ReportDiagnostic(diagnostic); } foreach (var child in codeAnalysisMetricData.Children) { analyzeMetricsData(child); } } uint?getThreshold(string ruleId, SymbolKind symbolKind) { // Check if we have custom threshold value for the given ruleId and symbolKind. if (ruleIdToThresholdMap != null && ruleIdToThresholdMap.TryGetValue(ruleId, out IReadOnlyList <(SymbolKind?symbolKindOpt, uint threshold)> values)) { foreach ((SymbolKind? symbolKindOpt, uint threshold) in values) { if (symbolKindOpt.HasValue && symbolKindOpt.Value == symbolKind) { return(threshold); } } if (values.Count == 1 && values[0].symbolKindOpt == null && isApplicableByDefault(ruleId, symbolKind)) { return(values[0].threshold); } } return(getDefaultThreshold(ruleId, symbolKind)); } static bool isApplicableByDefault(string ruleId, SymbolKind symbolKind) { switch (ruleId) { case CA1501RuleId: return(symbolKind == SymbolKind.NamedType); case CA1502RuleId: return(symbolKind == SymbolKind.Method); case CA1505RuleId: switch (symbolKind) { case SymbolKind.NamedType: case SymbolKind.Method: case SymbolKind.Field: case SymbolKind.Property: case SymbolKind.Event: return(true); default: return(false); } case CA1506RuleId: switch (symbolKind) { case SymbolKind.NamedType: case SymbolKind.Method: case SymbolKind.Field: case SymbolKind.Property: case SymbolKind.Event: return(true); default: return(false); } default: throw new NotImplementedException(); } }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(HandleObjectCreation, SyntaxKind.ObjectCreationExpression); }
/// <summary> /// This is used to initialize the analyzer. /// </summary> /// <param name="context"> /// The context the analysis should take place in. /// </param> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol expectedExceptionType = WellKnownTypes.ExpectedException(compilationContext.Compilation); INamedTypeSymbol nunitAssertType = WellKnownTypes.NunitAssert(compilationContext.Compilation); INamedTypeSymbol xunitAssertType = WellKnownTypes.XunitAssert(compilationContext.Compilation); compilationContext.RegisterOperationBlockStartAction(osContext => { if (!(osContext.OwningSymbol is IMethodSymbol method)) { return; } osContext.RegisterOperationAction(opContext => { IOperation expression = ((IExpressionStatementOperation)opContext.Operation).Operation; DiagnosticDescriptor rule = null; string targetMethodName = null; switch (expression.Kind) { case OperationKind.ObjectCreation: IMethodSymbol ctor = ((IObjectCreationOperation)expression).Constructor; if (ctor != null) { rule = ObjectCreationRule; targetMethodName = ctor.ContainingType.Name; } break; case OperationKind.Invocation: IInvocationOperation invocationExpression = ((IInvocationOperation)expression); IMethodSymbol targetMethod = invocationExpression.TargetMethod; if (targetMethod == null) { break; } if (IsStringCreatingMethod(targetMethod)) { rule = StringCreationRule; } else if (IsTryParseMethod(targetMethod)) { rule = TryParseRule; } else if (IsHResultOrErrorCodeReturningMethod(targetMethod)) { rule = HResultOrErrorCodeRule; } else if (IsPureMethod(targetMethod, opContext.Compilation)) { rule = PureMethodRule; } targetMethodName = targetMethod.Name; break; } if (rule != null) { if (ShouldSkipAnalyzing(opContext, expectedExceptionType, xunitAssertType, nunitAssertType)) { return; } Diagnostic diagnostic = Diagnostic.Create(rule, expression.Syntax.GetLocation(), method.Name, targetMethodName); opContext.ReportDiagnostic(diagnostic); } }, OperationKind.ExpressionStatement); }); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterSymbolAction(symbolAnalysisContext => { var symbol = symbolAnalysisContext.Symbol; // FxCop compat: only analyze externally visible symbols if (!symbol.IsExternallyVisible()) { return; } switch (symbol.Kind) { case SymbolKind.Namespace: { if (ContainsUnderScore(symbol.Name)) { symbolAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(NamespaceRule, symbol.ToDisplayString())); } return; } case SymbolKind.NamedType: { var namedType = symbol as INamedTypeSymbol; AnalyzeTypeParameters(symbolAnalysisContext, namedType.TypeParameters); if (namedType.TypeKind == TypeKind.Delegate && namedType.DelegateInvokeMethod != null) { AnalyzeParameters(symbolAnalysisContext, namedType.DelegateInvokeMethod.Parameters); } if (!ContainsUnderScore(symbol.Name)) { return; } symbolAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(TypeRule, symbol.ToDisplayString())); return; } case SymbolKind.Field: { var fieldSymbol = symbol as IFieldSymbol; if (ContainsUnderScore(symbol.Name) && (fieldSymbol.IsConst || (fieldSymbol.IsStatic && fieldSymbol.IsReadOnly))) { symbolAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(MemberRule, symbol.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); return; } return; } default: { if (symbol is IMethodSymbol methodSymbol) { if (methodSymbol.IsOperator()) { // Do not flag for operators. return; } if (methodSymbol.MethodKind == MethodKind.Conversion) { // Do not flag for conversion methods generated for operators. return; } AnalyzeParameters(symbolAnalysisContext, methodSymbol.Parameters); AnalyzeTypeParameters(symbolAnalysisContext, methodSymbol.TypeParameters); } if (symbol is IPropertySymbol propertySymbol) { AnalyzeParameters(symbolAnalysisContext, propertySymbol.Parameters); } if (!ContainsUnderScore(symbol.Name) || IsInvalidSymbol(symbol)) { return; } symbolAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(MemberRule, symbol.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); return; } } }, SymbolKind.Namespace, // Namespace SymbolKind.NamedType, //Type SymbolKind.Method, SymbolKind.Property, SymbolKind.Field, SymbolKind.Event // Members ); analysisContext.RegisterCompilationAction(compilationAnalysisContext => { var compilation = compilationAnalysisContext.Compilation; if (ContainsUnderScore(compilation.AssemblyName)) { compilationAnalysisContext.ReportDiagnostic(compilation.Assembly.CreateDiagnostic(AssemblyRule, compilation.AssemblyName)); } }); }
/// <inheritdoc/> private protected override void Register(AnalysisContext context) { context.EnableConcurrentExecution(); context.RegisterSyntaxTreeAction(AnalyzeSyntaxTree); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationContext.Compilation); INamedTypeSymbol cancellationTokenType = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingCancellationToken); INamedTypeSymbol iprogressType = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIProgress1); if (cancellationTokenType == null) { return; } compilationContext.RegisterSymbolAction(symbolContext => { var methodSymbol = (IMethodSymbol)symbolContext.Symbol; if (methodSymbol.IsOverride || methodSymbol.IsImplementationOfAnyInterfaceMember()) { return; } int last = methodSymbol.Parameters.Length - 1; if (last >= 0 && methodSymbol.Parameters[last].IsParams) { last--; } // Skip optional parameters, UNLESS one of them is a CancellationToken // AND it's not the last one. if (last >= 0 && methodSymbol.Parameters[last].IsOptional && !methodSymbol.Parameters[last].Type.Equals(cancellationTokenType)) { last--; while (last >= 0 && methodSymbol.Parameters[last].IsOptional) { if (methodSymbol.Parameters[last].Type.Equals(cancellationTokenType)) { symbolContext.ReportDiagnostic(Diagnostic.Create( Rule, methodSymbol.Locations.First(), methodSymbol.ToDisplayString())); } last--; } } // Ignore multiple cancellation token parameters at the end of the parameter list. while (last >= 0 && methodSymbol.Parameters[last].Type.Equals(cancellationTokenType)) { last--; } // Ignore parameters passed by reference when they appear at the end of the parameter list. while (last >= 0 && methodSymbol.Parameters[last].RefKind != RefKind.None) { last--; } // Ignore IProgress<T> when last if (last >= 0 && iprogressType != null && methodSymbol.Parameters[last].Type.OriginalDefinition.Equals(iprogressType)) { last--; } for (int i = last - 1; i >= 0; i--) { ITypeSymbol parameterType = methodSymbol.Parameters[i].Type; if (!parameterType.Equals(cancellationTokenType)) { continue; } // Bail if the CancellationToken is the first parameter of an extension method. if (i == 0 && methodSymbol.IsExtensionMethod) { continue; } symbolContext.ReportDiagnostic(Diagnostic.Create( Rule, methodSymbol.Locations.First(), methodSymbol.ToDisplayString())); break; } }, SymbolKind.Method); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction(RegisterScopeBuilderAnalyzer); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction( compilationStartAnalysisContext => { Compilation compilation = compilationStartAnalysisContext.Compilation; ImmutableHashSet <INamedTypeSymbol> nativeResourceTypes = ImmutableHashSet.Create( compilation.GetSpecialType(SpecialType.System_IntPtr), compilation.GetSpecialType(SpecialType.System_UIntPtr), compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesHandleRef) ); var disposableType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); compilationStartAnalysisContext.RegisterOperationAction( operationAnalysisContext => { var assignment = (IAssignmentOperation)operationAnalysisContext.Operation; IOperation target = assignment.Target; if (target == null) { // This can happen if the left-hand side is an undefined symbol. return; } if (target.Kind != OperationKind.FieldReference) { return; } var fieldReference = (IFieldReferenceOperation)target; if (!(fieldReference.Member is IFieldSymbol field) || field.Kind != SymbolKind.Field || field.IsStatic) { return; } if (!nativeResourceTypes.Contains(field.Type)) { return; } INamedTypeSymbol containingType = field.ContainingType; if (containingType == null || containingType.IsValueType) { return; } if (!containingType.AllInterfaces.Contains(disposableType)) { return; } if (containingType.HasFinalizer()) { return; } if (assignment.Value == null || assignment.Value.Kind != OperationKind.Invocation) { return; } var invocation = (IInvocationOperation)assignment.Value; if (invocation == null) { return; } IMethodSymbol method = invocation.TargetMethod; // TODO: What about COM? if (method.GetDllImportData() == null) { return; } operationAnalysisContext.ReportDiagnostic(containingType.CreateDiagnostic(Rule)); }, OperationKind.SimpleAssignment); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction(context => { if (!ComponentSymbols.TryCreate(context.Compilation, out var symbols)) { // Types we need are not defined. return; } context.RegisterOperationBlockStartAction(startBlockContext => { startBlockContext.RegisterOperationAction(context => { IOperation leftHandSide; if (context.Operation is IAssignmentOperation assignmentOperation) { leftHandSide = assignmentOperation.Target; } else { var incrementOrDecrementOperation = (IIncrementOrDecrementOperation)context.Operation; leftHandSide = incrementOrDecrementOperation.Target; } if (leftHandSide == null) { // Malformed assignment, no left hand side. return; } if (leftHandSide.Kind != OperationKind.PropertyReference) { // We don't want to capture situations where a user does // MyOtherProperty = aComponent.SomeParameter return; } var propertyReference = (IPropertyReferenceOperation)leftHandSide; var componentProperty = (IPropertySymbol)propertyReference.Member; if (!ComponentFacts.IsParameter(symbols, componentProperty)) { // This is not a property reference that we care about, it is not decorated with [Parameter]. return; } var propertyContainingType = componentProperty.ContainingType; if (!ComponentFacts.IsComponent(symbols, context.Compilation, propertyContainingType)) { // Someone referenced a property as [Parameter] inside something that is not a component. return; } var assignmentContainingType = startBlockContext.OwningSymbol?.ContainingType; if (assignmentContainingType == null) { // Assignment location has no containing type. Most likely we're operating on malformed code, don't try and validate. return; } var conversion = context.Compilation.ClassifyConversion(propertyContainingType, assignmentContainingType); if (conversion.Exists && conversion.IsIdentity) { // The assignment is taking place inside of the declaring component. return; } if (conversion.Exists && conversion.IsExplicit) { // The assignment is taking place within the components type hierarchy. This means the user is setting this in a supported // scenario. return; } // At this point the user is referencing a component parameter outside of its declaring class. context.ReportDiagnostic(Diagnostic.Create( DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent, propertyReference.Syntax.GetLocation(), propertyReference.Member.Name)); }, OperationKind.SimpleAssignment, OperationKind.CompoundAssignment, OperationKind.CoalesceAssignment, OperationKind.Increment, OperationKind.Decrement); }); }); }
public override void Initialize(AnalysisContext context) { if (!System.Diagnostics.Debugger.IsAttached) { context.EnableConcurrentExecution(); } context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction(context => { if (!context.Options.IsMSBuildPropertyValueTrue(MSBuildPropertyOptionNames.EnableTrimAnalyzer, context.Compilation)) { return; } context.RegisterOperationBlockAction(context => { if (context.OwningSymbol.IsInRequiresUnreferencedCodeAttributeScope()) { return; } // See https://github.com/dotnet/linker/issues/2587 // Need to punt on handling compiler generated methods until the linker is fixed // async is handled here and the rest are handled just below // iterators could be handled here once https://github.com/dotnet/roslyn/issues/20179 is fixed if (context.OwningSymbol is IMethodSymbol methodSymbol && methodSymbol.IsAsync) { return; } // Sub optimal way to handle analyzer not to generate warnings until the linker is fixed // Iterators, local functions and lambdas are handled foreach (IOperation blockOperation in context.OperationBlocks) { if (blockOperation is IBlockOperation blocks) { foreach (IOperation operation in blocks.Operations) { if (operation.Kind == OperationKind.AnonymousFunction || operation.Kind == OperationKind.LocalFunction || operation.Kind == OperationKind.YieldBreak || operation.Kind == OperationKind.YieldReturn) { return; } } } } foreach (var operationBlock in context.OperationBlocks) { ControlFlowGraph cfg = context.GetControlFlowGraph(operationBlock); TrimDataFlowAnalysis trimDataFlowAnalysis = new (context, cfg); foreach (var diagnostic in trimDataFlowAnalysis.ComputeTrimAnalysisPatterns().CollectDiagnostics()) { context.ReportDiagnostic(diagnostic); } } }); context.RegisterSyntaxNodeAction(context => { ProcessGenericParameters(context); }, SyntaxKind.GenericName); context.RegisterSymbolAction(context => { VerifyMemberOnlyApplyToTypesOrStrings(context, context.Symbol); VerifyDamOnPropertyAndAccessorMatch(context, (IMethodSymbol)context.Symbol); VerifyDamOnDerivedAndBaseMethodsMatch(context, (IMethodSymbol)context.Symbol); }, SymbolKind.Method); context.RegisterSymbolAction(context => { VerifyDamOnInterfaceAndImplementationMethodsMatch(context, (INamedTypeSymbol)context.Symbol); }, SymbolKind.NamedType); context.RegisterSymbolAction(context => { VerifyMemberOnlyApplyToTypesOrStrings(context, context.Symbol); }, SymbolKind.Property); context.RegisterSymbolAction(context => { VerifyMemberOnlyApplyToTypesOrStrings(context, context.Symbol); }, SymbolKind.Field); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationStartContext => { var objectType = compilationStartContext.Compilation.GetSpecialType(SpecialType.System_Object); if (objectType == null) { return; } var objectObjectParameters = new[] { ParameterInfo.GetParameterInfo(objectType), ParameterInfo.GetParameterInfo(objectType) }; var referenceEqualsMethodGroup = objectType.GetMembers("ReferenceEquals").OfType <IMethodSymbol>(); var referenceEqualsMethod = referenceEqualsMethodGroup.GetFirstOrDefaultMemberWithParameterInfos( objectObjectParameters); if (referenceEqualsMethod == null) { return; } var typeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartContext.Compilation); var referenceEqualityComparer = typeProvider.GetOrCreateTypeByMetadataName("System.Collections.Generic.ReferenceEqualityComparer"); IMethodSymbol?comparerEqualsMethod = null; if (referenceEqualityComparer != null) { var equalsMethodGroup = referenceEqualityComparer.GetMembers("Equals").OfType <IMethodSymbol>(); comparerEqualsMethod = equalsMethodGroup.GetFirstOrDefaultMemberWithParameterInfos( objectObjectParameters); } compilationStartContext.RegisterOperationAction(operationContext => { var invocationExpression = (IInvocationOperation)operationContext.Operation; var targetMethod = invocationExpression.TargetMethod; DiagnosticDescriptor rule; if (targetMethod == null) { return; } if (referenceEqualsMethod.Equals(targetMethod)) { rule = MethodRule; } else if (comparerEqualsMethod != null && comparerEqualsMethod.Equals(targetMethod)) { rule = ComparerRule; } else { return; } foreach (var argument in invocationExpression.Arguments) { var val = argument.Value; // Only check through one level of conversion, // which will be either the boxing conversion to object, // or a reference type implicit conversion to object. if (val is IConversionOperation conversion) { val = conversion.Operand; } if (val.Type?.IsValueType == true) { operationContext.ReportDiagnostic( val.CreateDiagnostic( rule, val.Type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); } } }, OperationKind.Invocation); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(csaContext => { #region "Get All the WellKnown Types and Members" var iformatProviderType = csaContext.Compilation.GetTypeByMetadataName("System.IFormatProvider"); var cultureInfoType = csaContext.Compilation.GetTypeByMetadataName("System.Globalization.CultureInfo"); if (iformatProviderType == null || cultureInfoType == null) { return; } var objectType = csaContext.Compilation.GetSpecialType(SpecialType.System_Object); var stringType = csaContext.Compilation.GetSpecialType(SpecialType.System_String); var stringFormatMembers = stringType?.GetMembers("Format").OfType <IMethodSymbol>(); var stringFormatMemberWithStringAndObjectParameter = stringFormatMembers.GetSingleOrDefaultMemberWithParameterInfos( GetParameterInfo(stringType), GetParameterInfo(objectType)); var stringFormatMemberWithStringObjectAndObjectParameter = stringFormatMembers.GetSingleOrDefaultMemberWithParameterInfos( GetParameterInfo(stringType), GetParameterInfo(objectType), GetParameterInfo(objectType)); var stringFormatMemberWithStringObjectObjectAndObjectParameter = stringFormatMembers.GetSingleOrDefaultMemberWithParameterInfos( GetParameterInfo(stringType), GetParameterInfo(objectType), GetParameterInfo(objectType), GetParameterInfo(objectType)); var stringFormatMemberWithStringAndParamsObjectParameter = stringFormatMembers.GetSingleOrDefaultMemberWithParameterInfos( GetParameterInfo(stringType), GetParameterInfo(objectType, isArray: true, arrayRank: 1, isParams: true)); var stringFormatMemberWithIFormatProviderStringAndParamsObjectParameter = stringFormatMembers.GetSingleOrDefaultMemberWithParameterInfos( GetParameterInfo(iformatProviderType), GetParameterInfo(stringType), GetParameterInfo(objectType, isArray: true, arrayRank: 1, isParams: true)); var currentCultureProperty = cultureInfoType?.GetMembers("CurrentCulture").OfType <IPropertySymbol>().SingleOrDefault(); var invariantCultureProperty = cultureInfoType?.GetMembers("InvariantCulture").OfType <IPropertySymbol>().SingleOrDefault(); var currentUICultureProperty = cultureInfoType?.GetMembers("CurrentUICulture").OfType <IPropertySymbol>().SingleOrDefault(); var installedUICultureProperty = cultureInfoType?.GetMembers("InstalledUICulture").OfType <IPropertySymbol>().SingleOrDefault(); var threadType = csaContext.Compilation.GetTypeByMetadataName("System.Threading.Thread"); var currentThreadCurrentUICultureProperty = threadType?.GetMembers("CurrentUICulture").OfType <IPropertySymbol>().SingleOrDefault(); var activatorType = csaContext.Compilation.GetTypeByMetadataName("System.Activator"); var resourceManagerType = csaContext.Compilation.GetTypeByMetadataName("System.Resources.ResourceManager"); var computerInfoType = csaContext.Compilation.GetTypeByMetadataName("Microsoft.VisualBasic.Devices.ComputerInfo"); var installedUICulturePropertyOfComputerInfoType = computerInfoType?.GetMembers("InstalledUICulture").OfType <IPropertySymbol>().SingleOrDefault(); var obsoleteAttributeType = WellKnownTypes.ObsoleteAttribute(csaContext.Compilation); #endregion csaContext.RegisterOperationAction(oaContext => { var invocationExpression = (IInvocationOperation)oaContext.Operation; var targetMethod = invocationExpression.TargetMethod; #region "Exceptions" if (targetMethod.IsGenericMethod || targetMethod.ContainingType == null || targetMethod.ContainingType.IsErrorType() || (targetMethod.ContainingType != null && (activatorType != null && activatorType.Equals(targetMethod.ContainingType)) || (resourceManagerType != null && resourceManagerType.Equals(targetMethod.ContainingType)))) { return; } #endregion #region "IFormatProviderAlternateStringRule Only" if (stringType != null && cultureInfoType != null && (targetMethod.Equals(stringFormatMemberWithStringAndObjectParameter) || targetMethod.Equals(stringFormatMemberWithStringObjectAndObjectParameter) || targetMethod.Equals(stringFormatMemberWithStringObjectObjectAndObjectParameter) || targetMethod.Equals(stringFormatMemberWithStringAndParamsObjectParameter))) { // Sample message for IFormatProviderAlternateStringRule: Because the behavior of string.Format(string, object) could vary based on the current user's locale settings, // replace this call in IFormatProviderStringTest.M() with a call to string.Format(IFormatProvider, string, params object[]). oaContext.ReportDiagnostic( invocationExpression.Syntax.CreateDiagnostic( IFormatProviderAlternateStringRule, targetMethod.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat), oaContext.ContainingSymbol.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat), stringFormatMemberWithIFormatProviderStringAndParamsObjectParameter.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat))); return; } #endregion #region "IFormatProviderAlternateStringRule & IFormatProviderAlternateRule" IEnumerable <IMethodSymbol> methodsWithSameNameAsTargetMethod = targetMethod.ContainingType.GetMembers(targetMethod.Name).OfType <IMethodSymbol>().WhereMethodDoesNotContainAttribute(obsoleteAttributeType).ToList(); if (methodsWithSameNameAsTargetMethod.Count() > 1) { var correctOverloads = methodsWithSameNameAsTargetMethod.GetMethodOverloadsWithDesiredParameterAtLeadingOrTrailing(targetMethod, iformatProviderType).ToList(); // If there are two matching overloads, one with CultureInfo as the first parameter and one with CultureInfo as the last parameter, // report the diagnostic on the overload with CultureInfo as the last parameter, to match the behavior of FxCop. var correctOverload = correctOverloads.FirstOrDefault(overload => overload.Parameters.Last().Type.Equals(iformatProviderType)) ?? correctOverloads.FirstOrDefault(); // Sample message for IFormatProviderAlternateRule: Because the behavior of Convert.ToInt64(string) could vary based on the current user's locale settings, // replace this call in IFormatProviderStringTest.TestMethod() with a call to Convert.ToInt64(string, IFormatProvider). if (correctOverload != null) { oaContext.ReportDiagnostic( invocationExpression.Syntax.CreateDiagnostic( targetMethod.ReturnType.Equals(stringType) ? IFormatProviderAlternateStringRule : IFormatProviderAlternateRule, targetMethod.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat), oaContext.ContainingSymbol.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat), correctOverload.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat))); } } #endregion #region "UICultureStringRule & UICultureRule" IEnumerable <int> IformatProviderParameterIndices = GetIndexesOfParameterType(targetMethod, iformatProviderType); foreach (var index in IformatProviderParameterIndices) { var argument = invocationExpression.Arguments[index]; if (argument != null && currentUICultureProperty != null && installedUICultureProperty != null && currentThreadCurrentUICultureProperty != null) { var semanticModel = oaContext.Compilation.GetSemanticModel(argument.Syntax.SyntaxTree); var symbol = semanticModel.GetSymbolInfo(argument.Value.Syntax).Symbol; if (symbol != null && (symbol.Equals(currentUICultureProperty) || symbol.Equals(installedUICultureProperty) || symbol.Equals(currentThreadCurrentUICultureProperty) || (installedUICulturePropertyOfComputerInfoType != null && symbol.Equals(installedUICulturePropertyOfComputerInfoType)))) { // Sample message // 1. UICultureStringRule - 'TestClass.TestMethod()' passes 'Thread.CurrentUICulture' as the 'IFormatProvider' parameter to 'TestClass.CalleeMethod(string, IFormatProvider)'. // This property returns a culture that is inappropriate for formatting methods. // 2. UICultureRule -'TestClass.TestMethod()' passes 'CultureInfo.CurrentUICulture' as the 'IFormatProvider' parameter to 'TestClass.Callee(IFormatProvider, string)'. // This property returns a culture that is inappropriate for formatting methods. oaContext.ReportDiagnostic( invocationExpression.Syntax.CreateDiagnostic( targetMethod.ReturnType.Equals(stringType) ? UICultureStringRule : UICultureRule, oaContext.ContainingSymbol.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat), symbol.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat), targetMethod.ToDisplayString(SymbolDisplayFormats.ShortSymbolDisplayFormat))); } } } #endregion }, OperationKind.Invocation); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out var disposeAnalysisHelper)) { return; } var reportedLocations = new ConcurrentDictionary <Location, bool>(); compilationContext.RegisterOperationBlockAction(operationBlockContext => { if (operationBlockContext.OwningSymbol is not IMethodSymbol containingMethod || !disposeAnalysisHelper.HasAnyDisposableCreationDescendant(operationBlockContext.OperationBlocks, containingMethod) || operationBlockContext.Options.IsConfiguredToSkipAnalysis(NotDisposedRule, containingMethod, operationBlockContext.Compilation)) { return; } var disposeAnalysisKind = operationBlockContext.Options.GetDisposeAnalysisKindOption(NotDisposedOnExceptionPathsRule, containingMethod, operationBlockContext.Compilation, DisposeAnalysisKind.NonExceptionPaths); var trackExceptionPaths = disposeAnalysisKind.AreExceptionPathsEnabled(); // For non-exception paths analysis, we can skip interprocedural analysis for certain invocations. var interproceduralAnalysisPredicate = !trackExceptionPaths ? new InterproceduralAnalysisPredicate( skipAnalysisForInvokedMethodPredicate: SkipInterproceduralAnalysis, skipAnalysisForInvokedLambdaOrLocalFunctionPredicate: null, skipAnalysisForInvokedContextPredicate: null) : null; if (disposeAnalysisHelper.TryGetOrComputeResult(operationBlockContext.OperationBlocks, containingMethod, operationBlockContext.Options, NotDisposedRule, PointsToAnalysisKind.PartialWithoutTrackingFieldsAndProperties, trackInstanceFields: false, trackExceptionPaths: trackExceptionPaths, disposeAnalysisResult: out var disposeAnalysisResult, pointsToAnalysisResult: out var pointsToAnalysisResult, interproceduralAnalysisPredicate: interproceduralAnalysisPredicate)) { using var notDisposedDiagnostics = ArrayBuilder <Diagnostic> .GetInstance(); using var mayBeNotDisposedDiagnostics = ArrayBuilder <Diagnostic> .GetInstance(); // Compute diagnostics for undisposed objects at exit block for non-exceptional exit paths. var exitBlock = disposeAnalysisResult.ControlFlowGraph.GetExit(); var disposeDataAtExit = disposeAnalysisResult.ExitBlockOutput.Data; ComputeDiagnostics(disposeDataAtExit, notDisposedDiagnostics, mayBeNotDisposedDiagnostics, disposeAnalysisResult, pointsToAnalysisResult, disposeAnalysisKind, isDisposeDataForExceptionPaths: false); if (trackExceptionPaths) { // Compute diagnostics for undisposed objects at handled exception exit paths. var disposeDataAtHandledExceptionPaths = disposeAnalysisResult.ExceptionPathsExitBlockOutput !.Data; ComputeDiagnostics(disposeDataAtHandledExceptionPaths, notDisposedDiagnostics, mayBeNotDisposedDiagnostics, disposeAnalysisResult, pointsToAnalysisResult, disposeAnalysisKind, isDisposeDataForExceptionPaths: true); // Compute diagnostics for undisposed objects at unhandled exception exit paths, if any. var disposeDataAtUnhandledExceptionPaths = disposeAnalysisResult.MergedStateForUnhandledThrowOperations?.Data; if (disposeDataAtUnhandledExceptionPaths != null) { ComputeDiagnostics(disposeDataAtUnhandledExceptionPaths, notDisposedDiagnostics, mayBeNotDisposedDiagnostics, disposeAnalysisResult, pointsToAnalysisResult, disposeAnalysisKind, isDisposeDataForExceptionPaths: true); } } if (!notDisposedDiagnostics.Any() && !mayBeNotDisposedDiagnostics.Any()) { return; } // Report diagnostics preferring *not* disposed diagnostics over may be not disposed diagnostics // and avoiding duplicates. foreach (var diagnostic in notDisposedDiagnostics.Concat(mayBeNotDisposedDiagnostics)) { if (reportedLocations.TryAdd(diagnostic.Location, true)) { operationBlockContext.ReportDiagnostic(diagnostic); } } } }); return; // Local functions. bool SkipInterproceduralAnalysis(IMethodSymbol invokedMethod) { // Skip interprocedural analysis if we are invoking a method and not passing any disposable object as an argument // and not receiving a disposable object as a return value. // We also check that we are not passing any object type argument which might hold disposable object // and also check that we are not passing delegate type argument which can // be a lambda or local function that has access to disposable object in current method's scope. if (CanBeDisposable(invokedMethod.ReturnType)) { return(false); } foreach (var p in invokedMethod.Parameters) { if (CanBeDisposable(p.Type)) { return(false); } } return(true); bool CanBeDisposable(ITypeSymbol type) => type.SpecialType == SpecialType.System_Object || type.DerivesFrom(disposeAnalysisHelper !.IDisposable) || type.TypeKind == TypeKind.Delegate; } }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterOperationBlockStartActionInternal(osContext => { var method = osContext.OwningSymbol as IMethodSymbol; if (method == null) { return; } osContext.RegisterOperationActionInternal(opContext => { IOperation expression = ((IExpressionStatement)opContext.Operation).Expression; DiagnosticDescriptor rule = null; string targetMethodName = null; switch (expression.Kind) { case OperationKind.ObjectCreationExpression: IMethodSymbol ctor = ((IObjectCreationExpression)expression).Constructor; if (ctor != null) { rule = ObjectCreationRule; targetMethodName = ctor.ContainingType.Name; } break; case OperationKind.InvocationExpression: IInvocationExpression invocationExpression = ((IInvocationExpression)expression); IMethodSymbol targetMethod = invocationExpression.TargetMethod; if (targetMethod == null) { break; } if (IsStringCreatingMethod(targetMethod)) { rule = StringCreationRule; } else if (IsTryParseMethod(targetMethod)) { rule = TryParseRule; } else if (IsHResultOrErrorCodeReturningMethod(targetMethod)) { rule = HResultOrErrorCodeRule; } else if (IsPureMethod(targetMethod, opContext.Compilation)) { rule = PureMethodRule; } targetMethodName = targetMethod.Name; break; } if (rule != null) { Diagnostic diagnostic = Diagnostic.Create(rule, expression.Syntax.GetLocation(), method.Name, targetMethodName); opContext.ReportDiagnostic(diagnostic); } }, OperationKind.ExpressionStatement); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { var attributeTokenType = compilationContext.Compilation.GetTypeByMetadataName("SkipNamedAttribute"); var objectType = compilationContext.Compilation.GetSpecialType(SpecialType.System_Object); var taskTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task"); var taskGenericTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1"); var valueTaskTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask"); var valueTaskGenericTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask`1"); var taskCompletionSourceType = compilationContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.TaskCompletionSource`1"); var methodBaseTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Reflection.MethodBase"); var fieldInfoTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Reflection.FieldInfo"); var propertyInfoTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Reflection.PropertyInfo"); var msTestAssertTokenType = compilationContext.Compilation.GetTypeByMetadataName("Microsoft.VisualStudio.TestTools.UnitTesting.Assert"); var nunitAssertTokenType = compilationContext.Compilation.GetTypeByMetadataName("NUnit.Framework.Assert"); var xunitAssertTokenType = compilationContext.Compilation.GetTypeByMetadataName("Xunit.Assert"); var keyValuePairTokenType = compilationContext.Compilation.GetTypeByMetadataName("System.Collection.Generic.KeyValuePair`2"); var propertyBuilderType = compilationContext.Compilation.GetTypeByMetadataName("Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder`1"); var syntaxNodeType = compilationContext.Compilation.GetTypeByMetadataName("Microsoft.CodeAnalysis.SyntaxNode"); compilationContext.RegisterSyntaxNodeAction(syntaxContext => { var argument = (ArgumentSyntax)syntaxContext.Node; if (argument.NameColon != null) { return; } if (argument.Expression == null) { return; } var kind = argument.Expression.Kind(); if (kind == SyntaxKind.TrueLiteralExpression || kind == SyntaxKind.FalseLiteralExpression || kind == SyntaxKind.NullLiteralExpression) { // Exclude in some methods such as ConfigureAwait(false) var invocationExpression = argument.FirstAncestorOrSelf <InvocationExpressionSyntax>(); if (invocationExpression != null) { var methodSymbol = (IMethodSymbol?)syntaxContext.SemanticModel.GetSymbolInfo(invocationExpression).Symbol; if (methodSymbol != null) { var argumentIndex = ArgumentIndex(argument); if (methodSymbol.Parameters.Length == 1 && methodSymbol.Name.StartsWith("Is", StringComparison.Ordinal)) { return; } if (methodSymbol.Parameters.Length == 1 && methodSymbol.Name == nameof(Task.ConfigureAwait)) { return; } if (IsMethod(methodSymbol, objectType, nameof(object.Equals))) { return; } if (IsMethod(methodSymbol, objectType, nameof(object.ReferenceEquals))) { return; } if (IsMethod(methodSymbol, taskTokenType, nameof(Task.FromResult))) { return; } if (IsMethod(methodSymbol, taskCompletionSourceType, nameof(TaskCompletionSource <object> .SetResult))) { return; } if (IsMethod(methodSymbol, taskCompletionSourceType, nameof(TaskCompletionSource <object> .TrySetResult))) { return; } if (IsMethod(methodSymbol, methodBaseTokenType, nameof(MethodBase.Invoke)) && argumentIndex == 0) { return; } if (IsMethod(methodSymbol, fieldInfoTokenType, nameof(FieldInfo.SetValue)) && argumentIndex == 0) { return; } if (IsMethod(methodSymbol, fieldInfoTokenType, nameof(FieldInfo.GetValue)) && argumentIndex == 0) { return; } if (IsMethod(methodSymbol, propertyInfoTokenType, nameof(PropertyInfo.SetValue)) && argumentIndex == 0) { return; } if (IsMethod(methodSymbol, propertyInfoTokenType, nameof(PropertyInfo.GetValue)) && argumentIndex == 0) { return; } if (IsMethod(methodSymbol, msTestAssertTokenType, "*")) { return; } if (IsMethod(methodSymbol, nunitAssertTokenType, "*")) { return; } if (IsMethod(methodSymbol, xunitAssertTokenType, "*")) { return; } if ((string.Equals(methodSymbol.Name, "Parse", StringComparison.Ordinal) || string.Equals(methodSymbol.Name, "TryParse", StringComparison.Ordinal)) && argumentIndex == 0) { return; } // e.g. SyntaxNode.WithElse if (methodSymbol.Name.StartsWith("With", StringComparison.Ordinal) && methodSymbol.ContainingType.IsOrInheritFrom(syntaxNodeType)) { return; } var operation = syntaxContext.SemanticModel.GetOperation(argument, syntaxContext.CancellationToken); if (operation != null && operation.IsInExpressionArgument()) { return; } } } syntaxContext.ReportDiagnostic(s_rule, syntaxContext.Node); } }, SyntaxKind.Argument); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSyntaxNodeAction(AnalyzeNode, ImmutableArray.Create(SyntaxKind.LocalDeclarationStatement)); }
public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(AnalyzeIdentifierGuid, SyntaxKind.IdentifierName); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterSymbolAction(AnalyzeNamedType, SymbolKind.NamedType); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { var formatInfo = new StringFormatInfo(compilationContext.Compilation); compilationContext.RegisterOperationAction(operationContext => { var invocation = (IInvocationOperation)operationContext.Operation; StringFormatInfo.Info?info = formatInfo.TryGet(invocation.TargetMethod, operationContext); if (info == null || invocation.Arguments.Length <= info.FormatStringIndex) { // not a target method return; } IArgumentOperation formatStringArgument = invocation.Arguments[info.FormatStringIndex]; if (!object.Equals(formatStringArgument?.Value?.Type, formatInfo.String) || !(formatStringArgument?.Value?.ConstantValue.Value is string)) { // wrong argument return; } var stringFormat = (string)formatStringArgument.Value.ConstantValue.Value; int expectedStringFormatArgumentCount = GetFormattingArguments(stringFormat); // explicit parameter case if (info.ExpectedStringFormatArgumentCount >= 0) { // __arglist is not supported here if (invocation.TargetMethod.IsVararg) { // can't deal with this for now. return; } if (info.ExpectedStringFormatArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } return; } // ensure argument is an array IArgumentOperation paramsArgument = invocation.Arguments[info.FormatStringIndex + 1]; if (paramsArgument.ArgumentKind is not ArgumentKind.ParamArray and not ArgumentKind.Explicit) { // wrong format return; } if (paramsArgument.Value is not IArrayCreationOperation arrayCreation || arrayCreation.GetElementType() is not ITypeSymbol elementType || !object.Equals(elementType, formatInfo.Object) || arrayCreation.DimensionSizes.Length != 1) { // wrong format return; } // compiler generating object array for params case IArrayInitializerOperation intializer = arrayCreation.Initializer; if (intializer == null) { // unsupported format return; } // REVIEW: "ElementValues" is a bit confusing where I need to double dot those to get number of elements int actualArgumentCount = intializer.ElementValues.Length; if (actualArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } }, OperationKind.Invocation); }); }
public override void Initialize(AnalysisContext context) { Debug.Assert(TypeMetadataName != null); Debug.Assert(MethodMetadataName != null); Debug.Assert(Rule != null); context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction(compilationStartAnalysisContext => { var compilation = compilationStartAnalysisContext.Compilation; var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation); if (!wellKnownTypeProvider.TryGetTypeByMetadataName( TypeMetadataName, out INamedTypeSymbol xmlSchemaTypeSymbol)) { return; } wellKnownTypeProvider.TryGetTypeByMetadataName( WellKnownTypeNames.SystemXmlXmlReader, out INamedTypeSymbol xmlReaderTypeSymbol); compilationStartAnalysisContext.RegisterOperationAction(operationAnalysisContext => { var operation = operationAnalysisContext.Operation; IMethodSymbol methodSymbol = null; string methodName = null; switch (operation.Kind) { case OperationKind.Invocation: methodSymbol = (operation as IInvocationOperation).TargetMethod; methodName = methodSymbol.Name; break; case OperationKind.ObjectCreation: methodSymbol = (operation as IObjectCreationOperation).Constructor; methodName = methodSymbol.ContainingType.Name; break; default: return; } if (methodName.StartsWith(MethodMetadataName, StringComparison.Ordinal) && methodSymbol.IsOverrideOrVirtualMethodOf(xmlSchemaTypeSymbol)) { if (xmlReaderTypeSymbol != null && methodSymbol.Parameters.Length > 0 && methodSymbol.Parameters[0].Type.Equals(xmlReaderTypeSymbol)) { return; } operationAnalysisContext.ReportDiagnostic( operation.CreateDiagnostic( Rule, methodSymbol.ContainingType.Name, methodName)); } }, OperationKind.Invocation, OperationKind.ObjectCreation); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(AnalyzeCompilationStart); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(x => Handle(x), SyntaxKind.Argument); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); // Analyze type names. analysisContext.RegisterCompilationStartAction( compilationStartAnalysisContext => { var suffixToBaseTypeDictionaryBuilder = ImmutableDictionary.CreateBuilder <string, ImmutableArray <INamedTypeSymbol> >(); foreach (string suffix in s_suffixToBaseTypeNamesDictionary.Keys) { ImmutableArray <string> typeNames = s_suffixToBaseTypeNamesDictionary[suffix]; ImmutableArray <INamedTypeSymbol> namedTypeSymbolArray = ImmutableArray.CreateRange( typeNames.Select(typeName => compilationStartAnalysisContext.Compilation.GetOrCreateTypeByMetadataName(typeName)?.OriginalDefinition).WhereNotNull()); suffixToBaseTypeDictionaryBuilder.Add(suffix, namedTypeSymbolArray); } var suffixToBaseTypeDictionary = suffixToBaseTypeDictionaryBuilder.ToImmutableDictionary(); compilationStartAnalysisContext.RegisterSymbolAction( (SymbolAnalysisContext symbolAnalysisContext) => { var namedTypeSymbol = (INamedTypeSymbol)symbolAnalysisContext.Symbol; // Note all the descriptors/rules for this analyzer have the same ID and category and hence // will always have identical configured visibility. if (!symbolAnalysisContext.Options.MatchesConfiguredVisibility(TypeNoAlternateRule, namedTypeSymbol, symbolAnalysisContext.Compilation, symbolAnalysisContext.CancellationToken)) { return; } var allowedSuffixes = symbolAnalysisContext.Options.GetStringOptionValue(EditorConfigOptionNames.AllowedSuffixes, TypeNoAlternateRule, namedTypeSymbol.Locations[0].SourceTree, symbolAnalysisContext.Compilation, symbolAnalysisContext.CancellationToken) .Split('|') .ToImmutableHashSet(); string name = namedTypeSymbol.Name; Compilation compilation = symbolAnalysisContext.Compilation; foreach (string suffix in s_suffixToBaseTypeNamesDictionary.Keys) { if (IsNotChildOfAnyButHasSuffix(namedTypeSymbol, suffixToBaseTypeDictionary[suffix], suffix, allowedSuffixes)) { symbolAnalysisContext.ReportDiagnostic( namedTypeSymbol.CreateDiagnostic(TypeNoAlternateRule, name, suffix)); return; } } foreach (string suffix in s_suffixToAllowedTypesDictionary.Keys) { if (IsInvalidSuffix(name, suffix, allowedSuffixes) && !s_suffixToAllowedTypesDictionary[suffix].Contains(name)) { symbolAnalysisContext.ReportDiagnostic( namedTypeSymbol.CreateDiagnostic(TypeNoAlternateRule, name, suffix)); return; } } if (IsInvalidSuffix(name, ImplSuffix, allowedSuffixes)) { symbolAnalysisContext.ReportDiagnostic( namedTypeSymbol.CreateDiagnostic(MemberWithAlternateRule, ImplSuffix, name, CoreSuffix)); return; } // FxCop performed the length check for "Ex", but not for any of the other // suffixes, because alone among the suffixes, "Ex" is the only one that // isn't itself a known type or a language keyword. if (IsInvalidSuffix(name, ExSuffix, allowedSuffixes) && name.Length > ExSuffix.Length) { symbolAnalysisContext.ReportDiagnostic( namedTypeSymbol.CreateDiagnostic(TypeNewerVersionRule, ExSuffix, name)); return; } if (IsInvalidSuffix(name, NewSuffix, allowedSuffixes)) { symbolAnalysisContext.ReportDiagnostic( namedTypeSymbol.CreateDiagnostic(TypeNewerVersionRule, NewSuffix, name)); return; } if (namedTypeSymbol.TypeKind == TypeKind.Enum) { if (IsInvalidSuffix(name, FlagSuffix, allowedSuffixes)) { symbolAnalysisContext.ReportDiagnostic( namedTypeSymbol.CreateDiagnostic(TypeNoAlternateRule, name, FlagSuffix)); return; } if (IsInvalidSuffix(name, FlagsSuffix, allowedSuffixes)) { symbolAnalysisContext.ReportDiagnostic( namedTypeSymbol.CreateDiagnostic(TypeNoAlternateRule, name, FlagsSuffix)); return; } } }, SymbolKind.NamedType); }); // Analyze method names. analysisContext.RegisterSymbolAction( (SymbolAnalysisContext context) => { var memberSymbol = context.Symbol; // Note all the descriptors/rules for this analyzer have the same ID and category and hence // will always have identical configured visibility. if (!context.Options.MatchesConfiguredVisibility(TypeNoAlternateRule, memberSymbol, context.Compilation, context.CancellationToken)) { return; } if (memberSymbol.IsOverride || memberSymbol.IsImplementationOfAnyInterfaceMember()) { return; } // If this is a method, and it's actually the getter or setter of a property, // then don't complain. We'll complain about the property itself. if (memberSymbol is IMethodSymbol methodSymbol && methodSymbol.IsPropertyAccessor()) { return; } string name = memberSymbol.Name; var allowedSuffixes = context.Options.GetStringOptionValue(EditorConfigOptionNames.AllowedSuffixes, TypeNoAlternateRule, memberSymbol.Locations[0].SourceTree, context.Compilation, context.CancellationToken) .Split('|') .ToImmutableHashSet(); if (IsInvalidSuffix(name, ExSuffix, allowedSuffixes)) { context.ReportDiagnostic( memberSymbol.CreateDiagnostic(MemberNewerVersionRule, ExSuffix, name)); return; } // We only fire on member suffix "New" if the type already defines // another member minus the suffix, e.g., we only fire on "MemberNew" if // "Member" already exists. For some reason FxCop did not apply the // same logic to the "Ex" suffix, and we follow FxCop's implementation. if (IsInvalidSuffix(name, NewSuffix, allowedSuffixes)) { string nameWithoutSuffix = name.WithoutSuffix(NewSuffix); INamedTypeSymbol containingType = memberSymbol.ContainingType; if (MemberNameExistsInHierarchy(nameWithoutSuffix, containingType, memberSymbol.Kind)) { context.ReportDiagnostic( memberSymbol.CreateDiagnostic(MemberNewerVersionRule, NewSuffix, name)); return; } } if (IsInvalidSuffix(name, ImplSuffix, allowedSuffixes)) { context.ReportDiagnostic( memberSymbol.CreateDiagnostic(MemberWithAlternateRule, ImplSuffix, name, CoreSuffix)); } }, SymbolKind.Event, SymbolKind.Field, SymbolKind.Method, SymbolKind.Property); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterSyntaxNodeAction(AnalyzeMethodDeclaration, SyntaxKind.MethodDeclaration); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol?iDbCommandType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataIDbCommand); INamedTypeSymbol?iDataAdapterType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataIDataAdapter); IPropertySymbol?commandTextProperty = iDbCommandType?.GetMembers("CommandText").OfType <IPropertySymbol>().FirstOrDefault(); if (iDbCommandType == null || iDataAdapterType == null || commandTextProperty == null) { return; } compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { ISymbol symbol = operationBlockStartContext.OwningSymbol; var isInDbCommandConstructor = false; var isInDataAdapterConstructor = false; if (symbol.Kind != SymbolKind.Method) { return; } var methodSymbol = (IMethodSymbol)symbol; if (methodSymbol.MethodKind == MethodKind.Constructor) { CheckForDbCommandAndDataAdapterImplementation(symbol.ContainingType, iDbCommandType, iDataAdapterType, out isInDbCommandConstructor, out isInDataAdapterConstructor); } operationBlockStartContext.RegisterOperationAction(operationContext => { var creation = (IObjectCreationOperation)operationContext.Operation; AnalyzeMethodCall(operationContext, creation.Constructor, symbol, creation.Arguments, creation.Syntax, isInDbCommandConstructor, isInDataAdapterConstructor, iDbCommandType, iDataAdapterType); }, OperationKind.ObjectCreation); // If an object calls a constructor in a base class or the same class, this will get called. operationBlockStartContext.RegisterOperationAction(operationContext => { var invocation = (IInvocationOperation)operationContext.Operation; // We only analyze constructor invocations if (invocation.TargetMethod.MethodKind != MethodKind.Constructor) { return; } // If we're calling another constructor in the same class from this constructor, assume that all parameters are safe and skip analysis. Parameter usage // will be analyzed there if (Equals(invocation.TargetMethod.ContainingType, symbol.ContainingType)) { return; } AnalyzeMethodCall(operationContext, invocation.TargetMethod, symbol, invocation.Arguments, invocation.Syntax, isInDbCommandConstructor, isInDataAdapterConstructor, iDbCommandType, iDataAdapterType); }, OperationKind.Invocation); operationBlockStartContext.RegisterOperationAction(operationContext => { var propertyReference = (IPropertyReferenceOperation)operationContext.Operation; // We're only interested in implementations of IDbCommand.CommandText if (!propertyReference.Property.IsOverrideOrImplementationOfInterfaceMember(commandTextProperty)) { return; } // Make sure we're in assignment statement if (!(propertyReference.Parent is IAssignmentOperation assignment)) { return; } // Only if the property reference is actually the target of the assignment if (assignment.Target != propertyReference) { return; } ReportDiagnosticIfNecessary(operationContext, assignment.Value, assignment.Syntax, propertyReference.Property, symbol); }, OperationKind.PropertyReference); }); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.RegisterOperationAction(AnalyzeInvocationOp, OperationKind.Invocation); }
/// <inheritdoc/> public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(Handle, SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration); }