private static string UsingDirectiveSyntaxToCanonicalString(UsingDirectiveSyntax usingDirective)
        {
            var builder = StringBuilderPool.Allocate();

            AppendCanonicalString(builder, usingDirective.Name);
            return(StringBuilderPool.ReturnAndFree(builder));
        }
        private string GetTextWithReplacementMap(string text, string returnReplacement, string newLineReplacement, List <ValueTuple <int, int> > replacementMap)
        {
            var delta         = 0;
            var returnLength  = returnReplacement.Length;
            var newLineLength = newLineReplacement.Length;

            var sb = StringBuilderPool.Allocate();

            for (var i = 0; i < text.Length; i++)
            {
                var ch = text[i];
                if (ch == '\r')
                {
                    sb.Append(returnReplacement);
                    delta += returnLength - 1;
                    replacementMap.Add(ValueTuple.Create(i + delta, delta));
                    continue;
                }
                else if (ch == '\n')
                {
                    sb.Append(newLineReplacement);
                    delta += newLineLength - 1;
                    replacementMap.Add(ValueTuple.Create(i + delta, delta));
                    continue;
                }

                sb.Append(ch);
            }

            return(StringBuilderPool.ReturnAndFree(sb));
        }
        protected static string DefaultMessageFormatter(string loggerName, LogLevel level, object message, Exception e)
        {
            var stringBuilder = StringBuilderPool.Allocate();

            stringBuilder.Append(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture));

            stringBuilder.Append(" ");

            // Append a readable representation of the log level
            stringBuilder.Append(("[" + level.ToString().ToUpper() + "]").PadRight(8));

            stringBuilder.Append("(" + loggerName + ") ");

            // Append the message
            stringBuilder.Append(message);

            // Append stack trace if there is an exception
            if (e != null)
            {
                stringBuilder.Append(Environment.NewLine).Append(e.GetType());
                stringBuilder.Append(Environment.NewLine).Append(e.Message);
                stringBuilder.Append(Environment.NewLine).Append(e.StackTrace);
            }

            return(StringBuilderPool.ReturnAndFree(stringBuilder));
        }
        internal static string GetText(XmlNodeSyntax nodeSyntax, bool normalizeWhitespace = false)
        {
            var xmlTextSyntax = nodeSyntax as XmlTextSyntax;

            if (xmlTextSyntax != null)
            {
                return(GetText(xmlTextSyntax, normalizeWhitespace));
            }

            var xmlElementSyntax = nodeSyntax as XmlElementSyntax;

            if (xmlElementSyntax != null)
            {
                var stringBuilder = StringBuilderPool.Allocate();

                foreach (var node in xmlElementSyntax.Content)
                {
                    stringBuilder.Append(GetText(node, normalizeWhitespace));
                }

                return(StringBuilderPool.ReturnAndFree(stringBuilder));
            }

            return(null);
        }
Exemple #5
0
        private static int GetIndentationSteps(IndentationOptions indentationOptions, SyntaxTree syntaxTree, SyntaxTriviaList leadingTrivia)
        {
            var triviaSpan = syntaxTree.GetLineSpan(leadingTrivia.FullSpan);

            // There is no indentation when the leading trivia doesn't begin at the start of the line.
            if ((triviaSpan.StartLinePosition == triviaSpan.EndLinePosition) && (triviaSpan.StartLinePosition.Character > 0))
            {
                return(0);
            }

            var builder = StringBuilderPool.Allocate();

            foreach (SyntaxTrivia trivia in leadingTrivia.Reverse())
            {
                if (!trivia.IsKind(SyntaxKind.WhitespaceTrivia))
                {
                    break;
                }

                builder.Insert(0, trivia.ToFullString());
            }

            var tabSize          = indentationOptions.TabSize;
            var indentationCount = 0;

            for (var i = 0; i < builder.Length; i++)
            {
                indentationCount += builder[i] == '\t' ? tabSize - (indentationCount % tabSize) : 1;
            }

            StringBuilderPool.ReturnAndFree(builder);

            return((indentationCount + (indentationOptions.IndentationSize / 2)) / indentationOptions.IndentationSize);
        }
        public static string ToPascalCase(this string underscoreString)
        {
            if (string.IsNullOrEmpty(underscoreString))
            {
                return(underscoreString);
            }

            var sb = StringBuilderPool.Allocate();

            sb.EnsureCapacity(underscoreString.Length);

            var capitalizeNext = true;

            foreach (var c in underscoreString)
            {
                if (capitalizeNext)
                {
                    sb.Append(char.ToUpper(c));
                    capitalizeNext = false;
                }
                else
                {
                    if (c == '_')
                    {
                        capitalizeNext = true;
                    }
                    else
                    {
                        sb.Append(char.ToLowerInvariant(c));
                    }
                }
            }

            return(StringBuilderPool.ReturnAndFree(sb));
        }
        internal static string GetText(XmlNodeSyntax nodeSyntax, bool normalizeWhitespace = false)
        {
            if (nodeSyntax is XmlTextSyntax xmlTextSyntax)
            {
                return(GetText(xmlTextSyntax, normalizeWhitespace));
            }

            if (nodeSyntax is XmlElementSyntax xmlElementSyntax)
            {
                var stringBuilder = StringBuilderPool.Allocate();

                foreach (var node in xmlElementSyntax.Content)
                {
                    stringBuilder.Append(GetText(node, normalizeWhitespace));
                }

                return(StringBuilderPool.ReturnAndFree(stringBuilder));
            }

            if (nodeSyntax is XmlEmptyElementSyntax emptyXmlElement)
            {
                return(emptyXmlElement.NormalizeWhitespace(string.Empty).ToString());
            }

            return(null);
        }
