Exemple #1
0
        public static SyntaxTriviaList GetContainingList(this SyntaxTrivia trivia)
        {
            SyntaxToken token = trivia.Token;

            SyntaxTriviaList leadingTrivia = token.LeadingTrivia;

            int index = leadingTrivia.IndexOf(trivia);

            if (index != -1)
            {
                return(token.LeadingTrivia);
            }

            SyntaxTriviaList trailingTrivia = token.TrailingTrivia;

            index = trailingTrivia.IndexOf(trivia);

            if (index != -1)
            {
                return(token.TrailingTrivia);
            }

            Debug.Assert(false, "containing trivia list not found");

            return(default(SyntaxTriviaList));
        }
        private static Task <Document> RefactorAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            TextSpan span,
            CancellationToken cancellationToken)
        {
            SyntaxTrivia trivia = enumDeclaration.FindTrivia(span.Start);

            SyntaxToken token = trivia.Token;

            EnumMemberDeclarationSyntax enumMemberDeclaration = token
                                                                .GetPreviousToken()
                                                                .Parent
                                                                .FirstAncestorOrSelf <EnumMemberDeclarationSyntax>();

            int enumMemberIndex = enumDeclaration.Members.IndexOf(enumMemberDeclaration);

            SyntaxTriviaList trailingTrivia = token.TrailingTrivia;

            SyntaxToken newToken = token.WithTrailingTrivia(trailingTrivia.Skip(trailingTrivia.IndexOf(trivia) + 1));

            EnumDeclarationSyntax newEnumDeclaration = enumDeclaration.ReplaceToken(token, newToken);

            var settings = new DocumentationCommentGeneratorSettings(ImmutableArray.Create(_leadingSlashesRegex.Replace(trivia.ToString(), "")));

            EnumMemberDeclarationSyntax newEnumMemberDeclaration = newEnumDeclaration.Members[enumMemberIndex].WithNewSingleLineDocumentationComment(settings);

            newEnumDeclaration = newEnumDeclaration.WithMembers(newEnumDeclaration.Members.ReplaceAt(enumMemberIndex, newEnumMemberDeclaration));

            return(document.ReplaceNodeAsync(enumDeclaration, newEnumDeclaration, cancellationToken));
        }
        private static SyntaxNode ProcessTriviaList(SyntaxNode syntaxRoot, SyntaxTriviaList triviaList, SyntaxTrivia singleLineComment)
        {
            var index = triviaList.IndexOf(singleLineComment);

            if (index == -1)
            {
                return(null);
            }

            index--;
            while (index >= 0)
            {
                switch (triviaList[index].Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    index--;
                    break;

                default:
                    return(syntaxRoot.ReplaceTrivia(triviaList[index], new[] { triviaList[index], SyntaxFactory.CarriageReturnLineFeed }));
                }
            }

            return(syntaxRoot.ReplaceTrivia(triviaList[0], new[] { SyntaxFactory.CarriageReturnLineFeed, triviaList[0] }));
        }
Exemple #4
0
        private void ClassifyDisabledText(SyntaxTrivia trivia, SyntaxTriviaList triviaList)
        {
            var index = triviaList.IndexOf(trivia);

            if (
                index >= 2 &&
                triviaList[index - 1].Kind() == SyntaxKind.EndOfLineTrivia &&
                triviaList[index - 2].Kind() == SyntaxKind.ConflictMarkerTrivia
                )
            {
                // for the ======== add a comment for the first line, and then lex all
                // subsequent lines up until the end of the conflict marker.
                foreach (
                    var token in SyntaxFactory.ParseTokens(
                        text: trivia.ToFullString(),
                        initialTokenPosition: trivia.SpanStart
                        )
                    )
                {
                    ClassifyToken(token);
                }
            }
            else
            {
                AddClassification(trivia, ClassificationTypeNames.ExcludedCode);
            }
        }
