Ejemplo n.º 1
0
        internal static IFieldSymbol FindEnumDefaultField(INamedTypeSymbol enumSymbol)
        {
            if (enumSymbol == null)
            {
                throw new ArgumentNullException(nameof(enumSymbol));
            }

            if (enumSymbol.EnumUnderlyingType == null)
            {
                throw new ArgumentException($"'{enumSymbol}' is not an enumeration.", nameof(enumSymbol));
            }

            foreach (ISymbol symbol in enumSymbol.GetMembers())
            {
                if (symbol.Kind == SymbolKind.Field)
                {
                    var fieldSymbol = (IFieldSymbol)symbol;

                    if (fieldSymbol.HasConstantValue &&
                        SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, enumSymbol) == 0)
                    {
                        return(fieldSymbol);
                    }
                }
            }

            return(default(IFieldSymbol));
        }
        private static async Task <Document> DeclareExplicitValueAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            INamedTypeSymbol enumSymbol,
            ImmutableArray <ulong> values,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            bool isFlags = enumSymbol.HasAttribute(MetadataNames.System_FlagsAttribute);

            List <ulong> reservedValues = values.ToList();

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members;

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> newMembers = members;

            for (int i = 0; i < members.Count; i++)
            {
                if (members[i].EqualsValue == null)
                {
                    IFieldSymbol fieldSymbol = semanticModel.GetDeclaredSymbol(members[i], cancellationToken);

                    ulong?value = null;

                    if (isFlags)
                    {
                        Optional <ulong> optional = FlagsUtility <ulong> .Instance.GetUniquePowerOfTwo(reservedValues);

                        if (optional.HasValue &&
                            ConvertHelpers.CanConvert(optional.Value, enumSymbol.EnumUnderlyingType.SpecialType))
                        {
                            value = optional.Value;
                        }
                    }
                    else
                    {
                        value = SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, enumSymbol);
                    }

                    if (value != null)
                    {
                        reservedValues.Add(value.Value);

                        EqualsValueClauseSyntax equalsValue = EqualsValueClause(NumericLiteralExpression(value.Value, enumSymbol.EnumUnderlyingType.SpecialType));

                        EnumMemberDeclarationSyntax newMember = members[i].WithEqualsValue(equalsValue);

                        newMembers = newMembers.ReplaceAt(i, newMember);
                    }
                }
            }

            EnumDeclarationSyntax newEnumDeclaration = enumDeclaration.WithMembers(newMembers);

            return(await document.ReplaceNodeAsync(enumDeclaration, newEnumDeclaration, cancellationToken).ConfigureAwait(false));
        }
