public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationStartContext => { var iEnumerator = WellKnownTypes.IEnumerator(compilationStartContext.Compilation); var genericIEnumerator = WellKnownTypes.GenericIEnumerator(compilationStartContext.Compilation); compilationStartContext.RegisterSymbolAction(context => { var namedType = (INamedTypeSymbol)context.Symbol; // FxCop compat: // 1. Do not fire for enums. // 2. Do not fire for enumerators. // 3. Do not fire for value types without members. // 4. Externally visible types by default. // Note all the descriptors/rules for this analyzer have the same ID and category and hence // will always have identical configured visibility. if (!namedType.IsValueType || namedType.TypeKind == TypeKind.Enum || !namedType.MatchesConfiguredVisibility(context.Options, EqualsRule, context.CancellationToken) || !namedType.GetMembers().Any(m => !m.IsConstructor())) { return; } // Enumerators are often ValueTypes to prevent heap allocation when enumerating if (iEnumerator != null && namedType.DerivesFromOrImplementsAnyConstructionOf(iEnumerator) || genericIEnumerator != null && namedType.DerivesFromOrImplementsAnyConstructionOf(genericIEnumerator)) { return; } if (!namedType.OverridesEquals()) { context.ReportDiagnostic(namedType.CreateDiagnostic(EqualsRule, namedType.Name)); } if (!namedType.ImplementsEqualityOperators()) { context.ReportDiagnostic(namedType.CreateDiagnostic(OpEqualityRule, namedType.Name)); } }, SymbolKind.NamedType); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationStartContext => { var iEnumerator = WellKnownTypes.IEnumerator(compilationStartContext.Compilation); var genericIEnumerator = WellKnownTypes.GenericIEnumerator(compilationStartContext.Compilation); compilationStartContext.RegisterSymbolAction(context => { var namedType = (INamedTypeSymbol)context.Symbol; // FxCop compat: // 1. Do not fire for enums. // 2. Do not fire for enumerators. // 3. Do not fire for value types without members. if (!namedType.IsValueType || namedType.TypeKind == TypeKind.Enum || namedType.GetResultantVisibility() != SymbolVisibility.Public || !namedType.GetMembers().Any(m => !m.IsConstructor())) { return; } // Enumerators are often ValueTypes to prevent heap allocation when enumerating if (iEnumerator != null && namedType.DerivesFromOrImplementsAnyConstructionOf(iEnumerator) || genericIEnumerator != null && namedType.DerivesFromOrImplementsAnyConstructionOf(genericIEnumerator)) { return; } if (!namedType.OverridesEquals()) { context.ReportDiagnostic(namedType.CreateDiagnostic(EqualsRule, namedType.Name)); } if (!namedType.ImplementsEqualityOperators()) { context.ReportDiagnostic(namedType.CreateDiagnostic(OpEqualityRule, namedType.Name)); } }, SymbolKind.NamedType); }); }