Exemple #5
0
        private static Task <Document> RefactorAsync(
            Document document,
            PragmaWarningDirectiveTriviaSyntax directive,
            CancellationToken cancellationToken)
        {
            SyntaxTrivia trivia = directive.ParentTrivia;

            SyntaxTriviaList list = trivia.GetContainingList();

            int index = list.IndexOf(trivia);

            int start = directive.EndOfDirectiveToken.SpanStart;

            StringBuilder sb = StringBuilderCache.GetInstance();

            int i = index + 1;

            SyntaxKind disableOrRestoreKind = directive.DisableOrRestoreKeyword.Kind();

            int end = start;

            bool addComma = !directive.ErrorCodes.HasTrailingSeparator();

            while (i < list.Count)
            {
                SyntaxTrivia trivia2 = list[i];

                if (trivia2.IsWhitespaceOrEndOfLineTrivia())
                {
                    i++;
                    continue;
                }

                if (trivia2.GetStructure() is PragmaWarningDirectiveTriviaSyntax directive2 &&
                    disableOrRestoreKind == directive2.DisableOrRestoreKeyword.Kind())
                {
                    if (addComma)
                    {
                        sb.Append(",");
                    }

                    sb.Append(" ");

                    SeparatedSyntaxList <ExpressionSyntax> errorCodes = directive2.ErrorCodes;
                    sb.Append(errorCodes.ToString());

                    addComma = !errorCodes.HasTrailingSeparator();

                    end = directive2.ErrorCodes.Span.End;
                }

                i++;
            }

            return(document.WithTextChangeAsync(
                       TextSpan.FromBounds(start, end),
                       StringBuilderCache.GetStringAndFree(sb),
                       cancellationToken));
        }
Exemple #6
0
        private SyntaxTriviaList RemoveIllegalHeadersFromMultilineComment(SyntaxTriviaList newTrivia, SyntaxTrivia trivia, string illegalHeader)
        {
            StringBuilder newTriviaString          = new StringBuilder();
            bool          commentHasMeaningfulInfo = false;
            bool          removedIllegalHeaders    = false;

            using (StringReader sr = new StringReader(trivia.ToFullString()))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    // If the current line contains the illegal header
                    if (line.IndexOf(illegalHeader, StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        // special care must be had to keep the /* and */ tokens.
                        if (line.TrimStart().StartsWith("/*"))
                        {
                            // Note: This will also cover the case where the comment is: /* illegalHeader */ as we remove the entire line (including the */).
                            newTriviaString.AppendLine("/*");
                        }
                        else if (line.TrimEnd().EndsWith("*/"))
                        {
                            newTriviaString.AppendLine("*/");
                        }
                        removedIllegalHeaders = true;
                    }
                    else
                    {
                        commentHasMeaningfulInfo |= CommentLineContainsMeaningfulIInformation(line);

                        newTriviaString.AppendLine(line);
                    }
                }
            }

            // We should not remove any comments if we don't have to.
            if (!removedIllegalHeaders)
            {
                return(newTrivia);
            }

            // Remove the old trivia and replace it with the new trivia
            var index = newTrivia.IndexOf(trivia);

            newTrivia = RemoveTriviaAtIndex(newTrivia, index);

            if (commentHasMeaningfulInfo)
            {
                // we need to remove the original multiline comment and replace it with this new one.
                var newMultilineComment = SyntaxFactory.Comment(newTriviaString.ToString());
                newTrivia = newTrivia.Insert(index, newMultilineComment);
            }

            return(newTrivia);
        }
        public static Task <Document> RefactorAsync(
            Document document,
            MemberDeclarationSyntax declaration,
            TextSpan span,
            CancellationToken cancellationToken)
        {
            if (declaration is EnumDeclarationSyntax enumDeclaration &&
                span.Start > enumDeclaration.Members.FirstOrDefault()?.SpanStart)
            {
                return(RefactorAsync(document, enumDeclaration, span, cancellationToken));
            }

            MemberDeclarationSyntax newDeclaration = declaration;

            ImmutableArray <string> comments;

            SyntaxTriviaList leadingTrivia = declaration.GetLeadingTrivia();

            if (leadingTrivia.Span.Contains(span))
            {
                comments = leadingTrivia
                           .Where(f => span.Contains(f.Span) && f.Kind() == SyntaxKind.SingleLineCommentTrivia)
                           .Select(f => _leadingSlashesRegex.Replace(f.ToString(), ""))
                           .ToImmutableArray();

                TextSpan spanToRemove = TextSpan.FromBounds(span.Start, declaration.SpanStart);

                newDeclaration = declaration.WithLeadingTrivia(leadingTrivia.Where(f => !spanToRemove.Contains(f.Span)));
            }
            else
            {
                SyntaxTrivia trivia = declaration.FindTrivia(span.Start);

                Debug.Assert(trivia != default);

                SyntaxToken token = trivia.Token;

                SyntaxTriviaList trailingTrivia = token.TrailingTrivia;

                Debug.Assert(trailingTrivia.Contains(trivia));

                comments = ImmutableArray.Create(_leadingSlashesRegex.Replace(trivia.ToString(), ""));

                SyntaxToken newToken = token.WithTrailingTrivia(trailingTrivia.Skip(trailingTrivia.IndexOf(trivia) + 1));

                newDeclaration = newDeclaration.ReplaceToken(token, newToken);
            }

            var settings = new DocumentationCommentGeneratorSettings(comments);

            newDeclaration = newDeclaration.WithNewSingleLineDocumentationComment(settings);

            return(document.ReplaceNodeAsync(declaration, newDeclaration, cancellationToken));
        }