Ejemplo n.º 3
0
        private static Task <Document> RefactorAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            SeparatedSyntaxListSelection <EnumMemberDeclarationSyntax> selectedMembers,
            INamedTypeSymbol enumSymbol,
            string name,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax            expression = null;
            EnumMemberDeclarationSyntax lastMember = null;

            using (IEnumerator <EnumMemberDeclarationSyntax> en = GetMembersToCombine().GetEnumerator())
            {
                if (en.MoveNext())
                {
                    lastMember = en.Current;
                    expression = IdentifierName(en.Current.Identifier.WithoutTrivia());

                    while (en.MoveNext())
                    {
                        expression = BitwiseOrExpression(
                            IdentifierName(en.Current.Identifier.WithoutTrivia()),
                            expression);
                    }
                }
            }

            EnumMemberDeclarationSyntax newEnumMember = EnumMemberDeclaration(
                Identifier(name).WithRenameAnnotation(),
                EqualsValueClause(expression));

            EnumDeclarationSyntax newEnumDeclaration = enumDeclaration
                                                       .WithMembers(enumDeclaration.Members.Insert(selectedMembers.UnderlyingList.IndexOf(lastMember) + 1, newEnumMember));

            return(document.ReplaceNodeAsync(enumDeclaration, newEnumDeclaration, cancellationToken));

            IEnumerable <EnumMemberDeclarationSyntax> GetMembersToCombine()
            {
                for (int i = selectedMembers.Count - 1; i >= 0; i--)
                {
                    IFieldSymbol symbol = semanticModel.GetDeclaredSymbol(selectedMembers[i], cancellationToken);

                    if (symbol.HasConstantValue)
                    {
                        ulong value = SymbolUtility.GetEnumValueAsUInt64(symbol.ConstantValue, enumSymbol);

                        if (!FlagsUtility <ulong> .Instance.IsComposite(value))
                        {
                            yield return(selectedMembers[i]);
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
        private static Task <Document> RefactorAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            INamedTypeSymbol enumSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ulong value = 0;

            SpecialType numericType = enumSymbol.EnumUnderlyingType.SpecialType;

            IEnumerable <EnumMemberDeclarationSyntax> newMembers = (enumSymbol.HasAttribute(MetadataNames.System_FlagsAttribute))
                ? enumDeclaration.Members.Select(CreateNewFlagsMember)
                : enumDeclaration.Members.Select(CreateNewMember);

            EnumDeclarationSyntax newEnumDeclaration = enumDeclaration.WithMembers(newMembers.ToSeparatedSyntaxList());

            return(document.ReplaceNodeAsync(enumDeclaration, newEnumDeclaration, cancellationToken));

            EnumMemberDeclarationSyntax CreateNewFlagsMember(EnumMemberDeclarationSyntax enumMember)
            {
                if (!ConvertHelpers.CanConvert(value, numericType))
                {
                    return(enumMember);
                }

                IFieldSymbol fieldSymbol = semanticModel.GetDeclaredSymbol(enumMember, cancellationToken);

                if (fieldSymbol.HasConstantValue &&
                    FlagsUtility <ulong> .Instance.IsComposite(SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, enumSymbol)))
                {
                    return(enumMember);
                }

                EnumMemberDeclarationSyntax newEnumMember = CreateNewEnumMember(enumMember, value, numericType);

                value = (value == 0) ? 1 : value * 2;

                return(newEnumMember);
            }

            EnumMemberDeclarationSyntax CreateNewMember(EnumMemberDeclarationSyntax enumMember)
            {
                if (!ConvertHelpers.CanConvert(value, numericType))
                {
                    return(enumMember);
                }

                EnumMemberDeclarationSyntax newEnumMember = CreateNewEnumMember(enumMember, value, numericType);

                value++;

                return(newEnumMember);
            }
        }
        private static async Task <Document> RefactorAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            IEnumerable <EnumMemberDeclarationSyntax> enumMembers,
            bool keepCompositeValue,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = null;

            if (keepCompositeValue)
            {
                semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                INamedTypeSymbol enumSymbol = semanticModel.GetDeclaredSymbol(enumDeclaration, cancellationToken);

                keepCompositeValue = enumSymbol.HasAttribute(MetadataNames.System_FlagsAttribute);
            }

            IEnumerable <TextChange> textChanges = enumMembers
                                                   .Where(enumMember =>
            {
                ExpressionSyntax expression = enumMember.EqualsValue?.Value;

                if (expression == null)
                {
                    return(false);
                }

                if (keepCompositeValue &&
                    !(expression is LiteralExpressionSyntax))
                {
                    IFieldSymbol fieldSymbol = semanticModel.GetDeclaredSymbol(enumMember, cancellationToken);

                    if (!fieldSymbol.HasConstantValue)
                    {
                        return(false);
                    }

                    ulong value = SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, fieldSymbol.ContainingType);

                    if (FlagsUtility <ulong> .Instance.IsComposite(value))
                    {
                        return(false);
                    }
                }

                return(true);
            })
                                                   .Select(f => new TextChange(TextSpan.FromBounds(f.Identifier.Span.End, f.EqualsValue.Span.End), ""));

            return(await document.WithTextChangesAsync(textChanges, cancellationToken).ConfigureAwait(false));
        }
