private Task <Document> GetUpdatedDocumentForRuleNameRename(Document document, SyntaxNode root, SyntaxNode nodeToFix, INamedTypeSymbol enumType, IEnumerable <IFieldSymbol> zeroValuedFields, CancellationToken cancellationToken)
        {
            Contract.ThrowIfFalse(zeroValuedFields.Count() == 1);
            var zeroValuedField = zeroValuedFields.Single();

            Contract.ThrowIfTrue(CA1008DiagnosticAnalyzer.IsMemberNamedNone(zeroValuedField));

            var newFields = GetNewFieldsForRuleNameRename(enumType, zeroValuedField);

            return(GetUpdatedDocumentWithFix(document, root, nodeToFix, newFields, cancellationToken));
        }
        private IList <ISymbol> GetNewFieldsForRuleNameMultipleZero(INamedTypeSymbol enumType, IEnumerable <IFieldSymbol> zeroValuedFields, SyntaxGenerator syntaxFactoryService)
        {
            // Diagnostic: Remove all members that have the value zero from '{0}' except for one member that is named 'None'.
            // Fix: Remove all members that have the value zero except for one member that is named 'None'.

            bool needsNewZeroValuedNoneField = true;
            var  set = zeroValuedFields.ToSet();

            bool makeNextFieldExplicit = false;
            var  newFields             = new List <ISymbol>();

            foreach (IFieldSymbol field in enumType.GetMembers().Where(m => m.Kind == SymbolKind.Field))
            {
                var isZeroValued          = set.Contains(field);
                var isZeroValuedNamedNone = isZeroValued && CA1008DiagnosticAnalyzer.IsMemberNamedNone(field);

                if (!isZeroValued || isZeroValuedNamedNone)
                {
                    var newField = field;
                    if (makeNextFieldExplicit)
                    {
                        newField = GetExplicitlyAssignedField(field, syntaxFactoryService);
                        makeNextFieldExplicit = false;
                    }

                    newFields.Add(newField);

                    if (isZeroValuedNamedNone)
                    {
                        needsNewZeroValuedNoneField = false;
                    }
                }
                else
                {
                    makeNextFieldExplicit = true;
                }
            }

            if (needsNewZeroValuedNoneField)
            {
                var firstZeroValuedField    = zeroValuedFields.First();
                var constantValueExpression = syntaxFactoryService.LiteralExpression(firstZeroValuedField.ConstantValue);
                var newInitializer          = CreateConstantValueInitializer(constantValueExpression);
                var newField = CodeGenerationSymbolFactory.CreateFieldSymbol(firstZeroValuedField.GetAttributes(), firstZeroValuedField.DeclaredAccessibility, firstZeroValuedField.GetSymbolModifiers(),
                                                                             firstZeroValuedField.Type, "None", firstZeroValuedField.HasConstantValue, firstZeroValuedField.ConstantValue, newInitializer);
                newFields.Insert(0, newField);
            }

            return(newFields);
        }
        private async Task ApplyRuleNameNoZeroValueAsync(SymbolEditor editor, INamedTypeSymbol enumType, CancellationToken cancellationToken)
        {
            // remove any non-zero member named 'None'
            foreach (IFieldSymbol field in enumType.GetMembers().Where(m => m.Kind == SymbolKind.Field))
            {
                if (CA1008DiagnosticAnalyzer.IsMemberNamedNone(field))
                {
                    await editor.EditOneDeclarationAsync(field, (e, d) => e.RemoveNode(d), cancellationToken);
                }
            }

            // insert zero-valued member 'None' to top
            await editor.EditOneDeclarationAsync(enumType, (e, d) => e.InsertMembers(d, 0, new[] { e.Generator.EnumMember("None") }), cancellationToken);
        }
        private async Task ApplyRuleNameMultipleZeroAsync(SymbolEditor editor, INamedTypeSymbol enumType, CancellationToken cancellationToken)
        {
            // Diagnostic: Remove all members that have the value zero from '{0}' except for one member that is named 'None'.
            // Fix: Remove all members that have the value zero except for one member that is named 'None'.

            bool needsNewZeroValuedNoneField = true;
            var  set = CA1008DiagnosticAnalyzer.GetZeroValuedFields(enumType).ToSet();

            bool makeNextFieldExplicit = false;

            foreach (IFieldSymbol field in enumType.GetMembers().Where(m => m.Kind == SymbolKind.Field))
            {
                var isZeroValued          = set.Contains(field);
                var isZeroValuedNamedNone = isZeroValued && CA1008DiagnosticAnalyzer.IsMemberNamedNone(field);

                if (!isZeroValued || isZeroValuedNamedNone)
                {
                    if (makeNextFieldExplicit)
                    {
                        await editor.EditOneDeclarationAsync(field, (e, d) => e.ReplaceNode(d, GetExplicitlyAssignedField(field, d, e.Generator)), cancellationToken);

                        makeNextFieldExplicit = false;
                    }

                    if (isZeroValuedNamedNone)
                    {
                        needsNewZeroValuedNoneField = false;
                    }
                }
                else
                {
                    await editor.EditOneDeclarationAsync(field, (e, d) => e.RemoveNode(d), cancellationToken); // removes the field declaration

                    makeNextFieldExplicit = true;
                }
            }

            if (needsNewZeroValuedNoneField)
            {
                await editor.EditOneDeclarationAsync(enumType, (e, d) => e.InsertMembers(d, 0, new[] { e.Generator.EnumMember("None") }), cancellationToken);
            }
        }
        private IList <ISymbol> GetNewFieldsForRuleNameNoZeroValue(INamedTypeSymbol enumType, SyntaxGenerator syntaxFactoryService)
        {
            // Diagnostic: Add a member to '{0}' that has a value of zero with a suggested name of 'None'.
            // Fix: Add a zero-valued member 'None' to enum.

            var newFields = new List <ISymbol>();
            var constantValueExpression = syntaxFactoryService.LiteralExpression(0);
            var newInitializer          = CreateConstantValueInitializer(constantValueExpression);
            var newField = CodeGenerationSymbolFactory.CreateFieldSymbol(SpecializedCollections.EmptyList <AttributeData>(), Accessibility.Public,
                                                                         default(SymbolModifiers), enumType.EnumUnderlyingType, "None", true, 0, newInitializer);

            newFields.Add(newField);

            foreach (var member in enumType.GetMembers())
            {
                if (!CA1008DiagnosticAnalyzer.IsMemberNamedNone(member))
                {
                    newFields.Add(member);
                }
            }

            return(newFields);
        }