Exemple #8
0
        public Task <SyntaxNode> ProcessAsync(Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken)
        {
            var leadingTrivia          = syntaxNode.GetLeadingTrivia();
            SyntaxTriviaList newTrivia = leadingTrivia;
            var illegalHeaders         = GetIllegalHeaders(document);

            // We also want to add the filename (without path but with extension) to this list.

            // because we are mutating the list, once we remove a header, we won't remove any others...
            for (int idx = 0; idx < illegalHeaders.Length; idx++)
            {
                var illegalHeader = illegalHeaders[idx];
                foreach (var trivia in newTrivia)
                {
                    // If we have an illegal header here...
                    if (trivia.ToFullString().IndexOf(illegalHeader, StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        if (trivia.IsKind(SyntaxKind.MultiLineCommentTrivia))
                        {
                            // For multiline comment trivia we need to process them line by line and remove all the illegal headers.
                            // We then need to re-create the multiline comment and append it to the list.
                            var modifiedTrivia = RemoveIllegalHeadersFromMultilineComment(newTrivia, trivia, illegalHeader);

                            // We need to go back and re-try the current illegal header if we have modified the multiline trivia.
                            if (modifiedTrivia != newTrivia)
                            {
                                newTrivia = modifiedTrivia;
                                idx--;
                            }
                            break;
                        }
                        else
                        {
                            var index = newTrivia.IndexOf(trivia);

                            newTrivia = RemoveTriviaAtIndex(newTrivia, index);

                            // We need to re-try the current illegal header to make sure there are no other comments containing it
                            // further down the trivia list
                            idx--;
                            break;
                        }
                    }
                }
            }

            if (leadingTrivia.Equals(newTrivia))
            {
                return(Task.FromResult(syntaxNode));
            }

            return(Task.FromResult(syntaxNode.WithLeadingTrivia(newTrivia)));
        }
        private static SyntaxTriviaList FixTriviaList(SyntaxTriviaList triviaList, IEnumerable<SyntaxTrivia> commentTrivias)
        {
            foreach (var singleLineComment in commentTrivias)
            {
                int commentLocation = triviaList.IndexOf(singleLineComment);
                if (commentLocation == -1)
                {
                    continue;
                }

                int index = commentLocation + 1;

                index++;
                while (index < triviaList.Count && index > 0)
                {
                    switch (triviaList[index].Kind())
                    {
                    case SyntaxKind.EndOfLineTrivia:
                    case SyntaxKind.WhitespaceTrivia:
                        index++;
                        break;

                    default:

                        if (triviaList[index - 1].IsKind(SyntaxKind.WhitespaceTrivia))
                        {
                            index--;
                        }

                        triviaList = SyntaxTriviaList.Empty.AddRange(triviaList.Take(commentLocation + 2).Concat(triviaList.Skip(index)));

                        // We found the trivia so we don't have to loop any longer
                        index = -1;
                        break;
                    }
                }

                if (index == triviaList.Count)
                {
                    if (triviaList[index - 1].IsKind(SyntaxKind.WhitespaceTrivia))
                    {
                        index--;
                    }

                    triviaList = SyntaxTriviaList.Empty.AddRange(triviaList.Take(commentLocation + 2).Concat(triviaList.Skip(index)));
                }
            }

            return triviaList;
        }
Exemple #10
0
        private void DoTestAddInsertRemoveReplaceOnEmptyList(SyntaxTriviaList list)
        {
            Assert.Equal(0, list.Count);

            var triviaD = SyntaxFactory.ParseLeadingTrivia("/*D*/")[0];
            var triviaE = SyntaxFactory.ParseLeadingTrivia("/*E*/")[0];

            var newList = list.Add(triviaD);

            Assert.Equal(1, newList.Count);
            Assert.Equal("/*D*/", newList.ToFullString());

            newList = list.AddRange(new[] { triviaD, triviaE });
            Assert.Equal(2, newList.Count);
            Assert.Equal("/*D*//*E*/", newList.ToFullString());

            newList = list.Insert(0, triviaD);
            Assert.Equal(1, newList.Count);
            Assert.Equal("/*D*/", newList.ToFullString());

            newList = list.InsertRange(0, new[] { triviaD, triviaE });
            Assert.Equal(2, newList.Count);
            Assert.Equal("/*D*//*E*/", newList.ToFullString());

            newList = list.Remove(triviaD);
            Assert.Equal(0, newList.Count);

            Assert.Equal(-1, list.IndexOf(triviaD));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.RemoveAt(0));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.Insert(1, triviaD));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.Insert(-1, triviaD));
            Assert.Throws <ArgumentOutOfRangeException>(
                () => list.InsertRange(1, new[] { triviaD })
                );
            Assert.Throws <ArgumentOutOfRangeException>(
                () => list.InsertRange(-1, new[] { triviaD })
                );
            Assert.Throws <ArgumentOutOfRangeException>(() => list.Replace(triviaD, triviaE));
            Assert.Throws <ArgumentOutOfRangeException>(
                () => list.ReplaceRange(triviaD, new[] { triviaE })
                );
            Assert.Throws <ArgumentOutOfRangeException>(() => list.Add(default(SyntaxTrivia)));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.Insert(0, default(SyntaxTrivia)));
            Assert.Throws <ArgumentNullException>(
                () => list.AddRange((IEnumerable <SyntaxTrivia>)null)
                );
            Assert.Throws <ArgumentNullException>(
                () => list.InsertRange(0, (IEnumerable <SyntaxTrivia>)null)
                );
        }
