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) ); }
private static void InsertIfNotWhiteSpaceOrEndOfLine(IEnumerable <SyntaxTrivia> trivia, ref SyntaxTriviaList triviaList) { if (trivia.Any(f => !f.IsWhitespaceOrEndOfLineTrivia())) { triviaList = triviaList.InsertRange(0, trivia); } }
/// <summary> /// Ensure the trivia list has a blank line at the end. Both the second to last /// and final line may contain spaces. /// /// Note: This function assumes the trivia token before <param name="startIndex" /> /// is an end of line trivia. /// </summary> private static void EnsureHasBlankLineAtEnd(ref SyntaxTriviaList list, int startIndex, SyntaxTrivia newLineTrivia) { const int StateNone = 0; const int StateEol = 1; const int StateBlankLine = 2; var state = StateEol; var index = startIndex; var eolIndex = startIndex - 1; while (index < list.Count) { var current = list[index]; if (current.IsKind(SyntaxKind.WhitespaceTrivia)) { index++; continue; } var isStateAnyEol = (state == StateEol || state == StateBlankLine); if (isStateAnyEol && current.IsKind(SyntaxKind.EndOfLineTrivia)) { state = StateBlankLine; } else if (current.IsAnyEndOfLine()) { eolIndex = index; state = StateEol; } else { state = StateNone; } index++; } switch (state) { case StateNone: list = list.InsertRange(list.Count, new[] { newLineTrivia, newLineTrivia }); break; case StateEol: list = list.Insert(eolIndex + 1, newLineTrivia); break; case StateBlankLine: // Nothing to do. break; default: Debug.Assert(false); break; } }
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)); }
public static async Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { ExpressionSyntax left = binaryExpression.Left; ExpressionSyntax right = binaryExpression.Right; SyntaxToken operatorToken = binaryExpression.OperatorToken; ExpressionSyntax newNode = binaryExpression; TextSpan span = TextSpan.FromBounds(left.Span.End, right.Span.Start); IEnumerable <SyntaxTrivia> trivia = binaryExpression.DescendantTrivia(span); bool isWhiteSpaceOrEndOfLine = trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()); if (left.IsBooleanLiteralExpression()) { SyntaxTriviaList leadingTrivia = binaryExpression.GetLeadingTrivia(); if (!isWhiteSpaceOrEndOfLine) { leadingTrivia = leadingTrivia.AddRange(trivia); } newNode = right .Negate() .WithLeadingTrivia(leadingTrivia); } else if (right.IsBooleanLiteralExpression()) { SyntaxTriviaList trailingTrivia = binaryExpression.GetTrailingTrivia(); if (!isWhiteSpaceOrEndOfLine) { trailingTrivia = trailingTrivia.InsertRange(0, trivia); } newNode = left .Negate() .WithTrailingTrivia(trailingTrivia); } #if DEBUG else { Debug.Assert(false, binaryExpression.ToString()); } #endif return(await document.ReplaceNodeAsync(binaryExpression, newNode.WithFormatterAnnotation(), cancellationToken).ConfigureAwait(false)); }
public static Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { ExpressionSyntax left = binaryExpression.Left; ExpressionSyntax right = binaryExpression.Right; ExpressionSyntax newNode = binaryExpression; TextSpan span = TextSpan.FromBounds(left.Span.End, right.SpanStart); IEnumerable <SyntaxTrivia> trivia = binaryExpression.DescendantTrivia(span); bool isWhiteSpaceOrEndOfLine = trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()); if (IsBooleanLiteralExpression(left.Kind())) { SyntaxTriviaList leadingTrivia = binaryExpression.GetLeadingTrivia(); if (!isWhiteSpaceOrEndOfLine) { leadingTrivia = leadingTrivia.AddRange(trivia); } newNode = right.WithLeadingTrivia(leadingTrivia); } else if (IsBooleanLiteralExpression(right.Kind())) { SyntaxTriviaList trailingTrivia = binaryExpression.GetTrailingTrivia(); if (!isWhiteSpaceOrEndOfLine) { trailingTrivia = trailingTrivia.InsertRange(0, trivia); } newNode = left.WithTrailingTrivia(trailingTrivia); } else { SyntaxDebug.Fail(binaryExpression); } return(document.ReplaceNodeAsync(binaryExpression, newNode.WithFormatterAnnotation(), cancellationToken)); }
/// <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)); }
public static MemberDeclarationSyntax GenerateAndAttach(MemberDeclarationSyntax memberDeclaration, DocumentationCommentGeneratorSettings settings = null) { if (memberDeclaration == null) { throw new ArgumentNullException(nameof(memberDeclaration)); } SyntaxTriviaList leadingTrivia = memberDeclaration.GetLeadingTrivia(); int index = 0; string indent = ""; if (leadingTrivia.Any()) { index = leadingTrivia.Count - 1; for (int i = leadingTrivia.Count - 1; i >= 0; i--) { if (leadingTrivia[i].IsWhitespaceTrivia()) { index = i; } else { break; } } indent = string.Concat(leadingTrivia.Skip(index)); } settings = settings ?? DocumentationCommentGeneratorSettings.Default; settings = settings.WithIndent(indent); SyntaxTriviaList comment = Generate(memberDeclaration, settings); SyntaxTriviaList newLeadingTrivia = leadingTrivia.InsertRange(index, comment); return(memberDeclaration.WithLeadingTrivia(newLeadingTrivia)); }
public static Task <Document> RefactorAsync( Document document, InvocationExpressionSyntax invocation, CancellationToken cancellationToken) { var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; var invocation2 = (InvocationExpressionSyntax)memberAccess.Expression; var memberAccess2 = (MemberAccessExpressionSyntax)invocation2.Expression; ExpressionSyntax expression1 = GetCondition(invocation); ExpressionSyntax expression2 = GetCondition(invocation2); InvocationExpressionSyntax newInvocation = invocation2.ReplaceNode( expression2, LogicalAndExpression( expression2.Parenthesize().WithSimplifierAnnotation(), expression1.Parenthesize().WithSimplifierAnnotation())); var newMemberAccess = (MemberAccessExpressionSyntax)newInvocation.Expression; SyntaxTriviaList trailingTrivia = invocation.GetTrailingTrivia(); IEnumerable <SyntaxTrivia> trivia = invocation.DescendantTrivia(TextSpan.FromBounds(invocation2.Span.End, memberAccess.Name.SpanStart)); if (trivia.Any(f => !f.IsWhitespaceOrEndOfLineTrivia())) { trailingTrivia = trailingTrivia.InsertRange(0, trivia); } newInvocation = newInvocation .WithExpression(newMemberAccess) .WithTrailingTrivia(trailingTrivia) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(invocation, newInvocation, cancellationToken)); }
private static XmlElementSyntax TrimWhitespaceContent(XmlElementSyntax paragraph, out SyntaxList <XmlNodeSyntax> leadingWhitespaceContent, out SyntaxList <XmlNodeSyntax> trailingWhitespaceContent) { SyntaxList <XmlNodeSyntax> completeContent = XmlSyntaxFactory.List(paragraph.Content.SelectMany(ExpandTextNodes).ToArray()); leadingWhitespaceContent = XmlSyntaxFactory.List(completeContent.TakeWhile(x => XmlCommentHelper.IsConsideredEmpty(x)).ToArray()); trailingWhitespaceContent = XmlSyntaxFactory.List(completeContent.Skip(leadingWhitespaceContent.Count).Reverse().TakeWhile(x => XmlCommentHelper.IsConsideredEmpty(x)).Reverse().ToArray()); SyntaxList <XmlNodeSyntax> trimmedContent = XmlSyntaxFactory.List(completeContent.Skip(leadingWhitespaceContent.Count).Take(completeContent.Count - leadingWhitespaceContent.Count - trailingWhitespaceContent.Count).ToArray()); SyntaxTriviaList leadingTrivia = SyntaxFactory.TriviaList(); SyntaxTriviaList trailingTrivia = SyntaxFactory.TriviaList(); if (trimmedContent.Any()) { leadingTrivia = trimmedContent[0].GetLeadingTrivia(); trailingTrivia = trimmedContent.Last().GetTrailingTrivia(); trimmedContent = trimmedContent.Replace(trimmedContent[0], trimmedContent[0].WithoutLeadingTrivia()); trimmedContent = trimmedContent.Replace(trimmedContent.Last(), trimmedContent.Last().WithoutTrailingTrivia()); } else { leadingTrivia = SyntaxFactory.TriviaList(); trailingTrivia = SyntaxFactory.TriviaList(); } XmlElementSyntax result = paragraph; if (leadingWhitespaceContent.Any()) { var first = leadingWhitespaceContent[0]; var newFirst = first.WithLeadingTrivia(first.GetLeadingTrivia().InsertRange(0, paragraph.GetLeadingTrivia())); leadingWhitespaceContent = leadingWhitespaceContent.Replace(first, newFirst); } else { leadingTrivia = leadingTrivia.InsertRange(0, result.GetLeadingTrivia()); } if (trailingWhitespaceContent.Any()) { var last = trailingWhitespaceContent.Last(); var newLast = last.WithLeadingTrivia(last.GetLeadingTrivia().AddRange(paragraph.GetTrailingTrivia())); trailingWhitespaceContent = trailingWhitespaceContent.Replace(last, newLast); } else { trailingTrivia = trailingTrivia.AddRange(result.GetTrailingTrivia()); } if (trimmedContent.FirstOrDefault() is XmlTextSyntax firstTextNode && firstTextNode.TextTokens.Any()) { SyntaxToken firstTextToken = firstTextNode.TextTokens[0]; string leadingWhitespace = new(firstTextToken.Text.Cast <char>().TakeWhile(char.IsWhiteSpace).ToArray()); if (leadingWhitespace.Length > 0) { SyntaxToken newFirstTextToken = XmlSyntaxFactory.TextLiteral(firstTextToken.Text.Substring(leadingWhitespace.Length)).WithTriviaFrom(firstTextToken); XmlTextSyntax newFirstTextNode = firstTextNode.WithTextTokens(firstTextNode.TextTokens.Replace(firstTextToken, newFirstTextToken)); trimmedContent = trimmedContent.Replace(firstTextNode, newFirstTextNode); leadingTrivia = leadingTrivia.Add(SyntaxFactory.Whitespace(leadingWhitespace)); } } if (trimmedContent.LastOrDefault() is XmlTextSyntax lastTextNode && lastTextNode.TextTokens.Any()) { SyntaxToken lastTextToken = lastTextNode.TextTokens.Last(); string trailingWhitespace = new(lastTextToken.Text.Cast <char>().Reverse().TakeWhile(char.IsWhiteSpace).Reverse().ToArray()); if (trailingWhitespace.Length > 0) { SyntaxToken newLastTextToken = XmlSyntaxFactory.TextLiteral(lastTextToken.Text.Substring(0, lastTextToken.Text.Length - trailingWhitespace.Length)).WithTriviaFrom(lastTextToken); XmlTextSyntax newLastTextNode = lastTextNode.WithTextTokens(lastTextNode.TextTokens.Replace(lastTextToken, newLastTextToken)); trimmedContent = trimmedContent.Replace(lastTextNode, newLastTextNode); trailingTrivia = trailingTrivia.Insert(0, SyntaxFactory.Whitespace(trailingWhitespace)); } } return(result.WithContent(trimmedContent) .WithLeadingTrivia(leadingTrivia) .WithTrailingTrivia(trailingTrivia)); }
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)); }
/// <summary> /// Get new leading trivia with doxygen comments inserted /// </summary> /// <param name="leadingTrivias">Original leading trivia</param> /// <param name="doxygenComments">Enumerable of doxygen comments</param> /// <param name="whitespaceCount">Whitespace count</param> /// <returns>new leading trivia with doxygen comments inserted</returns> public static SyntaxTriviaList GetNewLeadingTrivia(SyntaxTriviaList leadingTrivias, IEnumerable <string> doxygenComments, int whitespaceCount) { var commentTrivias = SyntaxFactory.ParseLeadingTrivia(ConcatCommentString(doxygenComments, whitespaceCount)); return(leadingTrivias.InsertRange(leadingTrivias.Count - 1, commentTrivias)); }
private static async Task <ExpressionSyntax> CreateNewNodeAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { ExpressionSyntax left = binaryExpression.Left; ExpressionSyntax right = binaryExpression.Right; TextSpan span = TextSpan.FromBounds(left.Span.End, right.Span.Start); IEnumerable <SyntaxTrivia> trivia = binaryExpression.DescendantTrivia(span); bool isWhiteSpaceOrEndOfLine = trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (left.Kind().IsBooleanLiteralExpression()) { SyntaxTriviaList leadingTrivia = binaryExpression.GetLeadingTrivia(); if (!isWhiteSpaceOrEndOfLine) { leadingTrivia = leadingTrivia.AddRange(trivia); } if (right.IsKind(SyntaxKind.LogicalNotExpression)) { var logicalNot = (PrefixUnaryExpressionSyntax)right; ExpressionSyntax operand = logicalNot.Operand; if (semanticModel.GetTypeInfo(operand, cancellationToken).ConvertedType.IsNullableOf(SpecialType.System_Boolean)) { return(binaryExpression .WithLeft(LogicalNegationHelper.LogicallyNegate(left, semanticModel, cancellationToken)) .WithRight(operand.WithTriviaFrom(right))); } } return(LogicalNegationHelper.LogicallyNegate(right, semanticModel, cancellationToken) .WithLeadingTrivia(leadingTrivia)); } else if (right.Kind().IsBooleanLiteralExpression()) { SyntaxTriviaList trailingTrivia = binaryExpression.GetTrailingTrivia(); if (!isWhiteSpaceOrEndOfLine) { trailingTrivia = trailingTrivia.InsertRange(0, trivia); } if (left.IsKind(SyntaxKind.LogicalNotExpression)) { var logicalNot = (PrefixUnaryExpressionSyntax)left; ExpressionSyntax operand = logicalNot.Operand; if (semanticModel.GetTypeInfo(operand, cancellationToken).ConvertedType.IsNullableOf(SpecialType.System_Boolean)) { return(binaryExpression .WithLeft(operand.WithTriviaFrom(left)) .WithRight(LogicalNegationHelper.LogicallyNegate(right, semanticModel, cancellationToken))); } } return(LogicalNegationHelper.LogicallyNegate(left, semanticModel, cancellationToken) .WithTrailingTrivia(trailingTrivia)); } Debug.Fail(binaryExpression.ToString()); return(binaryExpression); }