Exemple #8
0
        protected Task EnsureEventsSubscribed()
        {
            var sb = StringBuilderPool.Allocate();

            sb.Append("event plain");

            foreach (var @event in subscribedEvents)
            {
                sb.Append(" ");
                sb.Append(@event.ToString().ToUpperWithUnderscores());
            }

            if (customEvents.Any())
            {
                sb.Append(" CUSTOM ");

                foreach (var @event in customEvents)
                {
                    sb.Append(" ");
                    sb.Append(@event);
                }
            }

            return(SendCommand(StringBuilderPool.ReturnAndFree(sb)));
        }
        public static string ToUpperWithUnderscores(this string pascalCaseString)
        {
            if (string.IsNullOrEmpty(pascalCaseString))
            {
                return(pascalCaseString);
            }

            var sb = StringBuilderPool.Allocate();

            sb.EnsureCapacity(pascalCaseString.Length);

            for (var i = 0; i < pascalCaseString.Length; i++)
            {
                var c = pascalCaseString[i];
                if (char.IsUpper(c))
                {
                    if (i != 0)
                    {
                        sb.Append('_');
                    }

                    sb.Append(char.ToUpper(c));
                }
                else
                {
                    sb.Append(char.ToUpper(c));
                }
            }

            return(StringBuilderPool.ReturnAndFree(sb));
        }
        private static int GetIndentationStepsUnchecked(IndentationSettings indentationSettings, SyntaxTriviaList leadingTrivia)
        {
            var builder = StringBuilderPool.Allocate();

            foreach (SyntaxTrivia trivia in leadingTrivia.Reverse())
            {
                if (!trivia.IsKind(SyntaxKind.WhitespaceTrivia))
                {
                    break;
                }

                builder.Insert(0, trivia.ToFullString());
            }

            var tabSize          = indentationSettings.TabSize;
            var indentationCount = 0;

            for (var i = 0; i < builder.Length; i++)
            {
                indentationCount += builder[i] == '\t' ? tabSize - (indentationCount % tabSize) : 1;
            }

            StringBuilderPool.ReturnAndFree(builder);

            return((indentationCount + (indentationSettings.IndentationSize / 2)) / indentationSettings.IndentationSize);
        }
        private static string UsingDirectiveSyntaxToCanonicalString(UsingDirectiveSyntax usingDirective)
        {
            var builder = StringBuilderPool.Allocate();
            var insideArrayDeclaration = false;

            // NOTE: this does not cover embedded comments. It is very unlikely that comments are present
            // within a multiline using statement and handling them requires a lot more effort (and keeping of state).
            foreach (var c in usingDirective.Name.ToString())
            {
                switch (c)
                {
                case ' ':
                case '\t':
                case '\r':
                case '\n':
                    break;
                case '[':
                    insideArrayDeclaration = true;
                    builder.Append(c);
                    break;
                case ']':
                    insideArrayDeclaration = false;
                    builder.Append(c);
                    break;
                case ',':
                    builder.Append(insideArrayDeclaration ? "," : ", ");
                    break;
                default:
                    builder.Append(c);
                    break;
                }
            }

            return StringBuilderPool.ReturnAndFree(builder);
        }
        internal static string ToUnaliasedString(this NameSyntax nameSyntax)
        {
            var sb = StringBuilderPool.Allocate();

            BuildName(nameSyntax, sb, false);

            return(StringBuilderPool.ReturnAndFree(sb));
        }
        /// <summary>
        /// Converts the <seealso cref="OriginateOptions"/> instance into an originate string.
        /// </summary>
        /// <returns>An originate string.</returns>
        public override string ToString()
        {
            var sb = StringBuilderPool.Allocate();

            AppendOriginateEnterpriseChannelVariablesString(sb);
            AppendOriginateChannelVariablesString(sb);

            return(StringBuilderPool.ReturnAndFree(sb));
        }
        private static string ProcessSingleLineCommentsHeader(SyntaxTriviaList triviaList, int startIndex, out int fileHeaderStart, out int fileHeaderEnd)
        {
            var sb             = StringBuilderPool.Allocate();
            var endOfLineCount = 0;
            var done           = false;

            fileHeaderStart = int.MaxValue;
            fileHeaderEnd   = int.MinValue;

            // wrap the XML from the file header in a single root element to make XML parsing work.
            sb.AppendLine("<root>");

            int i;

            for (i = startIndex; !done && (i < triviaList.Count); i++)
            {
                var trivia = triviaList[i];

                switch (trivia.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    endOfLineCount = 0;
                    break;

                case SyntaxKind.SingleLineCommentTrivia:
                    endOfLineCount = 0;

                    var commentString = trivia.ToFullString();

                    // ignore borders
                    if (commentString.StartsWith("//-", StringComparison.OrdinalIgnoreCase))
                    {
                        break;
                    }

                    fileHeaderStart = Math.Min(trivia.FullSpan.Start, fileHeaderStart);
                    fileHeaderEnd   = trivia.FullSpan.End;

                    sb.AppendLine(commentString.Substring(2));
                    break;

                case SyntaxKind.EndOfLineTrivia:
                    endOfLineCount++;
                    done = endOfLineCount > 1;
                    break;

                default:
                    done = (fileHeaderStart < fileHeaderEnd) || !trivia.IsDirective;
                    break;
                }
            }

            sb.AppendLine("</root>");
            return(StringBuilderPool.ReturnAndFree(sb));
        }
        public static string ToOriginateString(this IDictionary <string, string> dictionary)
        {
            var sb = StringBuilderPool.Allocate();

            foreach (var kvp in dictionary)
            {
                sb.AppendFormat("{0}='{1}',", kvp.Key, kvp.Value);
            }

            return(StringBuilderPool.ReturnAndFree(sb));
        }
