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);
            }
        }
Пример #2
0
 public override void Initialize(AnalysisContext analysisContext)
 {
     analysisContext.RegisterCompilationStartAction(compilationContext =>
     {
         INamedTypeSymbol flagsAttribute = WellKnownTypes.FlagsAttribute(compilationContext.Compilation);
         compilationContext.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, flagsAttribute), SymbolKind.NamedType);
     });
 }
Пример #3
0
        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;
                    }
                }
            }
        }
Пример #4
0
        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)));
        }
Пример #5
0
        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);
            });
        }
Пример #6
0
        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;
                }
            }
        }
Пример #7
0
        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));
                        }
                    }
                }
            }
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
            });
        }