Ejemplo n.º 6
0
        public static OneOrMany <EnumFieldSymbolInfo> GetConstituentFields(object value, INamedTypeSymbol enumType)
        {
            EnumSymbolInfo enumInfo = EnumSymbolInfo.Create(enumType);

            ulong convertedValue = SymbolUtility.GetEnumValueAsUInt64(value, enumType);

            if (!enumType.HasAttribute(MetadataNames.System_FlagsAttribute) ||
                convertedValue == 0)
            {
                return(OneOrMany.Create(FindField(enumInfo, convertedValue)));
            }

            return(GetConstituentFields(convertedValue, enumInfo));
        }
Ejemplo n.º 7
0
        private static ImmutableArray <ulong> GetConstantValues(INamedTypeSymbol enumSymbol)
        {
            ImmutableArray <ulong> .Builder values = ImmutableArray.CreateBuilder <ulong>();

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

                    if (fieldSymbol.HasConstantValue)
                    {
                        values.Add(SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, enumSymbol));
                    }
                }
            }

            return(values.ToImmutableArray());
        }
        public static void ComputeRefactoring(
            RefactoringContext context,
            EnumDeclarationSyntax enumDeclaration,
            SeparatedSyntaxListSelection <EnumMemberDeclarationSyntax> selectedMembers,
            SemanticModel semanticModel)
        {
            INamedTypeSymbol enumSymbol = semanticModel.GetDeclaredSymbol(enumDeclaration, context.CancellationToken);

            if (enumSymbol?.HasAttribute(MetadataNames.System_FlagsAttribute) != true)
            {
                return;
            }

            ImmutableArray <ulong> constantValues = selectedMembers
                                                    .Select(f => semanticModel.GetDeclaredSymbol(f, context.CancellationToken))
                                                    .Where(f => f.HasConstantValue)
                                                    .Select(f => SymbolUtility.GetEnumValueAsUInt64(f.ConstantValue, enumSymbol))
                                                    .ToImmutableArray();

            Optional <ulong> optionalValue = FlagsUtility <ulong> .Instance.TryCompose(constantValues);

            if (!optionalValue.HasValue)
            {
                return;
            }

            if (IsValueDefined(enumSymbol, optionalValue))
            {
                return;
            }

            string name = NameGenerator.Default.EnsureUniqueMemberName(
                string.Concat(selectedMembers.Select(f => f.Identifier.ValueText)),
                enumSymbol);

            context.RegisterRefactoring(
                $"Generate enum member '{name}'",
                ct => RefactorAsync(context.Document, enumDeclaration, selectedMembers, name, ct),
                RefactoringIdentifiers.GenerateCombinedEnumMember);
        }
Ejemplo n.º 9
0
        private static ImmutableArray <ulong> GetExplicitValues(
            EnumDeclarationSyntax enumDeclaration,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ImmutableArray <ulong> .Builder values = ImmutableArray.CreateBuilder <ulong>();

            foreach (EnumMemberDeclarationSyntax member in enumDeclaration.Members)
            {
                ExpressionSyntax value = member.EqualsValue?.Value;

                if (value != null)
                {
                    IFieldSymbol fieldSymbol = semanticModel.GetDeclaredSymbol(member, cancellationToken);

                    if (fieldSymbol?.HasConstantValue == true)
                    {
                        values.Add(SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, fieldSymbol.ContainingType));
                    }
                }
            }

            return(values.ToImmutableArray());
        }