Exemple #16
0
        /// <inheritdoc/>
        protected override void HandleCompleteDocumentation(SyntaxNodeAnalysisContext context, bool needsComment, XElement completeDocumentation, params Location[] diagnosticLocations)
        {
            var objectPool = SharedPools.Default <HashSet <string> >();
            HashSet <string> documentationTexts = objectPool.Allocate();
            var settings        = context.Options.GetStyleCopSettings(context.CancellationToken);
            var culture         = new CultureInfo(settings.DocumentationRules.DocumentationCulture);
            var resourceManager = DocumentationResources.ResourceManager;

            // Concatenate all XML node values
            var documentationElements = completeDocumentation.Nodes()
                                        .OfType <XElement>()
                                        .Select(x =>
            {
                var builder = StringBuilderPool.Allocate();

                foreach (var node in x.Nodes())
                {
                    builder.Append(node.ToString().Trim());
                }

                var elementValue = builder.ToString();
                StringBuilderPool.ReturnAndFree(builder);

                return(elementValue);
            });

            foreach (var documentation in documentationElements)
            {
                if (ShouldSkipElement(documentation, resourceManager.GetString(nameof(DocumentationResources.ParameterNotUsed), culture)))
                {
                    continue;
                }

                if (documentationTexts.Contains(documentation))
                {
                    // Add violation
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, diagnosticLocations.First()));
                }
                else
                {
                    documentationTexts.Add(documentation);
                }
            }

            objectPool.ClearAndFree(documentationTexts);
        }
