Exemplo n.º 1
0
        public static void AnalyzeNamedType(SymbolAnalysisContext context, INamedTypeSymbol flagsAttribute)
        {
            var enumSymbol = (INamedTypeSymbol)context.Symbol;

            if (enumSymbol.IsEnum() &&
                enumSymbol.HasAttribute(flagsAttribute))
            {
                var infos = default(ImmutableArray <EnumFieldInfo>);

                foreach (ISymbol member in enumSymbol.GetMembers())
                {
                    if (member.IsField())
                    {
                        var fieldSymbol = (IFieldSymbol)member;

                        if (!fieldSymbol.HasConstantValue)
                        {
                            break;
                        }

                        var info = new EnumFieldInfo(fieldSymbol);

                        if (info.IsComposite())
                        {
                            var declaration = (EnumMemberDeclarationSyntax)info.Symbol.GetSyntax(context.CancellationToken);

                            ExpressionSyntax valueExpression = declaration.EqualsValue?.Value;

                            if (valueExpression != null &&
                                (valueExpression.IsKind(SyntaxKind.NumericLiteralExpression) ||
                                 valueExpression
                                 .DescendantNodes()
                                 .Any(f => f.IsKind(SyntaxKind.NumericLiteralExpression))))
                            {
                                if (infos.IsDefault)
                                {
                                    infos = EnumFieldInfo.CreateRange(enumSymbol);

                                    if (infos.IsDefault)
                                    {
                                        break;
                                    }
                                }

                                List <EnumFieldInfo> values = info.Decompose(infos);

                                if (values?.Count > 1)
                                {
                                    context.ReportDiagnostic(
                                        DiagnosticDescriptors.DeclareEnumValueAsCombinationOfNames,
                                        valueExpression);
                                }
                            }
                        }
                    }
                }
            }
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            EnumMemberDeclarationSyntax enumMemberDeclaration,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            IFieldSymbol enumMemberSymbol = semanticModel.GetDeclaredSymbol(enumMemberDeclaration, cancellationToken);

            ImmutableArray <EnumFieldInfo> infos = EnumFieldInfo.CreateRange(enumMemberSymbol.ContainingType);

            ExpressionSyntax value = enumMemberDeclaration.EqualsValue?.Value;

            var info = new EnumFieldInfo(enumMemberSymbol);

            List <EnumFieldInfo> values = info.Decompose(infos);

            values.Sort((f, g) =>
            {
                if (f.IsComposite())
                {
                    if (g.IsComposite())
                    {
                        return(((IComparable)f.Value).CompareTo((IComparable)g.Value));
                    }
                    else
                    {
                        return(-1);
                    }
                }
                else if (g.IsComposite())
                {
                    return(1);
                }

                return(((IComparable)f.Value).CompareTo((IComparable)g.Value));
            });

            BinaryExpressionSyntax newValue = BitwiseOrExpression(values[0].ToIdentifierName(), values[1].ToIdentifierName());

            for (int i = 2; i < values.Count; i++)
            {
                newValue = BitwiseOrExpression(newValue, values[i].ToIdentifierName());
            }

            newValue = newValue.WithFormatterAnnotation();

            return(await document.ReplaceNodeAsync(value, newValue, cancellationToken).ConfigureAwait(false));
        }