Exemple #11
0
        private static Task <Document> AddEmptyLineBeforeWhileInDoStatementAsync(
            Document document,
            StatementSyntax statement,
            CancellationToken cancellationToken = default)
        {
            SyntaxTriviaList trailingTrivia = statement.GetTrailingTrivia();

            int index = trailingTrivia.IndexOf(SyntaxKind.EndOfLineTrivia);

            SyntaxTriviaList newTrailingTrivia = trailingTrivia.Insert(index, CSharpFactory.NewLine());

            StatementSyntax newStatement = statement.WithTrailingTrivia(newTrailingTrivia);

            return(document.ReplaceNodeAsync(statement, newStatement, cancellationToken));
        }
Exemple #12
0
        public static bool IsFixable(SyntaxTrivia trivia)
        {
            if (trivia.Kind() != SyntaxKind.SingleLineCommentTrivia)
            {
                return(false);
            }

            if (!(trivia.Token.Parent is MemberDeclarationSyntax memberDeclaration))
            {
                return(false);
            }

            if (trivia.SpanStart >= memberDeclaration.SpanStart)
            {
                return(false);
            }

            SyntaxTriviaList leadingTrivia = memberDeclaration.GetLeadingTrivia();

            int i = leadingTrivia.IndexOf(trivia);

            Debug.Assert(i != -1, trivia.ToString());

            if (i == -1)
            {
                return(false);
            }

            i++;

            while (i < leadingTrivia.Count)
            {
                if (!leadingTrivia[i].IsKind(
                        SyntaxKind.WhitespaceTrivia,
                        SyntaxKind.EndOfLineTrivia,
                        SyntaxKind.SingleLineCommentTrivia))
                {
                    return(false);
                }

                i++;
            }

            return(true);
        }
        /// <summary>
        /// Get new leading trivia with summary comments inserted
        /// </summary>
        /// <param name="leadingTrivias">Original leading trivia</param>
        /// <param name="summaryComments">Enumerable of summary comments</param>
        /// <param name="whitespaceCount">Whitespace count</param>
        /// <returns>new leading trivia with summary comments inserted</returns>
        public static IEnumerable <SyntaxTrivia> GetNewLeadingTriviaWithSummary(SyntaxTriviaList leadingTrivias, IEnumerable <string> summaryComments, int whitespaceCount)
        {
            var summaryTrivias = SyntaxFactory.ParseLeadingTrivia(ConcatCommentString(summaryComments, whitespaceCount));
            var index          = leadingTrivias.IndexOf(SyntaxKind.SingleLineDocumentationCommentTrivia);

            if (index == -1)
            {
                index = 0;
            }

            if (index > 0 &&
                leadingTrivias[index - 1].Kind() == SyntaxKind.WhitespaceTrivia)
            {
                index -= 1;
            }

            return(leadingTrivias.InsertRange(index, summaryTrivias));
        }
        private static async Task <Document> AddEmptyLineAsync(
            Document document,
            StatementSyntax statement,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SyntaxTriviaList trailingTrivia = statement.GetTrailingTrivia();

            int index = trailingTrivia.IndexOf(SyntaxKind.EndOfLineTrivia);

            SyntaxTriviaList newTrailingTrivia = trailingTrivia.Insert(index, CSharpFactory.NewLineTrivia());

            StatementSyntax newStatement = statement.WithTrailingTrivia(newTrailingTrivia);

            SyntaxNode newRoot = root.ReplaceNode(statement, newStatement);

            return(document.WithSyntaxRoot(newRoot));
        }