Exemple #17
0
            private static string? ComputeEquivalenceKey(ImmutableArray<CodeAction> nestedActions)
            {
                var equivalenceKey = StringBuilderPool.Allocate();
                try
                {
                    foreach (var action in nestedActions)
                    {
                        equivalenceKey.Append((action.EquivalenceKey ?? action.GetHashCode().ToString()) + ";");
                    }

                    return equivalenceKey.Length > 0 ? equivalenceKey.ToString() : null;
                }
                finally
                {
                    StringBuilderPool.ReturnAndFree(equivalenceKey);
                }
            }
Exemple #18
0
        public override string ToString()
        {
            var sb = StringBuilderPool.Allocate();

            sb.Append("{");

            sb.Append(parameters.ToOriginateString());

            if (sb.Length > 1)
            {
                sb.Remove(sb.Length - 1, 1);
            }

            sb.Append("}");

            return(StringBuilderPool.ReturnAndFree(sb));
        }
        private static TextChange FixDiagnostic(IndentationOptions indentationOptions, SourceText sourceText, Diagnostic diagnostic)
        {
            TextSpan span = diagnostic.Location.SourceSpan;

            TextLine      startLine   = sourceText.Lines.GetLineFromPosition(span.Start);
            string        text        = sourceText.ToString(TextSpan.FromBounds(startLine.Start, span.End));
            StringBuilder replacement = StringBuilderPool.Allocate();
            int           column      = 0;

            for (int i = 0; i < text.Length; i++)
            {
                char c = text[i];
                if (c == '\t')
                {
                    var offsetWithinTabColumn = column % indentationOptions.TabSize;
                    var spaceCount            = indentationOptions.TabSize - offsetWithinTabColumn;

                    if (i >= span.Start - startLine.Start)
                    {
                        replacement.Append(' ', spaceCount);
                    }

                    column += spaceCount;
                }
                else
                {
                    if (i >= span.Start - startLine.Start)
                    {
                        replacement.Append(c);
                    }

                    if (c == '\n')
                    {
                        column = 0;
                    }
                    else
                    {
                        column++;
                    }
                }
            }

            return(new TextChange(span, StringBuilderPool.ReturnAndFree(replacement)));
        }
Exemple #20
0
        /// <inheritdoc/>
        protected override void HandleCompleteDocumentation(SyntaxNodeAnalysisContext context, XElement completeDocumentation, params Location[] diagnosticLocations)
        {
            var objectPool = SharedPools.Default <HashSet <string> >();
            HashSet <string> documentationTexts = objectPool.Allocate();

            // Concatenate all XML node values
            var documentationElements = completeDocumentation.Nodes()
                                        .OfType <XElement>()
                                        .Select(x =>
            {
                var builder = StringBuilderPool.Allocate();

                foreach (var node in x.Nodes())
                {
                    builder.Append(node.ToString().Trim());
                }

                var elementValue = builder.ToString();
                StringBuilderPool.ReturnAndFree(builder);

                return(elementValue);
            });

            foreach (var documentation in documentationElements)
            {
                if (ShouldSkipElement(documentation))
                {
                    continue;
                }

                if (documentationTexts.Contains(documentation))
                {
                    // Add violation
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, diagnosticLocations.First()));
                }
                else
                {
                    documentationTexts.Add(documentation);
                }
            }

            objectPool.ClearAndFree(documentationTexts);
        }
Exemple #21
0
        /// <summary>
        /// Provides a string representation of the <see cref="EventMessage"/> instance for debugging.
        /// </summary>
        public override string ToString()
        {
            var sb = StringBuilderPool.Allocate();

            sb.AppendLine("Event Headers:");

            foreach (var h in Headers.OrderBy(x => x.Key))
            {
                sb.AppendLine("\t" + h.Key + " : " + h.Value);
            }

            if (!string.IsNullOrEmpty(BodyText))
            {
                sb.AppendLine("Body:");
                sb.AppendLine(BodyText);
            }

            return(StringBuilderPool.ReturnAndFree(sb));
        }
        public Task Play(IEnumerable <string> files, Leg leg = Leg.ALeg, string terminator = null)
        {
            var sb    = StringBuilderPool.Allocate();
            var first = true;

            sb.Append("file_string://");

            foreach (var file in files)
            {
                if (!first)
                {
                    sb.Append("!");
                }
                sb.Append(file);
                first = false;
            }

            return(Play(StringBuilderPool.ReturnAndFree(sb), leg, terminator));
        }
        /// <summary>ToString helper.</summary>
        /// <returns>A <see cref="string"/> representation of the BasicMessage instance.</returns>
        public override string ToString()
        {
            var sb = StringBuilderPool.Allocate();

            sb.AppendLine("Headers:\n");

            foreach (var h in Headers.OrderBy(x => x.Key))
            {
                sb.AppendFormat("\t{0}:{1}\n".Fmt(h.Key, h.Value));
            }

            if (BodyText != null)
            {
                sb.AppendLine("Body:\n");
                sb.Append("\t");
                sb.AppendLine(BodyText);
            }

            return(StringBuilderPool.ReturnAndFree(sb));
        }
