protected internal StyleCopSettings(JsonObject settingsObject)
            : this()
        {
            foreach (var kvp in settingsObject)
            {
                var childSettingsObject = kvp.Value.AsJsonObject;
                switch (kvp.Key)
                {
                case "indentation":
                    kvp.AssertIsObject();
                    this.indentation = new IndentationSettings(childSettingsObject);
                    break;

                case "spacingRules":
                    kvp.AssertIsObject();
                    this.spacingRules = new SpacingSettings(childSettingsObject);
                    break;

                case "readabilityRules":
                    kvp.AssertIsObject();
                    this.readabilityRules = new ReadabilitySettings(childSettingsObject);
                    break;

                case "orderingRules":
                    kvp.AssertIsObject();
                    this.orderingRules = new OrderingSettings(childSettingsObject);
                    break;

                case "namingRules":
                    kvp.AssertIsObject();
                    this.namingRules = new NamingSettings(childSettingsObject);
                    break;

                case "maintainabilityRules":
                    kvp.AssertIsObject();
                    this.maintainabilityRules = new MaintainabilitySettings(childSettingsObject);
                    break;

                case "layoutRules":
                    kvp.AssertIsObject();
                    this.layoutRules = new LayoutSettings(childSettingsObject);
                    break;

                case "documentationRules":
                    kvp.AssertIsObject();
                    this.documentationRules = new DocumentationSettings(childSettingsObject);
                    break;

                case "alignmentRules":
                    kvp.AssertIsObject();
                    this.alignmentRules = new AlignmentSettings(childSettingsObject);
                    break;

                default:
                    break;
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="StyleCopSettings"/> class.
        /// </summary>
        protected internal StyleCopSettings()
        {
            this.indentation = new IndentationSettings();

            this.spacingRules         = new SpacingSettings();
            this.readabilityRules     = new ReadabilitySettings();
            this.orderingRules        = new OrderingSettings();
            this.namingRules          = new NamingSettings();
            this.maintainabilityRules = new MaintainabilitySettings();
            this.layoutRules          = new LayoutSettings();
            this.documentationRules   = new DocumentationSettings();
        }
        protected internal StyleCopSettings()
        {
            this.indentation = new IndentationSettings();

            this.spacingRules = new SpacingSettings();
            this.readabilityRules = new ReadabilitySettings();
            this.orderingRules = new OrderingSettings();
            this.namingRules = new NamingSettings();
            this.maintainabilityRules = new MaintainabilitySettings();
            this.layoutRules = new LayoutSettings();
            this.documentationRules = new DocumentationSettings();
        }
        protected internal StyleCopSettings(JsonObject settingsObject, AnalyzerConfigOptionsWrapper analyzerConfigOptions)
        {
            foreach (var kvp in settingsObject)
            {
                var childSettingsObject = kvp.Value.AsJsonObject;
                switch (kvp.Key)
                {
                case "indentation":
                    kvp.AssertIsObject();
                    this.indentation = new IndentationSettings(childSettingsObject, analyzerConfigOptions);
                    break;

                case "spacingRules":
                    kvp.AssertIsObject();
                    this.spacingRules = new SpacingSettings(childSettingsObject, analyzerConfigOptions);
                    break;

                case "readabilityRules":
                    kvp.AssertIsObject();
                    this.readabilityRules = new ReadabilitySettings(childSettingsObject, analyzerConfigOptions);
                    break;

                case "orderingRules":
                    kvp.AssertIsObject();
                    this.orderingRules = new OrderingSettings(childSettingsObject, analyzerConfigOptions);
                    break;

                case "namingRules":
                    kvp.AssertIsObject();
                    this.namingRules = new NamingSettings(childSettingsObject, analyzerConfigOptions);
                    break;

                case "maintainabilityRules":
                    kvp.AssertIsObject();
                    this.maintainabilityRules = new MaintainabilitySettings(childSettingsObject, analyzerConfigOptions);
                    break;

                case "layoutRules":
                    kvp.AssertIsObject();
                    this.layoutRules = new LayoutSettings(childSettingsObject, analyzerConfigOptions);
                    break;

                case "documentationRules":
                    kvp.AssertIsObject();
                    this.documentationRules = new DocumentationSettings(childSettingsObject, analyzerConfigOptions);
                    break;

                default:
                    break;
                }
            }

            this.indentation ??= new IndentationSettings(new JsonObject(), analyzerConfigOptions);

            this.spacingRules ??= new SpacingSettings(new JsonObject(), analyzerConfigOptions);
            this.readabilityRules ??= new ReadabilitySettings(new JsonObject(), analyzerConfigOptions);
            this.orderingRules ??= new OrderingSettings(new JsonObject(), analyzerConfigOptions);
            this.namingRules ??= new NamingSettings(new JsonObject(), analyzerConfigOptions);
            this.maintainabilityRules ??= new MaintainabilitySettings(new JsonObject(), analyzerConfigOptions);
            this.layoutRules ??= new LayoutSettings(new JsonObject(), analyzerConfigOptions);
            this.documentationRules ??= new DocumentationSettings(new JsonObject(), analyzerConfigOptions);
        }
        private static void ReportIncorrectTabUsage(SyntaxTreeAnalysisContext context, IndentationSettings indentationSettings, ImmutableArray<TextSpan> excludedSpans)
        {
            SyntaxTree syntaxTree = context.Tree;
            SourceText sourceText = syntaxTree.GetText(context.CancellationToken);

            string completeText = sourceText.ToString();
            int length = completeText.Length;

            bool useTabs = indentationSettings.UseTabs;
            int tabSize = indentationSettings.TabSize;

            int excludedSpanIndex = 0;
            var lastExcludedSpan = new TextSpan(completeText.Length, 0);
            TextSpan nextExcludedSpan = !excludedSpans.IsEmpty ? excludedSpans[0] : lastExcludedSpan;

            int lastLineStart = 0;
            for (int startIndex = 0; startIndex < length; startIndex++)
            {
                if (startIndex == nextExcludedSpan.Start)
                {
                    startIndex = nextExcludedSpan.End - 1;
                    excludedSpanIndex++;
                    nextExcludedSpan = excludedSpanIndex < excludedSpans.Length ? excludedSpans[excludedSpanIndex] : lastExcludedSpan;
                    continue;
                }

                int tabCount = 0;
                bool containsSpaces = false;
                bool tabAfterSpace = false;
                switch (completeText[startIndex])
                {
                case ' ':
                    containsSpaces = true;
                    break;

                case '\t':
                    tabCount++;
                    break;

                case '\r':
                case '\n':
                    // Handle newlines. We can ignore CR/LF/CRLF issues because we are only tracking column position
                    // in a line, and not the line numbers themselves.
                    lastLineStart = startIndex + 1;
                    continue;

                default:
                    continue;
                }

                int endIndex;
                for (endIndex = startIndex + 1; endIndex < length; endIndex++)
                {
                    if (endIndex == nextExcludedSpan.Start)
                    {
                        break;
                    }

                    if (completeText[endIndex] == ' ')
                    {
                        containsSpaces = true;
                    }
                    else if (completeText[endIndex] == '\t')
                    {
                        tabCount++;
                        tabAfterSpace = containsSpaces;
                    }
                    else
                    {
                        break;
                    }
                }

                if (useTabs && startIndex == lastLineStart)
                {
                    // For the case we care about in the following condition (tabAfterSpace is false), spaceCount is
                    // the number of consecutive trailing spaces.
                    int spaceCount = (endIndex - startIndex) - tabCount;
                    if (tabAfterSpace || spaceCount >= tabSize)
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptor,
                                Location.Create(syntaxTree, TextSpan.FromBounds(startIndex, endIndex)),
                                ConvertToTabsProperties));
                    }
                }
                else
                {
                    if (tabCount > 0)
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptor,
                                Location.Create(syntaxTree, TextSpan.FromBounds(startIndex, endIndex)),
                                ConvertToSpacesProperties));
                    }
                }

                // Make sure to not analyze overlapping spans
                startIndex = endIndex - 1;
            }
        }