private static SyntaxList <TNode> Swap <TNode>( SyntaxList <TNode> list, int index1, int index2) where TNode : SyntaxNode { TNode first = list[index1]; TNode second = list[index2]; SyntaxTriviaList firstLeading = first.GetLeadingTrivia(); SyntaxTriviaList secondLeading = second.GetLeadingTrivia(); if (firstLeading.IsEmptyOrWhitespace() && secondLeading.IsEmptyOrWhitespace()) { first = first.WithLeadingTrivia(secondLeading); second = second.WithLeadingTrivia(firstLeading); } SyntaxTriviaList firstTrailing = first.GetTrailingTrivia(); SyntaxTriviaList secondTrailing = second.GetTrailingTrivia(); if (firstTrailing.IsEmptyOrWhitespace() && secondTrailing.IsEmptyOrWhitespace()) { first = first.WithTrailingTrivia(secondTrailing); second = second.WithTrailingTrivia(firstTrailing); } return(list .ReplaceAt(index1, second) .ReplaceAt(index2, first)); }
private static void Analyze( SyntaxNodeAnalysisContext context, SyntaxToken token, SyntaxNode node) { SyntaxTriviaList trailingTrivia = token.TrailingTrivia; SyntaxTriviaList leadingTrivia = node.GetLeadingTrivia(); if (!IsStandardTriviaBetweenLines(trailingTrivia, leadingTrivia) && token .SyntaxTree .GetLineSpan(TextSpan.FromBounds(token.Span.End, node.Span.Start), context.CancellationToken) .GetLineCount() == 3) { SyntaxTrivia trivia = leadingTrivia .SkipWhile(f => f.IsWhitespaceTrivia()) .FirstOrDefault(); if (trivia.IsEndOfLineTrivia() && trailingTrivia.IsEmptyOrWhitespace() && leadingTrivia.IsEmptyOrWhitespace()) { context.ReportDiagnostic( DiagnosticDescriptors.RemoveRedundantEmptyLine, Location.Create(token.SyntaxTree, TextSpan.FromBounds(node.FullSpan.Start, trivia.Span.End))); } } }
private static void Analyze( SyntaxNodeAnalysisContext context, SyntaxToken token, SyntaxNode node, AnalyzerOptionDescriptor obsoleteAnalyzerOption = default) { SyntaxTriviaList trailingTrivia = token.TrailingTrivia; SyntaxTriviaList leadingTrivia = node.GetLeadingTrivia(); if (IsStandardTriviaBetweenLines(trailingTrivia, leadingTrivia)) { return; } if (token .SyntaxTree .GetLineSpan(TextSpan.FromBounds(token.Span.End, node.SpanStart), context.CancellationToken) .GetLineCount() != 3) { return; } var trivia = default(SyntaxTrivia); foreach (SyntaxTrivia t in leadingTrivia) { if (!t.IsWhitespaceTrivia()) { trivia = t; break; } } if (!trivia.IsEndOfLineTrivia()) { return; } if (!trailingTrivia.IsEmptyOrWhitespace()) { return; } if (!leadingTrivia.IsEmptyOrWhitespace()) { return; } Location location = Location.Create(token.SyntaxTree, TextSpan.FromBounds(node.FullSpan.Start, trivia.Span.End)); if (obsoleteAnalyzerOption.IsDefault) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveRedundantEmptyLine, location); } else { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveRedundantEmptyLine, location, obsoleteAnalyzerOption); } }
public static Task <Document> RemoveRedundantAssignmentAfterLocalDeclarationAsync( Document document, VariableDeclaratorSyntax declarator, CancellationToken cancellationToken = default) { var declaration = (VariableDeclarationSyntax)declarator.Parent; var localDeclaration = (LocalDeclarationStatementSyntax)declaration.Parent; StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(localDeclaration); SyntaxList <StatementSyntax> statements = statementsInfo.Statements; int index = statements.IndexOf(localDeclaration); StatementSyntax nextStatement = statements[index + 1]; var expressionStatement = (ExpressionStatementSyntax)nextStatement; var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression; ExpressionSyntax right = assignment.Right; EqualsValueClauseSyntax initializer = declarator.Initializer; ExpressionSyntax value = initializer?.Value; VariableDeclaratorSyntax newDeclarator = (value != null) ? declarator.ReplaceNode(value, right) : declarator.WithInitializer(EqualsValueClause(right)); LocalDeclarationStatementSyntax newLocalDeclaration = localDeclaration.ReplaceNode(declarator, newDeclarator); SyntaxTriviaList trailingTrivia = localDeclaration.GetTrailingTrivia(); if (!trailingTrivia.IsEmptyOrWhitespace()) { newLocalDeclaration = newLocalDeclaration.WithTrailingTrivia(trailingTrivia.Concat(nextStatement.GetTrailingTrivia())); } else { newLocalDeclaration = newLocalDeclaration.WithTrailingTrivia(nextStatement.GetTrailingTrivia()); } SyntaxTriviaList leadingTrivia = nextStatement.GetLeadingTrivia(); if (!leadingTrivia.IsEmptyOrWhitespace()) { newLocalDeclaration = newLocalDeclaration.WithLeadingTrivia(newLocalDeclaration.GetLeadingTrivia().Concat(leadingTrivia)); } SyntaxList <StatementSyntax> newStatements = statements .Replace(localDeclaration, newLocalDeclaration) .RemoveAt(index + 1); return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken)); }
private static void Analyze( SyntaxNodeAnalysisContext context, SyntaxNode node1, SyntaxNode node2) { SyntaxTriviaList trailingTrivia = node1.GetTrailingTrivia(); SyntaxTriviaList leadingTrivia = node2.GetLeadingTrivia(); if (IsStandardTriviaBetweenLines(trailingTrivia, leadingTrivia)) { return; } if (node1 .SyntaxTree .GetLineSpan(TextSpan.FromBounds(node1.Span.End, node2.SpanStart), context.CancellationToken) .GetLineCount() != 3) { return; } var trivia = default(SyntaxTrivia); foreach (SyntaxTrivia t in leadingTrivia) { if (!t.IsWhitespaceTrivia()) { trivia = t; break; } } if (!trivia.IsEndOfLineTrivia()) { return; } if (!trailingTrivia.IsEmptyOrWhitespace()) { return; } if (!leadingTrivia.IsEmptyOrWhitespace()) { return; } DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.RemoveRedundantEmptyLine, Location.Create(node1.SyntaxTree, TextSpan.FromBounds(node2.FullSpan.Start, trivia.Span.End))); }
internal static bool IsFixable(ExpressionSyntax expression, SyntaxToken token) { SyntaxTriviaList expressionTrailing = expression.GetTrailingTrivia(); if (expressionTrailing.IsEmptyOrWhitespace()) { SyntaxTriviaList tokenLeading = token.LeadingTrivia; if (tokenLeading.IsEmptyOrWhitespace()) { SyntaxTriviaList tokenTrailing = token.TrailingTrivia; int count = tokenTrailing.Count; if (count == 1) { if (tokenTrailing[0].IsEndOfLineTrivia()) { return(true); } } else if (count > 1) { for (int i = 0; i < count - 1; i++) { if (!tokenTrailing[i].IsWhitespaceTrivia()) { return(false); } } if (tokenTrailing.Last().IsEndOfLineTrivia()) { return(true); } } } } return(false); }
private static SyntaxToken CreateSemicolonToken(BlockSyntax block, BlockExpressionAnalysis analysis) { SyntaxTriviaList trivia = analysis.SemicolonToken.TrailingTrivia; SyntaxTriviaList leading = block.CloseBraceToken.LeadingTrivia; if (!leading.IsEmptyOrWhitespace()) { trivia = trivia.AddRange(leading); } SyntaxTriviaList trailing = block.CloseBraceToken.TrailingTrivia; if (!trailing.IsEmptyOrWhitespace() || !analysis.SemicolonToken.TrailingTrivia.LastOrDefault().IsEndOfLineTrivia()) { trivia = trivia.AddRange(trailing); } return(analysis.SemicolonToken.WithTrailingTrivia(trivia)); }
private static ArrowExpressionClauseSyntax CreateExpressionBody(BlockExpressionAnalysis analysis, SyntaxNode declaration) { SyntaxToken arrowToken = Token(SyntaxKind.EqualsGreaterThanToken); ExpressionSyntax expression = analysis.Expression; SyntaxToken keyword = analysis.ReturnOrThrowKeyword; switch (keyword.Kind()) { case SyntaxKind.ThrowKeyword: { expression = ThrowExpression(keyword, expression); break; } case SyntaxKind.ReturnKeyword: { SyntaxTriviaList leading = keyword.LeadingTrivia; if (!leading.IsEmptyOrWhitespace()) { arrowToken = arrowToken.WithLeadingTrivia(leading); } SyntaxTriviaList trailing = keyword.TrailingTrivia; if (!trailing.IsEmptyOrWhitespace()) { arrowToken = arrowToken.WithTrailingTrivia(trailing); } break; } } expression = SyntaxTriviaAnalysis.SetIndentation(expression, declaration); return(ArrowExpressionClause(arrowToken, expression)); }
public static Task <Document> FixBinaryExpressionAsync( Document document, BinaryExpressionSyntax binaryExpression, TextSpan span, CancellationToken cancellationToken) { IndentationAnalysis indentationAnalysis = AnalyzeIndentation(binaryExpression, cancellationToken); string indentation; if (indentationAnalysis.Indentation == binaryExpression.GetLeadingTrivia().LastOrDefault() && AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt.IsEnabled(document, binaryExpression)) { indentation = indentationAnalysis.Indentation.ToString(); } else { indentation = indentationAnalysis.GetIncreasedIndentation(); } string endOfLineAndIndentation = DetermineEndOfLine(binaryExpression).ToString() + indentation; var textChanges = new List <TextChange>(); int prevIndex = binaryExpression.Span.End; SyntaxKind binaryKind = binaryExpression.Kind(); while (true) { SyntaxToken token = binaryExpression.OperatorToken; if (token.Span.End > span.End) { continue; } if (token.SpanStart < span.Start) { break; } ExpressionSyntax left = binaryExpression.Left; ExpressionSyntax right = binaryExpression.Right; SyntaxTriviaList leftTrailing = left.GetTrailingTrivia(); SyntaxTriviaList tokenTrailing = token.TrailingTrivia; if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(leftTrailing)) { if (!SetIndentation(token)) { break; } } else if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(tokenTrailing)) { if (!SetIndentation(right)) { break; } } else if (leftTrailing.IsEmptyOrWhitespace() && tokenTrailing.IsEmptyOrWhitespace()) { if (AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt.IsEnabled(document, binaryExpression)) { if (!SetIndentation(right)) { break; } } else if (!SetIndentation(token)) { break; } } if (!left.IsKind(binaryKind)) { break; } binaryExpression = (BinaryExpressionSyntax)left; } if (textChanges.Count > 0) { SyntaxTriviaList leading = binaryExpression.GetLeadingTrivia(); if (!leading.Any()) { SyntaxTrivia trivia = binaryExpression.GetFirstToken().GetPreviousToken().TrailingTrivia.LastOrDefault(); if (trivia.IsEndOfLineTrivia() && trivia.Span.End == binaryExpression.SpanStart) { textChanges.Add(new TextSpan(binaryExpression.SpanStart, 0), indentation); } } } FormattingVerifier.VerifyChangedSpansAreWhitespace(binaryExpression, textChanges); return(document.WithTextChangesAsync(textChanges, cancellationToken)); bool SetIndentation(SyntaxNodeOrToken nodeOrToken) { SyntaxTriviaList leading = nodeOrToken.GetLeadingTrivia(); SyntaxTriviaList.Reversed.Enumerator en = leading.Reverse().GetEnumerator(); if (!en.MoveNext()) { SyntaxTrivia trivia = binaryExpression.FindTrivia(nodeOrToken.SpanStart - 1); string newText = (trivia.IsEndOfLineTrivia()) ? indentation : endOfLineAndIndentation; int start = (trivia.IsWhitespaceTrivia()) ? trivia.SpanStart : nodeOrToken.SpanStart; TextSpan span = (trivia.IsWhitespaceTrivia()) ? trivia.Span : new TextSpan(nodeOrToken.SpanStart, 0); textChanges.Add(span, newText); SetIndendation(nodeOrToken, prevIndex); prevIndex = start; return(true); } SyntaxTrivia last = en.Current; SyntaxKind kind = en.Current.Kind(); if (kind == SyntaxKind.WhitespaceTrivia) { if (en.Current.Span.Length != indentation.Length) { if (!en.MoveNext() || en.Current.IsEndOfLineTrivia()) { SyntaxTrivia trivia = binaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1); if (trivia.IsEndOfLineTrivia()) { AddTextChange((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span); SetIndendation(nodeOrToken, prevIndex); prevIndex = trivia.SpanStart; return(true); } } } } else if (kind == SyntaxKind.EndOfLineTrivia) { SyntaxTrivia trivia = binaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1); if (trivia.IsEndOfLineTrivia()) { AddTextChange((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span); SetIndendation(nodeOrToken, prevIndex); prevIndex = trivia.SpanStart; return(true); } } prevIndex = leading.Span.Start - 1; return(true); void AddTextChange(TextSpan span) => textChanges.Add(span, indentation); } void SetIndendation(SyntaxNodeOrToken nodeOrToken, int endIndex) { ImmutableArray <IndentationInfo> indentations = FindIndentations( binaryExpression, TextSpan.FromBounds(nodeOrToken.SpanStart, endIndex)) .ToImmutableArray(); if (!indentations.Any()) { return; } int firstIndentationLength = indentations[0].Span.Length; for (int j = 0; j < indentations.Length; j++) { IndentationInfo indentationInfo = indentations[j]; string replacement = indentation + indentationAnalysis.GetSingleIndentation(); if (j > 0 && indentationInfo.Span.Length > firstIndentationLength) { replacement += indentationInfo.ToString().Substring(firstIndentationLength); } if (indentationInfo.Span.Length != replacement.Length) { textChanges.Add(indentationInfo.Span, replacement); } } } }
public static Task <Document> FixCallChainAsync( Document document, ExpressionSyntax expression, TextSpan span, CancellationToken cancellationToken = default) { IndentationAnalysis indentationAnalysis = AnalyzeIndentation(expression, cancellationToken); string indentation = indentationAnalysis.GetIncreasedIndentation(); string endOfLineAndIndentation = DetermineEndOfLine(expression).ToString() + indentation; var textChanges = new List <TextChange>(); int prevIndex = expression.Span.End; foreach (SyntaxNode node in new MethodChain(expression)) { SyntaxKind kind = node.Kind(); if (kind == SyntaxKind.SimpleMemberAccessExpression) { var memberAccess = (MemberAccessExpressionSyntax)node; if (!SetIndentation(memberAccess.OperatorToken)) { break; } } else if (kind == SyntaxKind.MemberBindingExpression) { var memberBinding = (MemberBindingExpressionSyntax)node; if (!SetIndentation(memberBinding.OperatorToken)) { break; } } } FormattingVerifier.VerifyChangedSpansAreWhitespace(expression, textChanges); return(document.WithTextChangesAsync(textChanges, cancellationToken)); bool SetIndentation(SyntaxToken token) { if (token.Span.End > span.End) { return(true); } if (token.SpanStart < span.Start) { return(false); } SyntaxTriviaList leading = token.LeadingTrivia; SyntaxTriviaList.Reversed.Enumerator en = leading.Reverse().GetEnumerator(); if (!en.MoveNext()) { SyntaxTrivia trivia = expression.FindTrivia(token.SpanStart - 1); string newText = (trivia.IsEndOfLineTrivia()) ? indentation : endOfLineAndIndentation; textChanges.Add(new TextSpan(token.SpanStart, 0), newText); SetIndendation(token, prevIndex); prevIndex = (trivia.IsEndOfLineTrivia()) ? trivia.SpanStart : token.SpanStart; return(true); } SyntaxTrivia last = en.Current; SyntaxKind kind = en.Current.Kind(); if (kind == SyntaxKind.WhitespaceTrivia) { if (en.Current.Span.Length != indentation.Length) { if (!en.MoveNext() || en.Current.IsEndOfLineTrivia()) { SyntaxTrivia trivia = expression.FindTrivia(token.FullSpan.Start - 1); if (trivia.IsEndOfLineTrivia()) { textChanges.Add((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span, indentation); SetIndendation(token, prevIndex); prevIndex = trivia.SpanStart; return(true); } } } } else if (kind == SyntaxKind.EndOfLineTrivia) { SyntaxTrivia trivia = expression.FindTrivia(token.FullSpan.Start - 1); if (trivia.IsEndOfLineTrivia()) { textChanges.Add((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span, indentation); SetIndendation(token, prevIndex); prevIndex = trivia.SpanStart; return(true); } } prevIndex = leading.Span.Start - 1; return(true); } void SetIndendation(SyntaxToken token, int endIndex) { ImmutableArray <IndentationInfo> indentations = FindIndentations( expression, TextSpan.FromBounds(token.SpanStart, endIndex)) .ToImmutableArray(); if (!indentations.Any()) { return; } int firstIndentationLength = indentations[0].Span.Length; for (int j = 0; j < indentations.Length; j++) { IndentationInfo indentationInfo = indentations[j]; string replacement = indentation + indentationAnalysis.GetSingleIndentation(); if (j > 0 && indentationInfo.Span.Length > firstIndentationLength) { replacement += indentationInfo.ToString().Substring(firstIndentationLength); } if (indentationInfo.Span.Length != replacement.Length) { textChanges.Add(indentationInfo.Span, replacement); } } } }
private static SyntaxTriviaList AddIfNotEmptyOrWhitespace(SyntaxTriviaList trivia, SyntaxTriviaList triviaToAdd) { return((triviaToAdd.IsEmptyOrWhitespace()) ? trivia : trivia.AddRange(triviaToAdd)); }
private static void AnalyzeBinaryExpression(SyntaxNodeAnalysisContext context) { var topBinaryExpression = (BinaryExpressionSyntax)context.Node; SyntaxKind binaryKind = topBinaryExpression.Kind(); if (topBinaryExpression.IsParentKind(binaryKind)) { return; } if (topBinaryExpression.IsSingleLine(includeExteriorTrivia: false)) { return; } int?indentationLength = null; BinaryExpressionSyntax binaryExpression = topBinaryExpression; while (true) { context.CancellationToken.ThrowIfCancellationRequested(); ExpressionSyntax left = binaryExpression.Left; SyntaxToken token = binaryExpression.OperatorToken; SyntaxTriviaList leftTrailing = left.GetTrailingTrivia(); SyntaxTriviaList tokenTrailing = token.TrailingTrivia; if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(leftTrailing)) { if (Analyze(token)) { return; } } else if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(tokenTrailing)) { if (Analyze(binaryExpression.Right)) { return; } } else if (leftTrailing.IsEmptyOrWhitespace() && tokenTrailing.IsEmptyOrWhitespace()) { ReportDiagnostic(); return; } if (!left.IsKind(binaryKind)) { break; } binaryExpression = (BinaryExpressionSyntax)left; } bool Analyze(SyntaxNodeOrToken nodeOrToken) { SyntaxTriviaList.Reversed.Enumerator en = nodeOrToken.GetLeadingTrivia().Reverse().GetEnumerator(); if (!en.MoveNext()) { if ((indentationLength ??= GetIndentationLength()) == -1) { return(true); } ReportDiagnostic(); return(true); } switch (en.Current.Kind()) { case SyntaxKind.WhitespaceTrivia: { if ((indentationLength ??= GetIndentationLength()) == -1) { return(true); } if (en.Current.Span.Length != indentationLength) { if (!en.MoveNext() || en.Current.IsEndOfLineTrivia()) { if (topBinaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1).IsEndOfLineTrivia()) { ReportDiagnostic(); return(true); } } break; } break; } case SyntaxKind.EndOfLineTrivia: { if (topBinaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1).IsEndOfLineTrivia()) { if ((indentationLength ??= GetIndentationLength()) == -1) { return(true); } ReportDiagnostic(); return(true); } break; } } return(false); } int GetIndentationLength() { IndentationAnalysis indentationAnalysis = AnalyzeIndentation(topBinaryExpression); if (indentationAnalysis.IndentSize == 0) { return(-1); } SyntaxTriviaList leadingTrivia = topBinaryExpression.GetLeadingTrivia(); if (leadingTrivia.Any() && leadingTrivia.Last() == indentationAnalysis.Indentation && context.GetConfigOptions().GetBinaryOperatorNewLinePosition() == NewLinePosition.After) { return(indentationAnalysis.IndentationLength); } else { return(indentationAnalysis.IncreasedIndentationLength); } } void ReportDiagnostic() { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.FixFormattingOfBinaryExpressionChain, topBinaryExpression); } }