Exemple #24
0
        private static string BuildProposedName(string currentName)
        {
            StringBuilder builder = StringBuilderPool.Allocate();

            bool foundNonUnderscore   = false;
            bool capitalizeNextLetter = false;

            for (int i = 0; i < currentName.Length; i++)
            {
                char c = currentName[i];
                if (c != '_')
                {
                    foundNonUnderscore = true;

                    if (capitalizeNextLetter)
                    {
                        builder.Append(char.ToUpperInvariant(c));
                        capitalizeNextLetter = false;
                        continue;
                    }
                    else
                    {
                        builder.Append(c);
                        continue;
                    }
                }

                if (!foundNonUnderscore)
                {
                    // Leave leading underscores as-is (they are handled by SA1309)
                    builder.Append(c);
                    continue;
                }

                // drop the underscore(s), and attempt to capitalize the next character
                capitalizeNextLetter = true;
            }

            return(StringBuilderPool.ReturnAndFree(builder));
        }
Exemple #25
0
            private static string ComputeEquivalenceKey(IEnumerable <CodeAction> nestedActions)
            {
                if (nestedActions == null)
                {
                    return(null);
                }

                var equivalenceKey = StringBuilderPool.Allocate();

                try
                {
                    foreach (var action in nestedActions)
                    {
                        equivalenceKey.Append(action.EquivalenceKey ?? action.GetHashCode().ToString() + ";");
                    }

                    return(equivalenceKey.Length > 0 ? equivalenceKey.ToString() : null);
                }
                finally
                {
                    StringBuilderPool.ReturnAndFree(equivalenceKey);
                }
            }
        internal static string GetText(XmlTextSyntax textElement, bool normalizeWhitespace)
        {
            if (textElement == null)
            {
                return(null);
            }

            StringBuilder stringBuilder = StringBuilderPool.Allocate();

            foreach (var item in textElement.TextTokens)
            {
                stringBuilder.Append(item);
            }

            string result = StringBuilderPool.ReturnAndFree(stringBuilder);

            if (normalizeWhitespace)
            {
                result = Regex.Replace(result, @"\s+", " ");
            }

            return(result);
        }
        private static string ProcessMultiLineCommentsHeader(SyntaxTrivia multiLineComment, out int fileHeaderStart, out int fileHeaderEnd)
        {
            var sb = StringBuilderPool.Allocate();

            // wrap the XML from the file header in a single root element to make XML parsing work.
            sb.AppendLine("<root>");

            fileHeaderStart = multiLineComment.FullSpan.Start;
            fileHeaderEnd   = multiLineComment.FullSpan.End;

            var rawCommentString = multiLineComment.ToFullString();
            var commentText      = rawCommentString.Substring(2, rawCommentString.Length - 4);
            var commentLines     = commentText.Replace("\r\n", "\n").Split('\n');

            /* TODO: Ignore borders ??? */

            foreach (var commentLine in commentLines)
            {
                sb.AppendLine(commentLine.TrimStart(' ', '*'));
            }

            sb.AppendLine("</root>");
            return(StringBuilderPool.ReturnAndFree(sb));
        }
        internal static FileHeader ParseFileHeader(SyntaxNode root)
        {
            var firstToken = root.GetFirstToken(includeZeroWidth: true);
            var firstNonWhitespaceTrivia = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia, true);

            if (firstNonWhitespaceTrivia == -1)
            {
                return(FileHeader.MissingFileHeader);
            }

            var sb              = StringBuilderPool.Allocate();
            var endOfLineCount  = 0;
            var done            = false;
            var fileHeaderStart = int.MaxValue;
            var fileHeaderEnd   = int.MinValue;

            for (var i = firstNonWhitespaceTrivia; !done && (i < firstToken.LeadingTrivia.Count); i++)
            {
                var trivia = firstToken.LeadingTrivia[i];

                switch (trivia.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    endOfLineCount = 0;
                    break;

                case SyntaxKind.SingleLineCommentTrivia:
                    endOfLineCount = 0;

                    var commentString = trivia.ToFullString();

                    fileHeaderStart = Math.Min(trivia.FullSpan.Start, fileHeaderStart);
                    fileHeaderEnd   = trivia.FullSpan.End;

                    sb.AppendLine(commentString.Substring(2).Trim());
                    break;

                case SyntaxKind.MultiLineCommentTrivia:
                    // only process a MultiLineCommentTrivia if no SingleLineCommentTrivia have been processed
                    if (sb.Length == 0)
                    {
                        var triviaString = trivia.ToFullString();

                        var startIndex = triviaString.IndexOf("/*", StringComparison.Ordinal) + 2;
                        var endIndex   = triviaString.LastIndexOf("*/", StringComparison.Ordinal);
                        if (endIndex == -1)
                        {
                            // While editing, it is possible to have a multiline comment trivia that does not contain the closing '*/' yet.
                            return(FileHeader.MissingFileHeader);
                        }

                        var commentContext = triviaString.Substring(startIndex, endIndex - startIndex).Trim();

                        var triviaStringParts = commentContext.Replace("\r\n", "\n").Split('\n');

                        foreach (var part in triviaStringParts)
                        {
                            var trimmedPart = part.TrimStart(' ', '*');
                            sb.AppendLine(trimmedPart);
                        }

                        fileHeaderStart = trivia.FullSpan.Start;
                        fileHeaderEnd   = trivia.FullSpan.End;
                    }

                    done = true;
                    break;

                case SyntaxKind.EndOfLineTrivia:
                    endOfLineCount++;
                    done = endOfLineCount > 1;
                    break;

                default:
                    done = (fileHeaderStart < fileHeaderEnd) || !trivia.IsDirective;
                    break;
                }
            }

            if (fileHeaderStart > fileHeaderEnd)
            {
                StringBuilderPool.Free(sb);
                return(FileHeader.MissingFileHeader);
            }

            if (sb.Length > 0)
            {
                // remove the final newline
                var eolLength = Environment.NewLine.Length;
                sb.Remove(sb.Length - eolLength, eolLength);
            }

            return(new FileHeader(StringBuilderPool.ReturnAndFree(sb), fileHeaderStart, fileHeaderEnd));
        }
