private bool ContainsNoisyTrivia(SyntaxTriviaList list) { return(list.Any(t => !_nonNoisySet.Contains(t.RawKind))); }
private static bool ContainsComment(SyntaxTriviaList trivias) { return(trivias.Any(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineCommentTrivia))); }
private bool HasDocumentationComment(SyntaxTriviaList existingTrivia) { return existingTrivia.Any(SyntaxKind.DocumentationCommentTrivia) || existingTrivia.Any(x => x.ToFullString().IndexOf("<summary>") != -1); }
private static void Analyze <TNode>( SyntaxNodeAnalysisContext context, SyntaxNodeOrToken openNodeOrToken, SeparatedSyntaxList <TNode> nodes) where TNode : SyntaxNode { TNode first = nodes.FirstOrDefault(); if (first == null) { return; } TextSpan span = nodes.GetSpan(includeExteriorTrivia: false); if (span.IsSingleLine(first.SyntaxTree)) { SyntaxTriviaList trailing = openNodeOrToken.GetTrailingTrivia(); if (!IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing)) { return; } int indentationLength = GetIncreasedIndentationLength(openNodeOrToken.Parent); if (indentationLength == 0) { return; } if (ShouldFixIndentation(first.GetLeadingTrivia(), indentationLength)) { ReportDiagnostic(); } } else { TextLineCollection lines = null; IndentationAnalysis indentationAnalysis = IndentationAnalysis.Create(openNodeOrToken.Parent); int indentationLength = indentationAnalysis.IncreasedIndentationLength; if (indentationLength == 0) { return; } for (int i = nodes.Count - 1; i >= 0; i--) { context.CancellationToken.ThrowIfCancellationRequested(); SyntaxTriviaList trailing = (i == 0) ? openNodeOrToken.GetTrailingTrivia() : nodes.GetSeparator(i - 1).TrailingTrivia; if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing)) { if (ShouldFixIndentation(nodes[i].GetLeadingTrivia(), indentationLength)) { ReportDiagnostic(); break; } } else { if (nodes.Count > 1 && ShouldWrapAndIndent(context.Node, i)) { ReportDiagnostic(); break; } if (nodes.Count == 1 && first.IsKind(SyntaxKind.Argument)) { var argument = (ArgumentSyntax)(SyntaxNode)first; LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= first.SyntaxTree.GetText().Lines); if (lambdaBlock.Block != null) { SyntaxToken token = lambdaBlock.Token; SyntaxTriviaList leading = token.LeadingTrivia; if (leading.Any()) { SyntaxTrivia trivia = leading.Last(); if (trivia.IsWhitespaceTrivia() && trivia.SpanStart == lambdaBlock.LineStartIndex && trivia.Span.Length != indentationAnalysis.IndentationLength) { ReportDiagnostic(); break; } } else if (lambdaBlock.LineStartIndex == token.SpanStart) { ReportDiagnostic(); break; } return; } } if (lines == null) { lines = first.SyntaxTree.GetText().Lines; } int lineIndex = lines.IndexOf(span.Start); if (lineIndex < lines.Count - 1) { int lineStartIndex = lines[lineIndex + 1].Start; if (first.Span.Contains(lineStartIndex)) { SyntaxToken token = first.FindToken(lineStartIndex); if (!token.IsKind(SyntaxKind.None)) { SyntaxTriviaList leading = token.LeadingTrivia; if (leading.Any()) { if (leading.FullSpan.Contains(lineStartIndex)) { SyntaxTrivia trivia = leading.Last(); if (trivia.IsWhitespaceTrivia() && trivia.SpanStart == lineStartIndex && trivia.Span.Length != indentationLength) { ReportDiagnostic(); break; } } } else if (lineStartIndex == token.SpanStart) { ReportDiagnostic(); break; } } } } } } } void ReportDiagnostic() { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.FixFormattingOfList, Location.Create(first.SyntaxTree, nodes.Span), GetTitle()); }
private static List <BaseFieldDeclarationSyntax> DeclarationSplitter( Document document, VariableDeclarationSyntax declaration, Func <VariableDeclarationSyntax, BaseFieldDeclarationSyntax> declarationFactory, SyntaxTriviaList declarationTrailingTrivia) { SeparatedSyntaxList <VariableDeclaratorSyntax> variables = declaration.Variables; VariableDeclaratorSyntax first = variables.First(); BaseFieldDeclarationSyntax previous = null; var newFieldDeclarations = new List <BaseFieldDeclarationSyntax>(variables.Count); foreach (SyntaxNodeOrToken nodeOrToken in variables.GetWithSeparators()) { if (previous == null) { VariableDeclaratorSyntax variable = (VariableDeclaratorSyntax)nodeOrToken.AsNode(); variable = variable.WithIdentifier(variable.Identifier.WithoutLeadingWhitespace()); var variableDeclarator = SyntaxFactory.SingletonSeparatedList(variable); previous = declarationFactory(declaration.WithVariables(variableDeclarator)); if (variable != first) { var triviaList = previous.GetLeadingTrivia().WithoutDirectiveTrivia(); // Remove all leading blank lines var nonBlankLinetriviaIndex = TriviaHelper.IndexOfFirstNonBlankLineTrivia(triviaList); if (nonBlankLinetriviaIndex > 0) { triviaList = triviaList.RemoveRange(0, nonBlankLinetriviaIndex); } // Add a blank line if the first line contains a comment. var nonWhitespaceTriviaIndex = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(triviaList, false); if (nonWhitespaceTriviaIndex >= 0) { switch (triviaList[nonWhitespaceTriviaIndex].Kind()) { case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.MultiLineCommentTrivia: triviaList = triviaList.Insert(0, SyntaxFactory.CarriageReturnLineFeed); break; } } previous = previous.WithLeadingTrivia(triviaList); } } else { SyntaxToken commaToken = nodeOrToken.AsToken(); SyntaxTriviaList trailingTrivia = commaToken.TrailingTrivia; if (trailingTrivia.Any()) { if (!trailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia)) { trailingTrivia = trailingTrivia.WithoutTrailingWhitespace().Add(FormattingHelper.GetNewLineTrivia(document)); } } else { trailingTrivia = SyntaxTriviaList.Create(FormattingHelper.GetNewLineTrivia(document)); } newFieldDeclarations.Add(previous.WithTrailingTrivia(trailingTrivia)); previous = null; } } newFieldDeclarations.Add(previous.WithTrailingTrivia(declarationTrailingTrivia)); return(newFieldDeclarations); }
private bool ShouldPreserveTrivia(SyntaxTriviaList trivia) { return(trivia.Any(t => !t.IsWhitespaceOrEndOfLine())); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out CompilationUnitSyntax compilationUnit)) { return; } Document document = context.Document; Diagnostic diagnostic = context.Diagnostics[0]; switch (diagnostic.Id) { case DiagnosticIdentifiers.NormalizeWhitespaceAtEndOfFile: { bool preferNewLineAtEndOfFile = document.GetConfigOptions(compilationUnit.SyntaxTree).PreferNewLineAtEndOfFile() ?? false; CodeAction codeAction = CodeAction.Create( (preferNewLineAtEndOfFile) ? CodeFixTitles.AddNewLine : CodeFixTitles.RemoveNewLine, ct => { SyntaxToken endOfFile = compilationUnit.EndOfFileToken; SyntaxTriviaList leading = endOfFile.LeadingTrivia; SyntaxToken oldToken; SyntaxToken newToken; if (!preferNewLineAtEndOfFile) { if (leading.Any()) { SyntaxTrivia last = leading.Last(); if (last.GetStructure() is DirectiveTriviaSyntax directive) { SyntaxTriviaList trailing = directive.GetTrailingTrivia(); DirectiveTriviaSyntax newDirective = directive.WithTrailingTrivia(trailing.RemoveAt(trailing.Count - 1)); return(document.ReplaceNodeAsync(directive, newDirective, ct)); } else { oldToken = endOfFile; int index = leading.Count - 1; for (int i = leading.Count - 2; i >= 0; i--) { if (leading[i].IsWhitespaceOrEndOfLineTrivia()) { index--; } } newToken = oldToken.WithLeadingTrivia(leading.RemoveRange(index, leading.Count - index)); } } else { oldToken = endOfFile.GetPreviousToken(); SyntaxTriviaList trailing = oldToken.TrailingTrivia; newToken = oldToken.WithTrailingTrivia(trailing.RemoveAt(trailing.Count - 1)); } } else if (leading.Any()) { oldToken = endOfFile; if (leading.Span.Start == 0 && leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) { newToken = oldToken.WithoutLeadingTrivia(); } else { newToken = oldToken.AppendEndOfLineToLeadingTrivia(); } } else { oldToken = endOfFile.GetPreviousToken(); newToken = oldToken.AppendEndOfLineToTrailingTrivia(); } return(document.ReplaceTokenAsync(oldToken, newToken, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } }
private static Task <Document> FixAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { IndentationAnalysis indentationAnalysis = AnalyzeIndentation(binaryExpression, cancellationToken); string indentation; if (indentationAnalysis.Indentation == binaryExpression.GetLeadingTrivia().LastOrDefault() && document.IsAnalyzerOptionEnabled(AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt)) { 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) { ExpressionSyntax left = binaryExpression.Left; SyntaxToken token = binaryExpression.OperatorToken; 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 (document.IsAnalyzerOptionEnabled(AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt)) { 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); } } } }
private static bool ShouldPreserve(SyntaxTriviaList trivia) { return(trivia.Any(t => t.IsRegularComment() || t.IsDirective)); }
public static async Task ComputeRefactoringAsync(RefactoringContext context, LocalDeclarationStatementSyntax localDeclaration) { VariableDeclarationSyntax declaration = localDeclaration.Declaration; TypeSyntax type = declaration?.Type; if (type?.IsVar != false) { return; } VariableDeclaratorSyntax declarator = declaration.Variables.FirstOrDefault(); if (declarator == null) { return; } if (context.Span.Start < type.SpanStart) { return; } SyntaxTriviaList triviaList = type.GetTrailingTrivia(); if (!triviaList.Any()) { return; } SyntaxTrivia trivia = triviaList .SkipWhile(f => f.IsWhitespaceTrivia()) .FirstOrDefault(); if (!trivia.IsEndOfLineTrivia()) { return; } if (context.Span.End > trivia.SpanStart) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken); string name = NameGenerator.Default.CreateUniqueLocalName( typeSymbol, semanticModel, declarator.SpanStart, cancellationToken: context.CancellationToken); if (name == null) { return; } context.RegisterRefactoring( $"Add identifier '{name}'", c => RefactorAsync(context.Document, type, name, c), RefactoringIdentifiers.AddIdentifierToVariableDeclaration); }
public TNode InsertModifier(TNode node, SyntaxToken modifier, IModifierComparer comparer = null) { if (node == null) { throw new ArgumentNullException(nameof(node)); } SyntaxTokenList modifiers = GetModifiers(node); int insertIndex = (comparer ?? ModifierComparer.Instance).GetInsertIndex(modifiers, modifier); var token = default(SyntaxToken); if (!modifiers.Any() || insertIndex == modifiers.Count) { SyntaxNodeOrToken nodeOrToken = FindNodeOrTokenAfterModifiers(node); if (nodeOrToken.IsToken) { token = nodeOrToken.AsToken(); } else if (nodeOrToken.IsNode) { token = nodeOrToken.AsNode().GetFirstToken(); } } else { token = modifiers[insertIndex]; } if (token != default(SyntaxToken)) { SyntaxTriviaList newLeadingTrivia = token.LeadingTrivia; if (newLeadingTrivia.Any()) { SyntaxTriviaList leadingTrivia = modifier.LeadingTrivia; if (!leadingTrivia.IsSingleElasticMarker()) { newLeadingTrivia = newLeadingTrivia.AddRange(leadingTrivia); } modifier = modifier.WithLeadingTrivia(newLeadingTrivia); SyntaxToken newToken = token.WithoutLeadingTrivia(); if (!modifiers.Any() || insertIndex == modifiers.Count) { node = node.ReplaceToken(token, newToken); } else { modifiers = modifiers.ReplaceAt(insertIndex, newToken); } } if (modifier.TrailingTrivia.IsSingleElasticMarker()) { modifier = modifier.WithTrailingTrivia(TriviaList(Space)); } } modifiers = modifiers.Insert(insertIndex, modifier); return(WithModifiers(node, modifiers)); }
public static string GetNewLineIfExist(SyntaxTriviaList triviaList) { return(triviaList.Any(f => f.IsKind(SyntaxKind.EndOfLineTrivia)) ? Environment.NewLine : ""); }
private SyntaxFactoryWriter WriteArgument(string parameter, SyntaxTriviaList triviaList, bool closeArgumentList = false) { _ = this.writer .WriteArgumentStart(parameter); switch (triviaList.Count) { case 0: this.Append("default").WriteArgumentEnd(closeArgumentList); return(this); case 1 when TryGetSingleLine(out var text): return(this.Append(text !) .WriteArgumentEnd(closeArgumentList)); default: this.AppendLine("SyntaxFactory.TriviaList(") .PushIndent(); for (var i = 0; i < triviaList.Count; i++) { _ = this.Write(triviaList[i]); if (i < triviaList.Count - 1) { this.AppendLine(","); } } this.writer.Append(")"); return(this.WriteArgumentEnd(closeArgumentList) .PopIndent()); } bool TryGetSingleLine(out string?result) { if (!triviaList.Any()) { result = "default"; return(true); } if (triviaList.TrySingle(out var trivia)) { switch (trivia.Kind()) { case SyntaxKind.None: result = "default"; return(true); case SyntaxKind.WhitespaceTrivia: result = trivia.Span.Length == 1 ? "SyntaxFactory.TriviaList(SyntaxFactory.Space)" : $"SyntaxFactory.TriviaList(SyntaxFactory.Whitespace(\"{trivia.ToString()}\"))"; return(true); case SyntaxKind.EndOfLineTrivia: result = "SyntaxFactory.TriviaList(SyntaxFactory.LineFeed)"; return(true); } } result = null; return(false); } }
public bool Any(SyntaxKind kind) { return(part1.Any(kind) || part2.Any(kind)); }
private static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) { SyntaxTree tree = context.Tree; if (!tree.TryGetText(out SourceText sourceText)) { return; } int maxLength = AnalyzerSettings.Current.MaxLineLength; if (context.Options.AnalyzerConfigOptionsProvider.GetOptions(tree).TryGetValue("roslynator.max_line_length", out string maxLengthText) && int.TryParse(maxLengthText, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, CultureInfo.CurrentCulture, out int maxLength2)) { maxLength = maxLength2; } if (maxLength <= 0) { return; } SyntaxNode root = tree.GetRoot(context.CancellationToken); int i = 0; SyntaxTrivia trivia = root.FindTrivia(0); if (trivia.SpanStart == 0 && trivia.IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia)) { SyntaxTriviaList leadingTrivia = trivia.Token.LeadingTrivia; int count = leadingTrivia.Count; if (count > 1) { int j = 0; while (j < leadingTrivia.Count - 1 && leadingTrivia[j].IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia) && leadingTrivia[j + 1].IsKind(SyntaxKind.EndOfLineTrivia)) { i++; j += 2; } } } TextLineCollection lines = sourceText.Lines; for (; i < lines.Count; i++) { TextLine line = lines[i]; if (line.Span.Length <= maxLength) { continue; } int end = line.End; SyntaxToken token = root.FindToken(end); if (token.IsKind(SyntaxKind.StringLiteralToken)) { TextSpan span = token.Span; if (span.End == end) { if (span.Length >= maxLength) { continue; } } else if (span.Contains(end) && end - span.Start >= maxLength) { continue; } } SyntaxTriviaList list = default; if (token.LeadingTrivia.Span.Contains(end)) { list = token.LeadingTrivia; } else if (token.TrailingTrivia.Span.Contains(end)) { list = token.TrailingTrivia; } if (list.Any()) { int index = -1; for (int j = 0; j < list.Count; j++) { if (list[j].Span.Contains(end)) { trivia = list[j]; index = j; } } if (index >= 0) { SyntaxKind kind = trivia.Kind(); if (kind == SyntaxKind.MultiLineCommentTrivia || kind == SyntaxKind.SingleLineDocumentationCommentTrivia || kind == SyntaxKind.MultiLineDocumentationCommentTrivia) { continue; } if (kind == SyntaxKind.EndOfLineTrivia && index > 0 && list[index - 1].IsKind(SyntaxKind.SingleLineCommentTrivia)) { continue; } } } ImmutableDictionary <string, string> properties = _properties; if (properties == null || int.Parse(properties[PropertyKey]) != maxLength) { properties = ImmutableDictionary.CreateRange( new[] { new KeyValuePair <string, string>(PropertyKey, maxLength.ToString()) }); _properties = properties; } DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.LineIsTooLong, Location.Create(tree, line.Span), properties, line.Span.Length); } }
private TNode InsertModifier(TNode node, SyntaxTokenList modifiers, SyntaxToken modifier, int index) { SyntaxToken token; if (!modifiers.Any() || index == modifiers.Count) { if (modifiers.Any()) { token = modifiers.Last().GetNextToken(); } else { AttributeListSyntax attributeList = GetAttributeLists(node).LastOrDefault(); if (attributeList != null) { token = attributeList.GetLastToken().GetNextToken(); } else { token = node.GetFirstToken(); } } } else { token = modifiers[index]; } if (token != default(SyntaxToken)) { SyntaxTriviaList newLeadingTrivia = token.LeadingTrivia; if (newLeadingTrivia.Any()) { SyntaxTriviaList leadingTrivia = modifier.LeadingTrivia; if (!leadingTrivia.IsSingleElasticMarker()) { newLeadingTrivia = newLeadingTrivia.AddRange(leadingTrivia); } modifier = modifier.WithLeadingTrivia(newLeadingTrivia); SyntaxToken newToken = token.WithoutLeadingTrivia(); if (!modifiers.Any() || index == modifiers.Count) { node = node.ReplaceToken(token, newToken); } else { modifiers = modifiers.ReplaceAt(index, newToken); } } if (modifier.TrailingTrivia.IsSingleElasticMarker()) { modifier = modifier.WithTrailingTrivia(TriviaList(Space)); } } modifiers = modifiers.Insert(index, modifier); return(WithModifiers(node, modifiers)); }
public static void AnalyzeInitializer(SyntaxNodeAnalysisContext context) { var initializer = (InitializerExpressionSyntax)context.Node; SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions; ExpressionSyntax first = expressions.FirstOrDefault(); if (first == null) { return; } if (IsExpectedTrailingTrivia(initializer.OpenBraceToken.TrailingTrivia)) { SyntaxTriviaList leading = first.GetLeadingTrivia(); if (leading.Any()) { TextSpan?span = GetEmptyLineSpan(leading, isEnd: false); if (span != null) { ReportDiagnostic(context, span.Value); } } } if (IsExpectedTrailingTrivia(expressions.GetTrailingTrivia())) { SyntaxTriviaList leading = initializer.CloseBraceToken.LeadingTrivia; if (leading.Any()) { TextSpan?span = GetEmptyLineSpan(leading, isEnd: true); if (span != null) { ReportDiagnostic(context, span.Value); } } } bool IsExpectedTrailingTrivia(SyntaxTriviaList triviaList) { foreach (SyntaxTrivia trivia in triviaList) { switch (trivia.Kind()) { case SyntaxKind.WhitespaceTrivia: break; case SyntaxKind.EndOfLineTrivia: return(true); default: return(false); } } return(false); } }
private static void UpdateReplaceMap(Dictionary <SyntaxToken, SyntaxToken> replaceMap, SyntaxToken token, Diagnostic diagnostic) { string location; if (!diagnostic.Properties.TryGetValue(TokenSpacingProperties.LocationKey, out location)) { return; } string action; if (!diagnostic.Properties.TryGetValue(TokenSpacingProperties.ActionKey, out action)) { return; } string layout; if (!diagnostic.Properties.TryGetValue(TokenSpacingProperties.LayoutKey, out layout)) { layout = TokenSpacingProperties.LayoutPack; } SyntaxTriviaList triviaList; switch (location) { case TokenSpacingProperties.LocationPreceding: var prevToken = token.GetPreviousToken(); switch (action) { case TokenSpacingProperties.ActionInsert: if (!replaceMap.ContainsKey(prevToken)) { replaceMap[token] = token.WithLeadingTrivia(token.LeadingTrivia.Add(SyntaxFactory.Space)); } break; case TokenSpacingProperties.ActionRemove: bool tokenIsFirstInLine = token.IsFirstInLine(); bool preserveLayout = layout == TokenSpacingProperties.LayoutPreserve; triviaList = prevToken.TrailingTrivia.AddRange(token.LeadingTrivia); if (triviaList.Any(t => t.IsDirective)) { break; } replaceMap[prevToken] = prevToken.WithTrailingTrivia(); if ((!preserveLayout || !tokenIsFirstInLine) && triviaList.All(i => i.IsKind(SyntaxKind.WhitespaceTrivia) || i.IsKind(SyntaxKind.EndOfLineTrivia))) { replaceMap[token] = token.WithLeadingTrivia(); } else if (tokenIsFirstInLine && token.IsLastInLine()) { /* This block covers the case where `token` is the only non-trivia token on its line. However, * the line may still contain non-whitespace trivia which we want the removal process to * preserve. This code fix only removes the whitespace surrounding `token` if it is the only * non-whitespace token on the line. */ int lastNewLineLeading = token.LeadingTrivia.LastIndexOf(SyntaxKind.EndOfLineTrivia); int firstNewLineFollowing = token.TrailingTrivia.IndexOf(SyntaxKind.EndOfLineTrivia); bool onlyWhitespace = true; for (int i = lastNewLineLeading + 1; i < token.LeadingTrivia.Count; i++) { onlyWhitespace &= token.LeadingTrivia[i].IsKind(SyntaxKind.WhitespaceTrivia); } firstNewLineFollowing = firstNewLineFollowing == -1 ? token.TrailingTrivia.Count : firstNewLineFollowing; for (int i = 0; i < firstNewLineFollowing; i++) { onlyWhitespace &= token.TrailingTrivia[i].IsKind(SyntaxKind.WhitespaceTrivia); } if (onlyWhitespace) { // Move the token, and remove the other tokens from its line. Keep all other surrounding // trivia. Keep the last newline that precedes token, but not the first that follows it. SyntaxTriviaList trailingTrivia = prevToken.TrailingTrivia; if (lastNewLineLeading >= 0) { trailingTrivia = trailingTrivia.AddRange(token.LeadingTrivia.Take(lastNewLineLeading + 1)); } // firstNewLineFollowing was adjusted above to account for the missing case. trailingTrivia = trailingTrivia.AddRange(token.TrailingTrivia.Take(firstNewLineFollowing)); replaceMap[token] = token.WithLeadingTrivia().WithTrailingTrivia(trailingTrivia); } else { // Just move the token and keep all surrounding trivia. SyntaxTriviaList trailingTrivia = triviaList.AddRange(token.TrailingTrivia); replaceMap[token] = token.WithLeadingTrivia().WithTrailingTrivia(trailingTrivia); } } else { SyntaxTriviaList trailingTrivia = triviaList.AddRange(token.TrailingTrivia.WithoutLeadingWhitespace(endOfLineIsWhitespace: false)); replaceMap[token] = token.WithLeadingTrivia().WithTrailingTrivia(trailingTrivia); } break; case TokenSpacingProperties.ActionRemoveImmediate: SyntaxTriviaList tokenLeadingTrivia = token.LeadingTrivia; while (tokenLeadingTrivia.Any() && tokenLeadingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia)) { tokenLeadingTrivia = tokenLeadingTrivia.RemoveAt(tokenLeadingTrivia.Count - 1); } replaceMap[token] = token.WithLeadingTrivia(tokenLeadingTrivia); if (!tokenLeadingTrivia.Any()) { SyntaxTriviaList previousTrailingTrivia = prevToken.TrailingTrivia; while (previousTrailingTrivia.Any() && previousTrailingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia)) { previousTrailingTrivia = previousTrailingTrivia.RemoveAt(previousTrailingTrivia.Count - 1); } replaceMap[prevToken] = prevToken.WithTrailingTrivia(previousTrailingTrivia); } break; } break; case TokenSpacingProperties.LocationFollowing: var nextToken = token.GetNextToken(); switch (action) { case TokenSpacingProperties.ActionInsert: if (!replaceMap.ContainsKey(nextToken)) { replaceMap[token] = token.WithTrailingTrivia(token.TrailingTrivia.Insert(0, SyntaxFactory.Space)); } break; case TokenSpacingProperties.ActionRemove: triviaList = token.TrailingTrivia.AddRange(nextToken.LeadingTrivia); replaceMap[token] = token.WithTrailingTrivia(); replaceMap[nextToken] = nextToken.WithLeadingTrivia(triviaList.WithoutLeadingWhitespace(true)); break; } break; } }
public static SyntaxTrivia LastOrDefault(this SyntaxTriviaList triviaList) => triviaList.Any() ? triviaList.Last() : default;
PropertyDeclarationSyntax ConvertProperty(PropertyDeclarationSyntax propertyDeclaration, FieldDeclarationSyntax relatedField) { var leadingList = new SyntaxTriviaList(); if (relatedField.Declaration.Variables.Count == 1) { leadingList = leadingList.AddRange(relatedField.GetLeadingTrivia()); } var propertyDeclaration_GetLeadingTrivia = propertyDeclaration.GetLeadingTrivia(); if (leadingList.Any() && propertyDeclaration_GetLeadingTrivia.First().IsKind(SyntaxKind.EndOfLineTrivia) == false) { var endOfLine = relatedField.GetLeadingTrivia().FirstOrDefault(x => x.IsKind(SyntaxKind.EndOfLineTrivia)); if (endOfLine != null) { leadingList = leadingList.Add(endOfLine); } } leadingList = leadingList.AddRange(propertyDeclaration.GetLeadingTrivia()); var getNode = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(x => x.Keyword.IsKind(SyntaxKind.GetKeyword)); var setNode = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(x => x.Keyword.IsKind(SyntaxKind.SetKeyword)); propertyDeclaration = propertyDeclaration .WithAccessorList ( propertyDeclaration.AccessorList.WithAccessors( new SyntaxList <AccessorDeclarationSyntax>() .Add( getNode .WithBody(null) .WithTrailingTrivia() .WithSemicolonToken( SyntaxFactory.ParseToken(";") .WithTrailingTrivia(SyntaxFactory.Space) ) .WithLeadingTrivia(SyntaxFactory.Space) ) .Add( setNode .WithBody(null) .WithTrailingTrivia() .WithSemicolonToken( SyntaxFactory.ParseToken(";") .WithTrailingTrivia(SyntaxFactory.Space) ) .WithLeadingTrivia(SyntaxFactory.Space) ) ) .WithOpenBraceToken(propertyDeclaration.AccessorList.OpenBraceToken.WithLeadingTrivia().WithTrailingTrivia()) .WithCloseBraceToken(propertyDeclaration.AccessorList.CloseBraceToken.WithLeadingTrivia()) ) .WithIdentifier(propertyDeclaration.Identifier.WithTrailingTrivia(SyntaxFactory.Space)) .WithLeadingTrivia(leadingList); return(propertyDeclaration); }
private static void HandleSemicolonToken(SyntaxTreeAnalysisContext context, SyntaxToken token) { if (token.IsMissing) { return; } // check for a following space bool missingFollowingSpace = true; if (token.HasTrailingTrivia) { if (token.TrailingTrivia.First().IsKind(SyntaxKind.WhitespaceTrivia)) { missingFollowingSpace = false; } else if (token.TrailingTrivia.First().IsKind(SyntaxKind.EndOfLineTrivia)) { missingFollowingSpace = false; } } else { SyntaxToken nextToken = token.GetNextToken(); switch (nextToken.Kind()) { case SyntaxKind.CloseParenToken: // Special handling for the following case: // for (; ;) missingFollowingSpace = false; break; case SyntaxKind.SemicolonToken: // Special handling for the following case: // Statement();; if (nextToken.Parent.IsKind(SyntaxKind.EmptyStatement)) { missingFollowingSpace = false; } break; case SyntaxKind.None: // The semi colon is the last character in the file. return; default: break; } } bool hasPrecedingSpace = false; bool ignorePrecedingSpace = false; if (!token.IsFirstInLine()) { // only the first token on the line has leading trivia, and those are ignored SyntaxToken precedingToken = token.GetPreviousToken(); SyntaxTriviaList trailingTrivia = precedingToken.TrailingTrivia; if (trailingTrivia.Any() && trailingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia)) { hasPrecedingSpace = true; } if (precedingToken.IsKind(SyntaxKind.SemicolonToken)) { // Special handling for the following case: // for (; ;) ignorePrecedingSpace = true; } } if (missingFollowingSpace) { // semicolon should{} be {followed} by a space context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.InsertFollowing, string.Empty, "followed")); } if (hasPrecedingSpace && !ignorePrecedingSpace) { // semicolon should{ not} be {preceded} by a space context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemoveImmediatePreceding, " not", "preceded")); } }
private static bool ShouldPreserveTrivia(SyntaxTriviaList trivia) => trivia.Any(t => !t.IsWhitespaceOrEndOfLine());
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); } }
private static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) { SyntaxTree tree = context.Tree; if (!tree.TryGetText(out SourceText sourceText)) { return; } int maxLength = CSharp.AnalyzerOptions.MaxLineLength.GetInt32Value(context.Tree, context.Options, AnalyzerSettings.Current.MaxLineLength); if (maxLength <= 0) { return; } SyntaxNode root = tree.GetRoot(context.CancellationToken); int i = 0; SyntaxTrivia trivia = root.FindTrivia(0); if (trivia.SpanStart == 0 && trivia.IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia)) { SyntaxTriviaList leadingTrivia = trivia.Token.LeadingTrivia; int count = leadingTrivia.Count; if (count > 1) { int j = 0; while (j < leadingTrivia.Count - 1 && leadingTrivia[j].IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia) && leadingTrivia[j + 1].IsKind(SyntaxKind.EndOfLineTrivia)) { i++; j += 2; } } } TextLineCollection lines = sourceText.Lines; for (; i < lines.Count; i++) { TextLine line = lines[i]; if (line.Span.Length <= maxLength) { continue; } int end = line.End; SyntaxToken token = root.FindToken(end); if (token.IsKind(SyntaxKind.StringLiteralToken)) { TextSpan span = token.Span; if (span.End == end) { if (span.Length >= maxLength) { continue; } } else if (span.Contains(end) && end - span.Start >= maxLength) { continue; } } SyntaxTriviaList list = default; if (token.LeadingTrivia.Span.Contains(end)) { list = token.LeadingTrivia; } else if (token.TrailingTrivia.Span.Contains(end)) { list = token.TrailingTrivia; } if (list.Any()) { int index = -1; for (int j = 0; j < list.Count; j++) { if (list[j].Span.Contains(end)) { trivia = list[j]; index = j; } } if (index >= 0) { SyntaxKind kind = trivia.Kind(); if (kind == SyntaxKind.MultiLineCommentTrivia || kind == SyntaxKind.SingleLineDocumentationCommentTrivia || kind == SyntaxKind.MultiLineDocumentationCommentTrivia) { continue; } if (kind == SyntaxKind.EndOfLineTrivia && index > 0 && list[index - 1].IsKind(SyntaxKind.SingleLineCommentTrivia)) { continue; } } } DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.LineIsTooLong, Location.Create(tree, line.Span), line.Span.Length); } }
private static async Task <StatementListInfo> RefactorAsync <TStatement>( Document document, TStatement statement, StatementListInfo statementsInfo, Func <TStatement, TStatement> createNewStatement, int count, bool removeReturnStatement, CancellationToken cancellationToken) where TStatement : StatementSyntax { int statementIndex = statementsInfo.IndexOf(statement); var returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1]; ExpressionSyntax returnExpression = returnStatement.Expression; ExpressionSyntax newReturnExpression = null; SyntaxTriviaList newTrailingTrivia = default; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ISymbol symbol = semanticModel.GetSymbol(returnExpression, cancellationToken); if (symbol.Kind == SymbolKind.Local && statementIndex > 0 && statementsInfo[statementIndex - 1] is LocalDeclarationStatementSyntax localDeclarationStatement && !localDeclarationStatement.ContainsDiagnostics && !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() && !statement.GetLeadingTrivia().Any(f => f.IsDirective)) { SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables; VariableDeclaratorSyntax declarator = declarators.FirstOrDefault(f => semanticModel.GetDeclaredSymbol(f, cancellationToken)?.Equals(symbol) == true); if (declarator != null) { ExpressionSyntax value = declarator.Initializer?.Value; if (removeReturnStatement || value != null) { IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false); if (referencedSymbols.First().Locations.Count() == count + 1) { newReturnExpression = value; if (declarators.Count == 1) { if (!removeReturnStatement && returnStatement.GetTrailingTrivia().IsEmptyOrWhitespace()) { SyntaxTriviaList trailingTrivia = localDeclarationStatement.GetTrailingTrivia(); if (trailingTrivia .SkipWhile(f => f.IsWhitespaceTrivia()) .FirstOrDefault() .IsKind(SyntaxKind.SingleLineCommentTrivia)) { newTrailingTrivia = trailingTrivia; } } SyntaxRemoveOptions removeOptions = SyntaxRefactorings.GetRemoveOptions(localDeclarationStatement); if (newTrailingTrivia.Any()) { removeOptions &= ~SyntaxRemoveOptions.KeepTrailingTrivia; } statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, removeOptions); statementIndex--; } else { statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, SyntaxRefactorings.GetRemoveOptions(declarator))); } returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1]; } } } } if (removeReturnStatement) { statementsInfo = statementsInfo.RemoveNode(returnStatement, SyntaxRefactorings.GetRemoveOptions(returnStatement)); } else if (newReturnExpression != null) { ReturnStatementSyntax newReturnStatement = returnStatement.WithExpression(newReturnExpression.WithTriviaFrom(returnExpression)); if (newTrailingTrivia.Any()) { newReturnStatement = newReturnStatement.WithTrailingTrivia(newTrailingTrivia); } statementsInfo = statementsInfo.ReplaceNode(returnStatement, newReturnStatement); } StatementSyntax oldNode = statementsInfo[statementIndex]; TStatement newNode = createNewStatement((TStatement)oldNode).WithFormatterAnnotation(); return(statementsInfo.ReplaceNode(oldNode, newNode)); }
private static bool SpansPreprocessorDirective(SyntaxTriviaList list) { return(list.Any(t => t.GetStructure() is DirectiveTriviaSyntax)); }
private static bool SpansPreprocessorDirective(SyntaxTriviaList list) { return list.Any(t => t.GetStructure() is DirectiveTriviaSyntax); }
public static Task <Document> RemoveParenthesesAsync( Document document, ParenthesizedExpressionSyntax parenthesizedExpression, CancellationToken cancellationToken = default) { ExpressionSyntax expression = parenthesizedExpression.Expression; SyntaxTriviaList leading = parenthesizedExpression.GetLeadingTrivia() .Concat(parenthesizedExpression.OpenParenToken.TrailingTrivia) .Concat(expression.GetLeadingTrivia()) .ToSyntaxTriviaList(); SyntaxTriviaList trailing = expression.GetTrailingTrivia() .Concat(parenthesizedExpression.CloseParenToken.LeadingTrivia) .Concat(parenthesizedExpression.GetTrailingTrivia()) .ToSyntaxTriviaList(); ExpressionSyntax newExpression = expression .WithLeadingTrivia(leading) .WithTrailingTrivia(trailing) .WithFormatterAnnotation(); if (!leading.Any()) { SyntaxNode parent = parenthesizedExpression.Parent; switch (parent.Kind()) { case SyntaxKind.ReturnStatement: { var returnStatement = (ReturnStatementSyntax)parent; SyntaxToken returnKeyword = returnStatement.ReturnKeyword; if (!returnKeyword.TrailingTrivia.Any()) { ReturnStatementSyntax newNode = returnStatement.Update(returnKeyword.WithTrailingTrivia(Space), newExpression, returnStatement.SemicolonToken); return(document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken)); } break; } case SyntaxKind.YieldReturnStatement: { var yieldReturn = (YieldStatementSyntax)parent; SyntaxToken returnKeyword = yieldReturn.ReturnOrBreakKeyword; if (!returnKeyword.TrailingTrivia.Any()) { YieldStatementSyntax newNode = yieldReturn.Update(yieldReturn.YieldKeyword, returnKeyword.WithTrailingTrivia(Space), newExpression, yieldReturn.SemicolonToken); return(document.ReplaceNodeAsync(yieldReturn, newNode, cancellationToken)); } break; } case SyntaxKind.AwaitExpression: { var awaitExpression = (AwaitExpressionSyntax)parent; SyntaxToken awaitKeyword = awaitExpression.AwaitKeyword; if (!awaitKeyword.TrailingTrivia.Any()) { AwaitExpressionSyntax newNode = awaitExpression.Update(awaitKeyword.WithTrailingTrivia(Space), newExpression); return(document.ReplaceNodeAsync(awaitExpression, newNode, cancellationToken)); } break; } } } return(document.ReplaceNodeAsync(parenthesizedExpression, newExpression, cancellationToken)); }
private static Task <Document> FixAsync <TNode>( Document document, SyntaxNode containingNode, SyntaxNodeOrToken openNodeOrToken, SeparatedSyntaxList <TNode> nodes, CancellationToken cancellationToken) where TNode : SyntaxNode { IndentationAnalysis indentationAnalysis = AnalyzeIndentation(containingNode, cancellationToken); string increasedIndentation = indentationAnalysis.GetIncreasedIndentation(); if (nodes.IsSingleLine(includeExteriorTrivia: false, cancellationToken: cancellationToken)) { TNode node = nodes[0]; SyntaxTriviaList leading = node.GetLeadingTrivia(); TextSpan span = (leading.Any() && leading.Last().IsWhitespaceTrivia()) ? leading.Last().Span : new TextSpan(node.SpanStart, 0); return(document.WithTextChangeAsync( new TextChange(span, increasedIndentation), cancellationToken)); } var textChanges = new List <TextChange>(); TextLineCollection lines = null; string endOfLine = DetermineEndOfLine(containingNode).ToString(); for (int i = 0; i < nodes.Count; i++) { SyntaxToken token; if (i == 0) { token = (openNodeOrToken.IsNode) ? openNodeOrToken.AsNode().GetLastToken() : openNodeOrToken.AsToken(); } else { token = nodes.GetSeparator(i - 1); } SyntaxTriviaList trailing = token.TrailingTrivia; TNode node = nodes[i]; var indentationAdded = false; if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing)) { SyntaxTrivia last = node.GetLeadingTrivia().LastOrDefault(); if (last.IsWhitespaceTrivia()) { if (last.Span.Length == increasedIndentation.Length) { continue; } textChanges.Add(last.Span, increasedIndentation); } else { textChanges.Add(new TextSpan(node.SpanStart, 0), increasedIndentation); } indentationAdded = true; } else { if (nodes.Count == 1 && node is ArgumentSyntax argument) { LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= argument.SyntaxTree.GetText().Lines); if (lambdaBlock.Block != null) { increasedIndentation = indentationAnalysis.Indentation.ToString(); } } if (nodes.Count > 1 && (i > 0 || !containingNode.IsKind(SyntaxKind.AttributeList))) { textChanges.Add( (trailing.Any() && trailing.Last().IsWhitespaceTrivia()) ? trailing.Last().Span : new TextSpan(token.FullSpan.End, 0), endOfLine); textChanges.Add(new TextSpan(node.FullSpan.Start, 0), increasedIndentation); indentationAdded = true; } } ImmutableArray <IndentationInfo> indentations = FindIndentations(node, node.Span).ToImmutableArray(); if (!indentations.Any()) { continue; } LambdaBlock lambdaBlock2 = GetLambdaBlock(node, lines ??= node.SyntaxTree.GetText().Lines); bool isLambdaBlockWithOpenBraceAtEndOfLine = lambdaBlock2.Token == indentations.Last().Token; int baseIndentationLength = (isLambdaBlockWithOpenBraceAtEndOfLine) ? indentations.Last().Span.Length : indentations[0].Span.Length; for (int j = indentations.Length - 1; j >= 0; j--) { IndentationInfo indentationInfo = indentations[j]; if (indentationAdded && node is ArgumentSyntax argument && (argument.Expression as AnonymousFunctionExpressionSyntax)?.Block != null) { indentationAdded = false; } string replacement = increasedIndentation; if (indentationAdded) { replacement += indentationAnalysis.GetSingleIndentation(); } if ((j > 0 || isLambdaBlockWithOpenBraceAtEndOfLine) && indentationInfo.Span.Length > baseIndentationLength) { replacement += indentationInfo.ToString().Substring(baseIndentationLength); } if (indentationInfo.Span.Length != replacement.Length) { textChanges.Add(indentationInfo.Span, replacement); } } } FormattingVerifier.VerifyChangedSpansAreWhitespace(containingNode, textChanges); return(document.WithTextChangesAsync(textChanges, cancellationToken)); }
private static bool ContainsComment(SyntaxTriviaList trivias) { return trivias.Any(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)); }
private static void AnalyzeCompilationUnit(SyntaxNodeAnalysisContext context) { var compilationUnit = (CompilationUnitSyntax)context.Node; SyntaxToken endOfFile = compilationUnit.EndOfFileToken; SyntaxTriviaList.Reversed.Enumerator en = endOfFile.LeadingTrivia.Reverse().GetEnumerator(); bool?preferNewLineAtEndOfFile = context.PreferNewLineAtEndOfFile(); if (preferNewLineAtEndOfFile == null) { return; } if (preferNewLineAtEndOfFile == false) { if (en.MoveNext() && (!en.Current.IsWhitespaceTrivia() || en.MoveNext())) { if (en.Current.IsEndOfLineTrivia()) { ReportDiagnostic(context, endOfFile); } else if (SyntaxFacts.IsPreprocessorDirective(en.Current.Kind()) && en.Current.GetStructure() is DirectiveTriviaSyntax directiveTrivia && directiveTrivia.GetTrailingTrivia().LastOrDefault().IsEndOfLineTrivia()) { ReportDiagnostic(context, endOfFile); } } else { SyntaxTriviaList trailing = endOfFile.GetPreviousToken().TrailingTrivia; if (trailing.Any()) { Debug.Assert(endOfFile.FullSpan.Start == trailing.Span.End); if (endOfFile.FullSpan.Start == trailing.Span.End && trailing.LastOrDefault().IsEndOfLineTrivia()) { ReportDiagnostic(context, endOfFile); } } } } else if (en.MoveNext()) { if (CSharpFacts.IsCommentTrivia(en.Current.Kind()) || SyntaxFacts.IsPreprocessorDirective(en.Current.Kind())) { ReportDiagnostic(context, endOfFile); } else if (en.Current.IsWhitespaceOrEndOfLineTrivia() && endOfFile.LeadingTrivia.Span.Start == 0) { while (en.MoveNext()) { if (!en.Current.IsWhitespaceOrEndOfLineTrivia()) { return; } } ReportDiagnostic(context, endOfFile); } } else if (endOfFile.SpanStart > 0) { SyntaxTriviaList trailing = endOfFile.GetPreviousToken().TrailingTrivia; if (!trailing.Any()) { ReportDiagnostic(context, endOfFile); } else { Debug.Assert(endOfFile.FullSpan.Start == trailing.Span.End); if (endOfFile.FullSpan.Start == trailing.Span.End && !trailing.Last().IsEndOfLineTrivia()) { ReportDiagnostic(context, endOfFile); } } }