Exemple #15
0
            public override SyntaxTriviaList VisitList(SyntaxTriviaList list)
            {
                var index = list.IndexOf(_originalTrivia);

                if (index >= 0 && index < list.Count)
                {
                    switch (editKind)
                    {
                    case ListEditKind.Replace:
                        return(list.ReplaceRange(_originalTrivia, _newTrivia));

                    case ListEditKind.InsertAfter:
                        return(list.InsertRange(index + 1, _newTrivia));

                    case ListEditKind.InsertBefore:
                        return(list.InsertRange(index, _newTrivia));
                    }
                }

                return(base.VisitList(list));
            }
Exemple #16
0
        public static Task <Document> AddEmptyLineBeforeDirectiveAsync(
            Document document,
            DirectiveTriviaSyntax directiveTrivia,
            CancellationToken cancellationToken = default)
        {
            SyntaxTrivia     parentTrivia  = directiveTrivia.ParentTrivia;
            SyntaxToken      token         = parentTrivia.Token;
            SyntaxTriviaList leadingTrivia = token.LeadingTrivia;

            int index = leadingTrivia.IndexOf(parentTrivia);

            if (index > 0 &&
                leadingTrivia[index - 1].IsWhitespaceTrivia())
            {
                index--;
            }

            SyntaxTriviaList newLeadingTrivia = leadingTrivia.Insert(index, SyntaxTriviaAnalysis.DetermineEndOfLine(token));

            SyntaxToken newToken = token.WithLeadingTrivia(newLeadingTrivia);

            return(document.ReplaceTokenAsync(token, newToken, cancellationToken));
        }