Exemple #29
0
        private static TextChange FixDiagnostic(IndentationSettings indentationSettings, SourceText sourceText, Diagnostic diagnostic)
        {
            TextSpan span = diagnostic.Location.SourceSpan;

            TextLine startLine = sourceText.Lines.GetLineFromPosition(span.Start);

            bool   useTabs = false;
            string behavior;

            if (diagnostic.Properties.TryGetValue(SA1027UseTabsCorrectly.BehaviorKey, out behavior))
            {
                useTabs = behavior == SA1027UseTabsCorrectly.ConvertToTabsBehavior;
            }

            string        text        = sourceText.ToString(TextSpan.FromBounds(startLine.Start, span.End));
            StringBuilder replacement = StringBuilderPool.Allocate();
            int           spaceCount  = 0;
            int           column      = 0;

            for (int i = 0; i < text.Length; i++)
            {
                char c = text[i];
                if (c == '\t')
                {
                    var offsetWithinTabColumn = column % indentationSettings.TabSize;
                    var tabWidth = indentationSettings.TabSize - offsetWithinTabColumn;

                    if (i >= span.Start - startLine.Start)
                    {
                        if (useTabs)
                        {
                            replacement.Length -= spaceCount;
                            replacement.Append('\t');
                            spaceCount = 0;
                        }
                        else
                        {
                            replacement.Append(' ', tabWidth);
                        }
                    }

                    column += tabWidth;
                }
                else
                {
                    if (i >= span.Start - startLine.Start)
                    {
                        replacement.Append(c);
                        if (c == ' ')
                        {
                            spaceCount++;
                            if (useTabs)
                            {
                                // Note that we account for column not yet being incremented
                                var offsetWithinTabColumn = (column + 1) % indentationSettings.TabSize;
                                if (offsetWithinTabColumn == 0)
                                {
                                    // We reached a tab stop.
                                    replacement.Length -= spaceCount;
                                    replacement.Append('\t');
                                    spaceCount = 0;
                                }
                            }
                        }
                        else
                        {
                            spaceCount = 0;
                        }
                    }

                    if (c == '\r' || c == '\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.
                        column     = 0;
                        spaceCount = 0;
                    }
                    else
                    {
                        column++;
                    }
                }
            }

            return(new TextChange(span, StringBuilderPool.ReturnAndFree(replacement)));
        }
        private static SyntaxNode ReplaceWellFormedMultiLineCommentHeader(Document document, SyntaxNode root, StyleCopSettings settings, int commentIndex, XmlFileHeader header)
        {
            SyntaxTriviaList trivia = root.GetLeadingTrivia();
            var commentTrivia       = trivia[commentIndex];

            // Is the comment pushed in by a prefix?
            var commentIndentation = string.Empty;

            if (commentIndex > 0)
            {
                var prefixTrivia = trivia[commentIndex - 1];
                if (prefixTrivia.IsKind(SyntaxKind.WhitespaceTrivia))
                {
                    commentIndentation = prefixTrivia.ToFullString();
                }
            }

            var triviaString      = commentTrivia.ToFullString();
            var startIndex        = triviaString.IndexOf("/*", StringComparison.Ordinal) + 2;
            var endIndex          = triviaString.LastIndexOf("*/", StringComparison.Ordinal);
            var commentContext    = triviaString.Substring(startIndex, endIndex - startIndex).Trim(' ', '\t').TrimEnd();
            var triviaStringParts = commentContext.Replace("\r\n", "\n").Split('\n');

            // Assume we have comments that have a leading *
            string interlinePadding = " *";

            int    minExpectedLength = (commentIndentation + interlinePadding).Length;
            string newLineText       = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);

            // Examine second line to see if we should have stars or not if it's blank
            // set the interline padding to be blank also.
            if ((triviaStringParts.Length > 2) &&
                (triviaStringParts[1].Length > minExpectedLength) &&
                string.IsNullOrWhiteSpace(triviaStringParts[1].Substring(0, minExpectedLength)))
            {
                interlinePadding = "  ";
            }

            // Pad line that used to be next to a /*
            triviaStringParts[0] = commentIndentation + interlinePadding + " " + triviaStringParts[0];
            StringBuilder sb            = StringBuilderPool.Allocate();
            string        fileName      = GetFileName(document);
            var           copyrightText = GetCopyrightText(commentIndentation + interlinePadding, settings.DocumentationRules.GetCopyrightText(fileName), newLineText);
            var           newHeader     = WrapInXmlComment(commentIndentation + interlinePadding, copyrightText, fileName, settings, newLineText);

            sb.Append(commentIndentation);
            sb.Append("/*");
            if (header.GetElement("copyright") == null)
            {
                // No copyright element at the moment so add us.
                sb.Append(newHeader.Substring(minExpectedLength));
                sb.Append(newLineText);

                // Append the original stuff
                foreach (var oldLine in triviaStringParts)
                {
                    sb.Append(oldLine.TrimEnd());
                    sb.Append(newLineText);
                }
            }
            else
            {
                bool firstLine   = true;
                bool inCopyright = false;
                foreach (var oldLine in triviaStringParts)
                {
                    var openingTag = oldLine.Contains("<copyright ");
                    var closingTag = oldLine.Contains("</copyright>") ||
                                     (openingTag && oldLine.Trim().EndsWith("/>"));
                    if (openingTag)
                    {
                        inCopyright = !closingTag;
                        sb.Append(newHeader.Substring(firstLine ? minExpectedLength : 0));
                        sb.Append(newLineText);
                    }

                    if (inCopyright)
                    {
                        inCopyright = !closingTag;
                    }
                    else
                    {
                        sb.Append(oldLine.Substring(firstLine ? minExpectedLength : 0));
                        sb.Append(newLineText);
                    }

                    firstLine = false;
                }
            }

            sb.Append(commentIndentation);
            sb.Append(" */");

            // Get rid of any trailing spaces.
            var lines = sb.ToString().Split(new string[] { newLineText }, StringSplitOptions.None);

            sb.Clear();
            for (int i = 0; i < lines.Length; i++)
            {
                sb.Append((i == 0 ? string.Empty : newLineText) + lines[i].TrimEnd());
            }

            var newTrivia = SyntaxFactory.SyntaxTrivia(SyntaxKind.MultiLineCommentTrivia, StringBuilderPool.ReturnAndFree(sb));

            return(root.WithLeadingTrivia(trivia.Replace(commentTrivia, newTrivia)));
        }