protected override void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action <Diagnostic> addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) { if (symbol.TypeKind != TypeKind.Enum) { return; } var flagsAttribute = WellKnownTypes.FlagsAttribute(compilation); if (flagsAttribute == null) { return; } var zeroValuedFields = GetZeroValuedFields(symbol).ToImmutableArray(); bool hasFlagsAttribute = symbol.GetAttributes().Any(a => a.AttributeClass == flagsAttribute); if (hasFlagsAttribute) { CheckFlags(symbol, zeroValuedFields, addDiagnostic); } else { CheckNonFlags(symbol, zeroValuedFields, addDiagnostic); } }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol flagsAttribute = WellKnownTypes.FlagsAttribute(compilationContext.Compilation); compilationContext.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, flagsAttribute), SymbolKind.NamedType); }); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); INamedTypeSymbol flagsAttributeType = WellKnownTypes.FlagsAttribute(model.Compilation); if (flagsAttributeType == null) { return; } foreach (var diagnostic in context.Diagnostics) { SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(context.Span); ISymbol declaredSymbol = model.GetDeclaredSymbol(node, context.CancellationToken); Debug.Assert(declaredSymbol != null); string title; foreach (string customTag in diagnostic.Descriptor.CustomTags) { switch (customTag) { case EnumsShouldHaveZeroValueAnalyzer.RuleRenameCustomTag: title = MicrosoftCodeQualityAnalyzersResources.EnumsShouldZeroValueFlagsRenameCodeFix; context.RegisterCodeFix(new MyCodeAction(title, async ct => await GetUpdatedDocumentForRuleNameRenameAsync(context.Document, (IFieldSymbol)declaredSymbol, context.CancellationToken).ConfigureAwait(false), equivalenceKey: title), diagnostic); return; case EnumsShouldHaveZeroValueAnalyzer.RuleMultipleZeroCustomTag: title = MicrosoftCodeQualityAnalyzersResources.EnumsShouldZeroValueFlagsMultipleZeroCodeFix; context.RegisterCodeFix(new MyCodeAction(title, async ct => await ApplyRuleNameMultipleZeroAsync(context.Document, (INamedTypeSymbol)declaredSymbol, context.CancellationToken).ConfigureAwait(false), equivalenceKey: title), diagnostic); return; case EnumsShouldHaveZeroValueAnalyzer.RuleNoZeroCustomTag: title = MicrosoftCodeQualityAnalyzersResources.EnumsShouldZeroValueNotFlagsNoZeroValueCodeFix; context.RegisterCodeFix(new MyCodeAction(title, async ct => await ApplyRuleNameNoZeroValueAsync(context.Document, (INamedTypeSymbol)declaredSymbol, context.CancellationToken).ConfigureAwait(false), equivalenceKey: title), diagnostic); return; } } } }
internal sealed override Task <Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken) { var flagsAttributeType = WellKnownTypes.FlagsAttribute(model.Compilation); Contract.ThrowIfNull(flagsAttributeType); var workspace = document.Project.Solution.Workspace; var newEnumBlockSyntax = diagnostic.Id == EnumWithFlagsDiagnosticAnalyzer.RuleIdMarkEnumsWithFlags ? AddFlagsAttribute(workspace, nodeToFix, flagsAttributeType, cancellationToken) : RemoveFlagsAttribute(workspace, model, nodeToFix, flagsAttributeType, cancellationToken); var newRoot = GetUpdatedRoot(root, nodeToFix, newEnumBlockSyntax); return(Task.FromResult(document.WithSyntaxRoot(newRoot))); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol flagsAttribute = WellKnownTypes.FlagsAttribute(compilationContext.Compilation); if (flagsAttribute == null) { return; } compilationContext.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, flagsAttribute), SymbolKind.NamedType); }); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); INamedTypeSymbol flagsAttributeType = WellKnownTypes.FlagsAttribute(model.Compilation); if (flagsAttributeType == null) { return; } // We cannot have multiple overlapping diagnostics of this id. Diagnostic diagnostic = context.Diagnostics.Single(); SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(context.Span); ISymbol declaredSymbol = model.GetDeclaredSymbol(node, context.CancellationToken); Debug.Assert(declaredSymbol != null); foreach (string customTag in diagnostic.Descriptor.CustomTags) { switch (customTag) { case EnumsShouldHaveZeroValueAnalyzer.RuleRenameCustomTag: context.RegisterCodeFix(new DocumentChangeAction(MicrosoftApiDesignGuidelinesAnalyzersResources.EnumsShouldZeroValueFlagsRenameCodeFix, async ct => await GetUpdatedDocumentForRuleNameRenameAsync(context.Document, (IFieldSymbol)declaredSymbol, context.CancellationToken).ConfigureAwait(false)), diagnostic); return; case EnumsShouldHaveZeroValueAnalyzer.RuleMultipleZeroCustomTag: context.RegisterCodeFix(new DocumentChangeAction(MicrosoftApiDesignGuidelinesAnalyzersResources.EnumsShouldZeroValueFlagsMultipleZeroCodeFix, async ct => await ApplyRuleNameMultipleZeroAsync(context.Document, (INamedTypeSymbol)declaredSymbol, context.CancellationToken).ConfigureAwait(false)), diagnostic); return; case EnumsShouldHaveZeroValueAnalyzer.RuleNoZeroCustomTag: context.RegisterCodeFix(new DocumentChangeAction(MicrosoftApiDesignGuidelinesAnalyzersResources.EnumsShouldZeroValueNotFlagsNoZeroValueCodeFix, async ct => await ApplyRuleNameNoZeroValueAsync(context.Document, (INamedTypeSymbol)declaredSymbol, context.CancellationToken).ConfigureAwait(false)), diagnostic); return; } } }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationStartContext => { var flagsAttributeType = WellKnownTypes.FlagsAttribute(compilationStartContext.Compilation); if (flagsAttributeType == null) { return; } compilationStartContext.RegisterSymbolAction(symbolContext => { AnalyzeSymbol((INamedTypeSymbol)symbolContext.Symbol, flagsAttributeType, symbolContext.ReportDiagnostic); }, SymbolKind.NamedType); }); }
protected override void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action <Diagnostic> addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) { if (symbol != null && symbol.TypeKind == TypeKind.Enum && symbol.DeclaredAccessibility == Accessibility.Public) { var flagsAttributeType = WellKnownTypes.FlagsAttribute(compilation); if (flagsAttributeType == null) { return; } IList <ulong> memberValues; if (DiagnosticHelpers.TryGetEnumMemberValues(symbol, out memberValues)) { bool hasFlagsAttribute = symbol.GetAttributes().Any(a => a.AttributeClass == flagsAttributeType); if (hasFlagsAttribute) { // Check "CA2217: Do not mark enums with FlagsAttribute" IEnumerable <ulong> missingValues; if (!ShouldBeFlags(memberValues, out missingValues)) { Contract.ThrowIfNull(missingValues); var missingValuesString = missingValues.Select(v => v.ToString()).Aggregate((i, j) => i + ", " + j); var location = GetDiagnosticLocation(symbol.DeclaringSyntaxReferences[0].GetSyntax()); addDiagnostic(location.CreateDiagnostic(Rule2217, symbol.Name, missingValuesString)); } } else { // Check "CA1027: Mark enums with FlagsAttribute" // Ignore continguous value enums to reduce noise. if (!IsContiguous(memberValues) && ShouldBeFlags(memberValues)) { var location = GetDiagnosticLocation(symbol.DeclaringSyntaxReferences[0].GetSyntax()); addDiagnostic(location.CreateDiagnostic(Rule1027, symbol.Name)); } } } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); INamedTypeSymbol flagsAttributeType = WellKnownTypes.FlagsAttribute(model.Compilation); if (flagsAttributeType == null) { return; } // We cannot have multiple overlapping diagnostics of this id. Diagnostic diagnostic = context.Diagnostics.Single(); string fixTitle = diagnostic.Id == EnumWithFlagsAttributeAnalyzer.RuleIdMarkEnumsWithFlags ? MicrosoftApiDesignGuidelinesAnalyzersResources.MarkEnumsWithFlagsCodeFix : MicrosoftApiDesignGuidelinesAnalyzersResources.DoNotMarkEnumsWithFlagsCodeFix; context.RegisterCodeFix(new MyCodeAction(fixTitle, async ct => await AddOrRemoveFlagsAttribute(context.Document, context.Span, diagnostic.Id, flagsAttributeType, ct).ConfigureAwait(false)), diagnostic); }
private void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action <Diagnostic> addDiagnostic) { if (symbol != null && symbol.TypeKind == TypeKind.Enum && symbol.DeclaredAccessibility == Accessibility.Public) { INamedTypeSymbol flagsAttributeType = WellKnownTypes.FlagsAttribute(compilation); if (flagsAttributeType == null) { return; } IList <ulong> memberValues; if (EnumHelpers.TryGetEnumMemberValues(symbol, out memberValues)) { bool hasFlagsAttribute = symbol.GetAttributes().Any(a => a.AttributeClass == flagsAttributeType); if (hasFlagsAttribute) { // Check "CA2217: Do not mark enums with FlagsAttribute" IEnumerable <ulong> missingValues; if (!ShouldBeFlags(memberValues, out missingValues)) { Debug.Assert(missingValues != null); string missingValuesString = missingValues.Select(v => v.ToString()).Aggregate((i, j) => i + ", " + j); addDiagnostic(symbol.CreateDiagnostic(Rule2217, symbol.Name, missingValuesString)); } } else { // Check "CA1027: Mark enums with FlagsAttribute" // Ignore contiguous value enums to reduce noise. if (!IsContiguous(memberValues) && ShouldBeFlags(memberValues)) { addDiagnostic(symbol.CreateDiagnostic(Rule1027, symbol.Name)); } } } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); INamedTypeSymbol flagsAttributeType = WellKnownTypes.FlagsAttribute(model.Compilation); if (flagsAttributeType == null) { return; } foreach (var diagnostic in context.Diagnostics) { string fixTitle = diagnostic.Id == EnumWithFlagsAttributeAnalyzer.RuleIdMarkEnumsWithFlags ? MicrosoftCodeQualityAnalyzersResources.MarkEnumsWithFlagsCodeFix : MicrosoftCodeQualityAnalyzersResources.DoNotMarkEnumsWithFlagsCodeFix; context.RegisterCodeFix(new MyCodeAction(fixTitle, async ct => await AddOrRemoveFlagsAttribute(context.Document, context.Span, diagnostic.Id, flagsAttributeType, ct).ConfigureAwait(false), equivalenceKey: fixTitle), diagnostic); } }
public override void Initialize(AnalysisContext analysisContext) { if (!CultureInfo.CurrentCulture.Name.Equals("en", StringComparison.Ordinal) && !CultureInfo.CurrentCulture.Parent.Name.Equals("en", StringComparison.Ordinal)) { // FxCop compat: Skip for non-English cultures. return; } analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol flagsAttribute = WellKnownTypes.FlagsAttribute(compilationContext.Compilation); if (flagsAttribute == null) { return; } compilationContext.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, flagsAttribute), SymbolKind.NamedType); }); }