Exemple #17
0
        private static SyntaxNode ProcessTriviaList(SyntaxNode syntaxRoot, SyntaxTriviaList triviaList, SyntaxTrivia singleLineComment)
        {
            var index = triviaList.IndexOf(singleLineComment);

            if (index == -1)
            {
                return(null);
            }

            do
            {
                index++;
            }while (!triviaList[index].IsKind(SyntaxKind.EndOfLineTrivia));

            var startOfBlankLine = index;

            do
            {
                index++;
            }while (!triviaList[index].IsKind(SyntaxKind.EndOfLineTrivia));

            return(syntaxRoot.ReplaceTrivia(triviaList.Skip(startOfBlankLine).Take(index - startOfBlankLine), (t1, t2) => default(SyntaxTrivia)));
        }
        private static SyntaxNode ProcessTriviaList(SyntaxNode syntaxRoot, SyntaxTriviaList triviaList, SyntaxTrivia singleLineComment)
        {
            var index = triviaList.IndexOf(singleLineComment);
            if (index == -1)
            {
                return null;
            }

            do
            {
                index++;
            }
            while (!triviaList[index].IsKind(SyntaxKind.EndOfLineTrivia));

            var startOfBlankLine = index;

            do
            {
                index++;
            }
            while (!triviaList[index].IsKind(SyntaxKind.EndOfLineTrivia));

            return syntaxRoot.ReplaceTrivia(triviaList.Skip(startOfBlankLine).Take(index - startOfBlankLine), (t1, t2) => default(SyntaxTrivia));
        }
        /// <summary>
        /// Determines if the node should be json serialized based on the precedence of
        /// a //json single line comment
        /// </summary>
        public static bool ShouldBeConvertedToJson(this SyntaxNode node, SyntaxTriviaList leadingTrivia)
        {
            if (leadingTrivia == default)
            {
                return(false);
            }

            var singleLineCommentIndex = leadingTrivia.IndexOf(SyntaxKind.SingleLineCommentTrivia);

            if (singleLineCommentIndex == -1)
            {
                return(false);
            }

            // all trivia after the single line should be whitespace or end of line
            if (!leadingTrivia
                .SkipWhile((l, i) => i < singleLineCommentIndex)
                .Any(l => l.IsKind(SyntaxKind.EndOfLineTrivia) || l.IsKind(SyntaxKind.WhitespaceTrivia)))
            {
                return(false);
            }

            return(SingleLineJsonComment.IsMatch(leadingTrivia.ElementAt(singleLineCommentIndex).ToFullString()));
        }
        private static SyntaxTriviaList FixTriviaList(SyntaxTriviaList triviaList, IEnumerable <SyntaxTrivia> commentTrivias)
        {
            foreach (var singleLineComment in commentTrivias)
            {
                var index = triviaList.IndexOf(singleLineComment);
                if (index == -1)
                {
                    continue;
                }

                index--;
                while (index >= 0)
                {
                    switch (triviaList[index].Kind())
                    {
                    case SyntaxKind.WhitespaceTrivia:
                        index--;
                        break;

                    default:
                        triviaList = triviaList.ReplaceRange(triviaList[index], new[] { triviaList[index], SyntaxFactory.CarriageReturnLineFeed });

                        // We found the trivia so we don't have to loop any longer
                        index = -2;
                        break;
                    }
                }

                if (index == -1)
                {
                    triviaList = triviaList.ReplaceRange(triviaList[0], new[] { SyntaxFactory.CarriageReturnLineFeed, triviaList[0] });
                }
            }

            return(triviaList);
        }
        private static SyntaxTriviaList FixTriviaList(SyntaxTriviaList triviaList, IEnumerable<SyntaxTrivia> commentTrivias)
        {
            foreach (var singleLineComment in commentTrivias)
            {
                var index = triviaList.IndexOf(singleLineComment);
                if (index == -1)
                {
                    continue;
                }

                index--;
                while (index >= 0)
                {
                    switch (triviaList[index].Kind())
                    {
                    case SyntaxKind.WhitespaceTrivia:
                        index--;
                        break;

                    default:
                        triviaList = triviaList.ReplaceRange(triviaList[index], new[] { triviaList[index], SyntaxFactory.CarriageReturnLineFeed });

                        // We found the trivia so we don't have to loop any longer
                        index = -2;
                        break;
                    }
                }

                if (index == -1)
                {
                    triviaList = triviaList.ReplaceRange(triviaList[0], new[] { SyntaxFactory.CarriageReturnLineFeed, triviaList[0] });
                }
            }

            return triviaList;
        }
        private static SyntaxNode ProcessTriviaList(SyntaxNode syntaxRoot, SyntaxTriviaList triviaList, SyntaxTrivia singleLineComment)
        {
            var index = triviaList.IndexOf(singleLineComment);
            if (index == -1)
            {
                return null;
            }

            index--;
            while (index >= 0)
            {
                switch (triviaList[index].Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    index--;
                    break;

                default:
                    return syntaxRoot.ReplaceTrivia(triviaList[index], new[] { triviaList[index], SyntaxFactory.CarriageReturnLineFeed });
                }
            }

            return syntaxRoot.ReplaceTrivia(triviaList[0], new[] { SyntaxFactory.CarriageReturnLineFeed, triviaList[0] });
        }
        private SyntaxTriviaList RemoveIllegalHeadersFromMultilineComment(SyntaxTriviaList newTrivia, SyntaxTrivia trivia, string illegalHeader)
        {
            StringBuilder newTriviaString = new StringBuilder();
            bool commentHasMeaningfulInfo = false;
            bool removedIllegalHeaders = false;
            using (StringReader sr = new StringReader(trivia.ToFullString()))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    // If the current line contains the illegal header
                    if (line.IndexOf(illegalHeader, StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        // special care must be had to keep the /* and */ tokens.
                        if (line.TrimStart().StartsWith("/*"))
                        {
                            // Note: This will also cover the case where the comment is: /* illegalHeader */ as we remove the entire line (including the */).
                            newTriviaString.AppendLine("/*");
                        }
                        else if (line.TrimEnd().EndsWith("*/"))
                        {
                            newTriviaString.AppendLine("*/");
                        }
                        removedIllegalHeaders = true;
                    }
                    else
                    {
                        commentHasMeaningfulInfo |= CommentLineContainsMeaningfulIInformation(line);

                        newTriviaString.AppendLine(line);
                    }
                }
            }

            // We should not remove any comments if we don't have to.
            if (!removedIllegalHeaders)
            {
                return newTrivia;
            }

            // Remove the old trivia and replace it with the new trivia
            var index = newTrivia.IndexOf(trivia);
            newTrivia = RemoveTriviaAtIndex(newTrivia, index);

            if (commentHasMeaningfulInfo)
            {
                // we need to remove the original multiline comment and replace it with this new one.
                var newMultilineComment = SyntaxFactory.Comment(newTriviaString.ToString());
                newTrivia = newTrivia.Insert(index, newMultilineComment);
            }

            return newTrivia;
        }
 public static bool Contains(this SyntaxTriviaList list, SyntaxKind kind)
 {
     return(list.IndexOf(kind) != -1);
 }
        private void DoTestAddInsertRemoveReplaceOnEmptyList(SyntaxTriviaList list)
        {
            Assert.Equal(0, list.Count);

            var triviaD = SyntaxFactory.ParseLeadingTrivia("/*D*/")[0];
            var triviaE = SyntaxFactory.ParseLeadingTrivia("/*E*/")[0];

            var newList = list.Add(triviaD);
            Assert.Equal(1, newList.Count);
            Assert.Equal("/*D*/", newList.ToFullString());

            newList = list.AddRange(new[] { triviaD, triviaE });
            Assert.Equal(2, newList.Count);
            Assert.Equal("/*D*//*E*/", newList.ToFullString());

            newList = list.Insert(0, triviaD);
            Assert.Equal(1, newList.Count);
            Assert.Equal("/*D*/", newList.ToFullString());

            newList = list.InsertRange(0, new[] { triviaD, triviaE });
            Assert.Equal(2, newList.Count);
            Assert.Equal("/*D*//*E*/", newList.ToFullString());

            newList = list.Remove(triviaD);
            Assert.Equal(0, newList.Count);

            Assert.Equal(-1, list.IndexOf(triviaD));
            Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(0));
            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(1, triviaD));
            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(-1, triviaD));
            Assert.Throws<ArgumentOutOfRangeException>(() => list.InsertRange(1, new[] { triviaD }));
            Assert.Throws<ArgumentOutOfRangeException>(() => list.InsertRange(-1, new[] { triviaD }));
            Assert.Throws<ArgumentException>(() => list.Replace(triviaD, triviaE));
            Assert.Throws<ArgumentException>(() => list.ReplaceRange(triviaD, new[] { triviaE }));
            Assert.Throws<ArgumentException>(() => list.Add(default(SyntaxTrivia)));
            Assert.Throws<ArgumentException>(() => list.Insert(0, default(SyntaxTrivia)));
            Assert.Throws<ArgumentNullException>(() => list.AddRange((IEnumerable<SyntaxTrivia>)null));
            Assert.Throws<ArgumentNullException>(() => list.InsertRange(0, (IEnumerable<SyntaxTrivia>)null));
        }