Ejemplo n.º 10
0
        public static void ComputeRefactoring(
            RefactoringContext context,
            EnumDeclarationSyntax enumDeclaration,
            SeparatedSyntaxListSelection <EnumMemberDeclarationSyntax> selectedMembers,
            SemanticModel semanticModel)
        {
            if (!enumDeclaration.AttributeLists.Any())
            {
                return;
            }

            INamedTypeSymbol enumSymbol = semanticModel.GetDeclaredSymbol(enumDeclaration, context.CancellationToken);

            if (enumSymbol?.HasAttribute(MetadataNames.System_FlagsAttribute) != true)
            {
                return;
            }

            IEnumerable <(IFieldSymbol symbol, ulong value)> symbolsValues = selectedMembers
                                                                             .Select(f => semanticModel.GetDeclaredSymbol(f, context.CancellationToken))
                                                                             .Where(f => f.HasConstantValue)
                                                                             .Select(f => (symbol: f, value: SymbolUtility.GetEnumValueAsUInt64(f.ConstantValue, enumSymbol)))
                                                                             .Where(f => !FlagsUtility <ulong> .Instance.IsComposite(f.value));

            ImmutableArray <ulong> constantValues = symbolsValues.Select(f => f.value).ToImmutableArray();

            if (constantValues.Length <= 1)
            {
                return;
            }

            Optional <ulong> optionalValue = FlagsUtility <ulong> .Instance.TryCompose(constantValues);

            if (!optionalValue.HasValue)
            {
                return;
            }

            if (IsValueDefined(optionalValue))
            {
                return;
            }

            string name = NameGenerator.Default.EnsureUniqueEnumMemberName(
                string.Concat(symbolsValues.Select(f => f.symbol.Name)),
                enumSymbol);

            context.RegisterRefactoring(
                $"Generate member '{name}'",
                ct => RefactorAsync(context.Document, enumDeclaration, selectedMembers, enumSymbol, name, semanticModel, ct),
                RefactoringIdentifiers.GenerateCombinedEnumMember);

            bool IsValueDefined(object value)
            {
                foreach (ISymbol member in enumSymbol.GetMembers())
                {
                    if (member.Kind == SymbolKind.Field)
                    {
                        var fieldSymbol = (IFieldSymbol)member;

                        if (fieldSymbol.HasConstantValue &&
                            object.Equals(fieldSymbol.ConstantValue, value))
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
        }
Ejemplo n.º 11
0
        private static async Task <Document> DeclareExplicitValueAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            INamedTypeSymbol enumSymbol,
            bool isFlags,
            bool useBitShift,
            ImmutableArray <ulong> values,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            List <ulong> reservedValues = values.ToList();

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members;

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> newMembers = members;

            for (int i = 0; i < members.Count; i++)
            {
                if (members[i].EqualsValue == null)
                {
                    IFieldSymbol fieldSymbol = semanticModel.GetDeclaredSymbol(members[i], cancellationToken);

                    ulong?value = null;

                    if (isFlags)
                    {
                        Optional <ulong> optional = FlagsUtility <ulong> .Instance.GetUniquePowerOfTwo(reservedValues);

                        if (optional.HasValue &&
                            ConvertHelpers.CanConvertFromUInt64(optional.Value, enumSymbol.EnumUnderlyingType.SpecialType))
                        {
                            value = optional.Value;
                        }
                    }
                    else
                    {
                        value = SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, enumSymbol);
                    }

                    if (value != null)
                    {
                        reservedValues.Add(value.Value);

                        ExpressionSyntax expression;

                        if (useBitShift &&
                            value.Value > 1)
                        {
                            var power = (int)Math.Log(Convert.ToDouble(value.Value), 2);

                            expression = LeftShiftExpression(NumericLiteralExpression(1), NumericLiteralExpression(power));
                        }
                        else
                        {
                            expression = NumericLiteralExpression(value.Value, enumSymbol.EnumUnderlyingType.SpecialType);
                        }

                        EnumMemberDeclarationSyntax newMember = members[i].Update(
                            members[i].AttributeLists,
                            members[i].Modifiers,
                            members[i].Identifier.WithoutTrailingTrivia(),
                            EqualsValueClause(expression).WithTrailingTrivia(members[i].Identifier.TrailingTrivia));

                        newMembers = newMembers.ReplaceAt(i, newMember);
                    }
                }
            }

            EnumDeclarationSyntax newEnumDeclaration = enumDeclaration.WithMembers(newMembers);

            return(await document.ReplaceNodeAsync(enumDeclaration, newEnumDeclaration, cancellationToken).ConfigureAwait(false));
        }