private Document CreateCodeFix(Document document, IndentationSettings indentationSettings, Diagnostic diagnostic, SyntaxNode syntaxRoot) { SyntaxNode newSyntaxRoot = syntaxRoot; var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan); switch (node.Kind()) { case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.EnumDeclaration: newSyntaxRoot = this.RegisterBaseTypeDeclarationCodeFix(syntaxRoot, (BaseTypeDeclarationSyntax)node, indentationSettings); break; case SyntaxKind.AccessorList: newSyntaxRoot = this.RegisterPropertyLikeDeclarationCodeFix(syntaxRoot, (BasePropertyDeclarationSyntax)node.Parent, indentationSettings); break; case SyntaxKind.Block: newSyntaxRoot = this.RegisterMethodLikeDeclarationCodeFix(syntaxRoot, (BaseMethodDeclarationSyntax)node.Parent, indentationSettings); break; case SyntaxKind.NamespaceDeclaration: newSyntaxRoot = this.RegisterNamespaceDeclarationCodeFix(syntaxRoot, (NamespaceDeclarationSyntax)node, indentationSettings); break; } return(document.WithSyntaxRoot(newSyntaxRoot)); }
private Document CreateCodeFix(Document document, IndentationSettings indentationSettings, Diagnostic diagnostic, SyntaxNode syntaxRoot) { SyntaxNode newSyntaxRoot = syntaxRoot; var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan); switch (node.Kind()) { case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.EnumDeclaration: newSyntaxRoot = this.RegisterBaseTypeDeclarationCodeFix(syntaxRoot, (BaseTypeDeclarationSyntax)node, indentationSettings); break; case SyntaxKind.AccessorList: newSyntaxRoot = this.RegisterPropertyLikeDeclarationCodeFix(syntaxRoot, (BasePropertyDeclarationSyntax)node.Parent, indentationSettings); break; case SyntaxKind.Block: newSyntaxRoot = this.RegisterMethodLikeDeclarationCodeFix(syntaxRoot, (BaseMethodDeclarationSyntax)node.Parent, indentationSettings); break; case SyntaxKind.NamespaceDeclaration: newSyntaxRoot = this.RegisterNamespaceDeclarationCodeFix(syntaxRoot, (NamespaceDeclarationSyntax)node, indentationSettings); break; } return document.WithSyntaxRoot(newSyntaxRoot); }
private static SyntaxNode ReformatBlockAndParent(Document document, IndentationSettings indentationSettings, SyntaxNode syntaxRoot, BlockSyntax block) { var parentLastToken = block.OpenBraceToken.GetPreviousToken(); var parentEndLine = parentLastToken.GetEndLine(); var blockStartLine = block.OpenBraceToken.GetLine(); var newParentLastToken = parentLastToken; if (parentEndLine == blockStartLine) { var newTrailingTrivia = parentLastToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); newParentLastToken = newParentLastToken.WithTrailingTrivia(newTrailingTrivia); } var parentNextToken = block.CloseBraceToken.GetNextToken(); var nextTokenLine = parentNextToken.GetLine(); var blockCloseLine = block.CloseBraceToken.GetEndLine(); var newParentNextToken = parentNextToken; if (nextTokenLine == blockCloseLine) { newParentNextToken = newParentNextToken.WithLeadingTrivia(parentLastToken.LeadingTrivia); } var newBlock = ReformatBlock(document, indentationSettings, block); var rewriter = new BlockRewriter(parentLastToken, newParentLastToken, block, newBlock, parentNextToken, newParentNextToken); var newSyntaxRoot = rewriter.Visit(syntaxRoot); return newSyntaxRoot.WithoutFormatting(); }
private static void ReformatStatement(IndentationSettings indentationSettings, StatementSyntax statement, Dictionary <SyntaxToken, SyntaxToken> tokenReplaceMap) { var indentationLevel = DetermineIndentationLevel(indentationSettings, tokenReplaceMap, statement); // use one additional step of indentation for lambdas / anonymous methods switch (statement.Parent.Kind()) { case SyntaxKind.AnonymousMethodExpression: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.ParenthesizedLambdaExpression: indentationLevel++; break; } var statementIndentationTrivia = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationLevel + 1); var newFirstTokenLeadingTrivia = statement.GetFirstToken().LeadingTrivia .WithoutTrailingWhitespace() .Add(statementIndentationTrivia); var newLastTokenTrailingTrivia = statement.GetLastToken().TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); AddToReplaceMap(tokenReplaceMap, statement.GetFirstToken(), statement.GetFirstToken().WithLeadingTrivia(newFirstTokenLeadingTrivia)); AddToReplaceMap(tokenReplaceMap, statement.GetLastToken(), statement.GetLastToken().WithTrailingTrivia(newLastTokenTrailingTrivia)); }
private static int DetermineIndentationSteps(IndentationSettings indentationSettings, SyntaxToken token) { // For a closing brace use the indentation of the corresponding opening brace if (token.IsKind(SyntaxKind.CloseBraceToken)) { var depth = 1; while (depth > 0) { token = token.GetPreviousToken(); switch (token.Kind()) { case SyntaxKind.CloseBraceToken: depth++; break; case SyntaxKind.OpenBraceToken: depth--; break; } } } var startLine = GetTokenStartLinePosition(token).Line; while (!ContainsStartOfLine(token, startLine)) { token = token.GetPreviousToken(); } return(IndentationHelper.GetIndentationSteps(indentationSettings, token)); }
private static int GetIndentationStepsUnchecked(IndentationSettings indentationSettings, SyntaxTriviaList leadingTrivia) { var builder = StringBuilderPool.Allocate(); foreach (SyntaxTrivia trivia in leadingTrivia.Reverse()) { if (!trivia.IsKind(SyntaxKind.WhitespaceTrivia)) { break; } builder.Insert(0, trivia.ToFullString()); } var tabSize = indentationSettings.TabSize; var indentationCount = 0; for (var i = 0; i < builder.Length; i++) { indentationCount += builder[i] == '\t' ? tabSize - (indentationCount % tabSize) : 1; } StringBuilderPool.ReturnAndFree(builder); return((indentationCount + (indentationSettings.IndentationSize / 2)) / indentationSettings.IndentationSize); }
private static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxTree syntaxTree, SyntaxTriviaList leadingTrivia) { var triviaSpan = syntaxTree.GetLineSpan(leadingTrivia.FullSpan); // There is no indentation when the leading trivia doesn't begin at the start of the line. if ((triviaSpan.StartLinePosition == triviaSpan.EndLinePosition) && (triviaSpan.StartLinePosition.Character > 0)) { return(0); } var builder = StringBuilderPool.Allocate(); foreach (SyntaxTrivia trivia in leadingTrivia.Reverse()) { if (!trivia.IsKind(SyntaxKind.WhitespaceTrivia)) { break; } builder.Insert(0, trivia.ToFullString()); } var tabSize = indentationSettings.TabSize; var indentationCount = 0; for (var i = 0; i < builder.Length; i++) { indentationCount += builder[i] == '\t' ? tabSize - (indentationCount % tabSize) : 1; } StringBuilderPool.ReturnAndFree(builder); return((indentationCount + (indentationSettings.IndentationSize / 2)) / indentationSettings.IndentationSize); }
/// <summary> /// Gets the number of steps that the given token is indented. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="token">The token to inspect.</param> /// <returns>The number of steps that the token is indented.</returns> public static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxToken token) { // If the token does not belong to a syntax tree, it is a modified token and it is assumed that // the caller makes sure that the token is the first token on a line. return(token.SyntaxTree != null ? GetIndentationSteps(indentationSettings, token.SyntaxTree, token.LeadingTrivia) : GetIndentationStepsUnchecked(indentationSettings, token.LeadingTrivia)); }
public void Reformat(IDocumentAccessor doc, IndentationSettings set) { Init(); while (doc.MoveNext()) { Step(doc, set); } }
private static SyntaxNode ReformatStatementAndParent(Document document, IndentationSettings indentationSettings, SyntaxNode syntaxRoot, StatementSyntax statement) { var parentLastToken = statement.GetFirstToken().GetPreviousToken(); var parentEndLine = parentLastToken.GetEndLine(); var statementStartLine = statement.GetFirstToken().GetLine(); var newParentLastToken = parentLastToken; if (parentEndLine == statementStartLine) { var newTrailingTrivia = parentLastToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); newParentLastToken = newParentLastToken.WithTrailingTrivia(newTrailingTrivia); } var parentNextToken = statement.GetLastToken().GetNextToken(); var nextTokenLine = parentNextToken.GetLine(); var statementCloseLine = statement.GetLastToken().GetEndLine(); var newParentNextToken = parentNextToken; if (nextTokenLine == statementCloseLine) { var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(statement.Parent)); var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel); newParentNextToken = newParentNextToken.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } var newStatement = ReformatStatement(document, indentationSettings, statement); var newSyntaxRoot = syntaxRoot.ReplaceSyntax( new[] { statement }, (originalNode, rewrittenNode) => originalNode == statement ? newStatement : rewrittenNode, new[] { parentLastToken, parentNextToken }, (originalToken, rewrittenToken) => { if (originalToken == parentLastToken) { return(newParentLastToken); } else if (originalToken == parentNextToken) { return(newParentNextToken); } else { return(rewrittenToken); } }, Enumerable.Empty <SyntaxTrivia>(), (originalTrivia, rewrittenTrivia) => rewrittenTrivia); return(newSyntaxRoot.WithoutFormatting()); }
/// <summary> /// Gets a whitespace trivia containing the proper amount of indentation for new lines in the query of which the given token is a part. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="token">A token within a query expression.</param> /// <returns>A whitespace trivia containing the proper amount of indentation.</returns> internal static SyntaxTrivia GetQueryIndentationTrivia(IndentationSettings indentationSettings, SyntaxToken token) { var currentNode = token.Parent; while (!currentNode.IsKind(SyntaxKind.QueryExpression)) { currentNode = currentNode.Parent; } return GetQueryIndentationTrivia(indentationSettings, (QueryExpressionSyntax)currentNode); }
/// <summary> /// Gets a whitespace trivia containing the proper amount of indentation for new lines in the query of which the given token is a part. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="token">A token within a query expression.</param> /// <returns>A whitespace trivia containing the proper amount of indentation.</returns> internal static SyntaxTrivia GetQueryIndentationTrivia(IndentationSettings indentationSettings, SyntaxToken token) { var currentNode = token.Parent; while (!currentNode.IsKind(SyntaxKind.QueryExpression)) { currentNode = currentNode.Parent; } return(GetQueryIndentationTrivia(indentationSettings, (QueryExpressionSyntax)currentNode)); }
public void IndentationSettingsToString(Indentation indentation, byte size, string expectedString) { // Arrange var indentationSettings = new IndentationSettings(indentation, size); // Act var indentationString = indentationSettings.ToString(); // Assert indentationString.Should().Be(expectedString); }
private static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxTree syntaxTree, SyntaxTriviaList leadingTrivia) { var triviaSpan = syntaxTree.GetLineSpan(leadingTrivia.FullSpan); // There is no indentation when the leading trivia doesn't begin at the start of the line. if ((triviaSpan.StartLinePosition == triviaSpan.EndLinePosition) && (triviaSpan.StartLinePosition.Character > 0)) { return(0); } return(GetIndentationStepsUnchecked(indentationSettings, leadingTrivia)); }
/// <summary> /// Performs indentation using the specified document accessor. /// </summary> /// <param name="document">Object used for accessing the document line-by-line</param> /// <param name="keepEmptyLines">Specifies whether empty lines should be kept</param> public int Indent(IDocumentAccessor document, bool keepEmptyLines, int caretIndex) { if (document == null) throw new ArgumentNullException(nameof(document)); var settings = new IndentationSettings(); settings.IndentString = IndentationString; settings.LeaveEmptyLines = keepEmptyLines; var r = new IndentationReformatter(); r.Reformat(document, settings); return caretIndex; }
/// <summary> /// Gets a whitespace trivia containing the proper amount of indentation for new lines in the given query. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="queryExpression">The query expression to determine indentation from.</param> /// <returns>A whitespace trivia containing the proper amount of indentation.</returns> internal static SyntaxTrivia GetQueryIndentationTrivia(IndentationSettings indentationSettings, QueryExpressionSyntax queryExpression) { var firstTokenOnTextLine = IndentationHelper.GetFirstTokenOnTextLine(queryExpression.FromClause.FromKeyword); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, firstTokenOnTextLine); // add an extra indentation step when the first from clause is not properly indented yet if (!firstTokenOnTextLine.IsKind(SyntaxKind.OpenParenToken) && (firstTokenOnTextLine != queryExpression.FromClause.FromKeyword)) { indentationSteps++; } return(IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps)); }
/// <summary> /// Gets a whitespace trivia containing the proper amount of indentation for new lines in the given query. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="queryExpression">The query expression to determine indentation from.</param> /// <returns>A whitespace trivia containing the proper amount of indentation.</returns> internal static SyntaxTrivia GetQueryIndentationTrivia(IndentationSettings indentationSettings, QueryExpressionSyntax queryExpression) { var firstTokenOnTextLine = IndentationHelper.GetFirstTokenOnTextLine(queryExpression.FromClause.FromKeyword); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, firstTokenOnTextLine); // add an extra indentation step when the first from clause is not properly indented yet if (!firstTokenOnTextLine.IsKind(SyntaxKind.OpenParenToken) && (firstTokenOnTextLine != queryExpression.FromClause.FromKeyword)) { indentationSteps++; } return IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps); }
public void Indent(IDocumentAccessor document, bool keepEmptyLines) { if (document == null) { throw new ArgumentNullException("document"); } var set = new IndentationSettings { IndentString = IndentationString, LeaveEmptyLines = keepEmptyLines }; var indentationClass = new IndentationClass(); indentationClass.Reformat(document, set); }
private static SyntaxNode ReformatAccessorAsMultipleLines(IndentationSettings indentationSettings, AccessorDeclarationSyntax accessor) { var accessorList = (AccessorListSyntax)accessor.Parent; var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, accessorList.OpenBraceToken) + 1; var indentation = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps); var indentationStatements = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps + 1); var newAccessor = accessor .WithModifiers(ReformatModifiersAsMultipleLines(accessor.Modifiers, indentation)) .WithKeyword(ReformatKeywordAsMultipleLines(accessor.Keyword, indentation, accessor.Modifiers.Count == 0)) .WithBody(ReformatBodyAsMultipleLines(accessor.Body, indentation, indentationStatements)); return(newAccessor); }
private static SyntaxNode ReformatAccessorAsSingleLine(IndentationSettings indentationSettings, AccessorDeclarationSyntax accessor) { var newAccessor = accessor .WithModifiers(ReformatModifiersAsSingleLine(accessor.Modifiers)) .WithKeyword(ReformatKeywordAsSingleLine(accessor.Keyword)) .WithBody(ReformatBodyAsSingleLine(accessor.Body)); var accessorList = (AccessorListSyntax)accessor.Parent; var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, accessorList.OpenBraceToken); var indentation = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps + 1); newAccessor = newAccessor.WithLeadingTrivia(newAccessor.GetLeadingTrivia().Insert(0, indentation)); return(newAccessor); }
/// <summary> /// Generate a new indentation string. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="indentationSteps">The number of indentation steps.</param> /// <returns>A string containing the amount of whitespace needed for the given indentation steps.</returns> public static string GenerateIndentationString(IndentationSettings indentationSettings, int indentationSteps) { string result; var indentationCount = indentationSteps * indentationSettings.IndentationSize; if (indentationSettings.UseTabs) { var tabCount = indentationCount / indentationSettings.TabSize; var spaceCount = indentationCount % indentationSettings.TabSize; result = new string('\t', tabCount) + new string(' ', spaceCount); } else { result = new string(' ', indentationCount); } return result; }
private static StatementSyntax ReformatStatement(Document document, IndentationSettings indentationSettings, StatementSyntax statement) { var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(statement.Parent)); // use one additional step of indentation for lambdas / anonymous methods switch (statement.Parent.Kind()) { case SyntaxKind.AnonymousMethodExpression: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.ParenthesizedLambdaExpression: parentIndentationLevel++; break; } var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel + 1); var newFirstTokenLeadingTrivia = statement.GetFirstToken().LeadingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(statementIndentationString)); var newLastTokenTrailingTrivia = statement.GetLastToken().TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); var firstToken = statement.GetFirstToken().WithLeadingTrivia(newFirstTokenLeadingTrivia); var lastToken = statement.GetLastToken().WithTrailingTrivia(newLastTokenTrailingTrivia); return(statement.ReplaceTokens( new[] { statement.GetFirstToken(), statement.GetLastToken() }, (originalToken, rewrittenToken) => { if (originalToken == statement.GetFirstToken()) { return firstToken; } else if (originalToken == statement.GetLastToken()) { return lastToken; } else { return rewrittenToken; } })); }
/// <summary> /// Generate a new indentation string. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="indentationSteps">The number of indentation steps.</param> /// <returns>A string containing the amount of whitespace needed for the given indentation steps.</returns> public static string GenerateIndentationString(IndentationSettings indentationSettings, int indentationSteps) { string result; var indentationCount = indentationSteps * indentationSettings.IndentationSize; if (indentationSettings.UseTabs) { var tabCount = indentationCount / indentationSettings.TabSize; var spaceCount = indentationCount % indentationSettings.TabSize; result = new string('\t', tabCount) + new string(' ', spaceCount); } else { result = new string(' ', indentationCount); } return(result); }
private static TextChange FixDiagnostic(IndentationSettings indentationSettings, SourceText sourceText, Diagnostic diagnostic) { TextSpan span = diagnostic.Location.SourceSpan; TextLine startLine = sourceText.Lines.GetLineFromPosition(span.Start); string text = sourceText.ToString(TextSpan.FromBounds(startLine.Start, span.End)); StringBuilder replacement = StringBuilderPool.Allocate(); int column = 0; for (int i = 0; i < text.Length; i++) { char c = text[i]; if (c == '\t') { var offsetWithinTabColumn = column % indentationSettings.TabSize; var spaceCount = indentationSettings.TabSize - offsetWithinTabColumn; if (i >= span.Start - startLine.Start) { replacement.Append(' ', spaceCount); } column += spaceCount; } else { if (i >= span.Start - startLine.Start) { replacement.Append(c); } if (c == '\n') { column = 0; } else { column++; } } } return new TextChange(span, StringBuilderPool.ReturnAndFree(replacement)); }
private static int DetermineIndentationLevel(IndentationSettings indentationSettings, Dictionary <SyntaxToken, SyntaxToken> tokenReplaceMap, StatementSyntax statement) { var parent = GetStatementParent(statement.Parent); int parentIndentationLevel; SyntaxToken replacementToken; if (tokenReplaceMap.TryGetValue(parent.GetFirstToken(), out replacementToken)) { // if the parent is being modified, use the new leading trivia from the parent for determining the indentation parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, replacementToken); } else { parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetFirstOnLineParent(parent)); } return(parentIndentationLevel); }
private static SyntaxNode UpdateSyntaxRoot(MemberDeclarationSyntax memberDeclaration, ImmutableArray<OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { var parentDeclaration = memberDeclaration.Parent; var memberToMove = new MemberOrderHelper(memberDeclaration, elementOrder); if (parentDeclaration is TypeDeclarationSyntax) { return HandleTypeDeclaration(memberToMove, (TypeDeclarationSyntax)parentDeclaration, elementOrder, syntaxRoot, indentationSettings); } if (parentDeclaration is NamespaceDeclarationSyntax) { return HandleNamespaceDeclaration(memberToMove, (NamespaceDeclarationSyntax)parentDeclaration, elementOrder, syntaxRoot, indentationSettings); } if (parentDeclaration is CompilationUnitSyntax) { return HandleCompilationUnitDeclaration(memberToMove, (CompilationUnitSyntax)parentDeclaration, elementOrder, syntaxRoot, indentationSettings); } return syntaxRoot; }
private static SyntaxNode ReformatBlockAndParent(Document document, IndentationSettings indentationSettings, SyntaxNode syntaxRoot, BlockSyntax block) { var parentLastToken = block.OpenBraceToken.GetPreviousToken(); var parentEndLine = parentLastToken.GetEndLine(); var blockStartLine = block.OpenBraceToken.GetLine(); var newParentLastToken = parentLastToken; if (parentEndLine == blockStartLine) { var newTrailingTrivia = parentLastToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); newParentLastToken = newParentLastToken.WithTrailingTrivia(newTrailingTrivia); } var parentNextToken = block.CloseBraceToken.GetNextToken(); var nextTokenLine = parentNextToken.GetLine(); var blockCloseLine = block.CloseBraceToken.GetEndLine(); var newParentNextToken = parentNextToken; if (nextTokenLine == blockCloseLine) { newParentNextToken = newParentNextToken.WithLeadingTrivia(parentLastToken.LeadingTrivia); } var newBlock = ReformatBlock(document, indentationSettings, block); var rewriter = new BlockRewriter(parentLastToken, newParentLastToken, block, newBlock, parentNextToken, newParentNextToken); var newSyntaxRoot = rewriter.Visit(syntaxRoot); return(newSyntaxRoot.WithoutFormatting()); }
private static ConstructorDeclarationSyntax ReformatConstructorDeclaration(ConstructorDeclarationSyntax constructorDeclaration, IndentationSettings indentationSettings, SyntaxTrivia newLine) { var constructorInitializer = constructorDeclaration.Initializer; var newParameterList = constructorDeclaration.ParameterList .WithTrailingTrivia(constructorDeclaration.ParameterList.GetTrailingTrivia().WithoutTrailingWhitespace().Add(newLine)); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, constructorDeclaration); var indentation = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps + 1); var newColonTrailingTrivia = constructorInitializer.ColonToken.TrailingTrivia.WithoutTrailingWhitespace(); var newColonToken = constructorInitializer.ColonToken .WithLeadingTrivia(indentation) .WithTrailingTrivia(newColonTrailingTrivia); var newInitializer = constructorInitializer .WithColonToken(newColonToken) .WithThisOrBaseKeyword(constructorInitializer.ThisOrBaseKeyword.WithLeadingTrivia(SyntaxFactory.Space)); return constructorDeclaration .WithParameterList(newParameterList) .WithInitializer(newInitializer); }
private static Dictionary <SyntaxToken, SyntaxToken> GenerateBraceFixes(IndentationSettings indentationSettings, ImmutableArray <SyntaxToken> braceTokens) { var tokenReplacements = new Dictionary <SyntaxToken, SyntaxToken>(); foreach (var braceToken in braceTokens) { var braceLine = LocationHelpers.GetLineSpan(braceToken).StartLinePosition.Line; var braceReplacementToken = braceToken; var indentationSteps = DetermineIndentationSteps(indentationSettings, braceToken); var previousToken = braceToken.GetPreviousToken(); if (IsAccessorWithSingleLineBlock(previousToken, braceToken)) { var newTrailingTrivia = previousToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Space); AddReplacement(tokenReplacements, previousToken, previousToken.WithTrailingTrivia(newTrailingTrivia)); braceReplacementToken = braceReplacementToken.WithLeadingTrivia(braceToken.LeadingTrivia.WithoutLeadingWhitespace()); } else { // Check if we need to apply a fix before the brace if (LocationHelpers.GetLineSpan(previousToken).StartLinePosition.Line == braceLine) { if (!braceTokens.Contains(previousToken)) { var sharedTrivia = braceReplacementToken.LeadingTrivia.WithoutTrailingWhitespace(); var previousTokenNewTrailingTrivia = previousToken.TrailingTrivia .WithoutTrailingWhitespace() .AddRange(sharedTrivia) .Add(SyntaxFactory.CarriageReturnLineFeed); AddReplacement(tokenReplacements, previousToken, previousToken.WithTrailingTrivia(previousTokenNewTrailingTrivia)); } braceReplacementToken = braceReplacementToken.WithLeadingTrivia(IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps)); } // Check if we need to apply a fix after the brace. No fix is needed when: // - The closing brace is followed by a semi-colon or closing paren // - The closing brace is the last token in the file var nextToken = braceToken.GetNextToken(); var nextTokenLine = nextToken.IsKind(SyntaxKind.None) ? -1 : LocationHelpers.GetLineSpan(nextToken).StartLinePosition.Line; var isMultiDimensionArrayInitializer = braceToken.IsKind(SyntaxKind.OpenBraceToken) && braceToken.Parent.IsKind(SyntaxKind.ArrayInitializerExpression) && braceToken.Parent.Parent.IsKind(SyntaxKind.ArrayInitializerExpression); if ((nextTokenLine == braceLine) && (!braceToken.IsKind(SyntaxKind.CloseBraceToken) || !IsValidFollowingToken(nextToken)) && !isMultiDimensionArrayInitializer) { var sharedTrivia = nextToken.LeadingTrivia.WithoutTrailingWhitespace(); var newTrailingTrivia = braceReplacementToken.TrailingTrivia .WithoutTrailingWhitespace() .AddRange(sharedTrivia) .Add(SyntaxFactory.CarriageReturnLineFeed); if (!braceTokens.Contains(nextToken)) { int newIndentationSteps = indentationSteps; if (braceToken.IsKind(SyntaxKind.OpenBraceToken)) { newIndentationSteps++; } if (nextToken.IsKind(SyntaxKind.CloseBraceToken)) { newIndentationSteps = Math.Max(0, newIndentationSteps - 1); } AddReplacement(tokenReplacements, nextToken, nextToken.WithLeadingTrivia(IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, newIndentationSteps))); } braceReplacementToken = braceReplacementToken.WithTrailingTrivia(newTrailingTrivia); } } AddReplacement(tokenReplacements, braceToken, braceReplacementToken); } return(tokenReplacements); }
private static void ReportIncorrectTabUsage(SyntaxTreeAnalysisContext context, IndentationSettings indentationSettings, ImmutableArray <TextSpan> excludedSpans) { SyntaxTree syntaxTree = context.Tree; SourceText sourceText = syntaxTree.GetText(context.CancellationToken); string completeText = sourceText.ToString(); int length = completeText.Length; bool useTabs = indentationSettings.UseTabs; int tabSize = indentationSettings.TabSize; int excludedSpanIndex = 0; var lastExcludedSpan = new TextSpan(completeText.Length, 0); TextSpan nextExcludedSpan = !excludedSpans.IsEmpty ? excludedSpans[0] : lastExcludedSpan; int lastLineStart = 0; for (int startIndex = 0; startIndex < length; startIndex++) { if (startIndex == nextExcludedSpan.Start) { startIndex = nextExcludedSpan.End - 1; excludedSpanIndex++; nextExcludedSpan = excludedSpanIndex < excludedSpans.Length ? excludedSpans[excludedSpanIndex] : lastExcludedSpan; continue; } int tabCount = 0; bool containsSpaces = false; bool tabAfterSpace = false; switch (completeText[startIndex]) { case ' ': containsSpaces = true; break; case '\t': tabCount++; break; case '\r': case '\n': // Handle newlines. We can ignore CR/LF/CRLF issues because we are only tracking column position // in a line, and not the line numbers themselves. lastLineStart = startIndex + 1; continue; default: continue; } int endIndex; for (endIndex = startIndex + 1; endIndex < length; endIndex++) { if (endIndex == nextExcludedSpan.Start) { break; } if (completeText[endIndex] == ' ') { containsSpaces = true; } else if (completeText[endIndex] == '\t') { tabCount++; tabAfterSpace = containsSpaces; } else { break; } } if (useTabs && startIndex == lastLineStart) { // For the case we care about in the following condition (tabAfterSpace is false), spaceCount is // the number of consecutive trailing spaces. int spaceCount = (endIndex - startIndex) - tabCount; if (tabAfterSpace || spaceCount >= tabSize) { context.ReportDiagnostic( Diagnostic.Create( Descriptor, Location.Create(syntaxTree, TextSpan.FromBounds(startIndex, endIndex)), ConvertToTabsProperties)); } } else { if (tabCount > 0) { context.ReportDiagnostic( Diagnostic.Create( Descriptor, Location.Create(syntaxTree, TextSpan.FromBounds(startIndex, endIndex)), ConvertToSpacesProperties)); } } // Make sure to not analyze overlapping spans startIndex = endIndex - 1; } }
private static SyntaxNode ReformatStatementAndParent(Document document, IndentationSettings indentationSettings, SyntaxNode syntaxRoot, StatementSyntax statement) { var parentLastToken = statement.GetFirstToken().GetPreviousToken(); var parentEndLine = parentLastToken.GetEndLine(); var statementStartLine = statement.GetFirstToken().GetLine(); var newParentLastToken = parentLastToken; if (parentEndLine == statementStartLine) { var newTrailingTrivia = parentLastToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); newParentLastToken = newParentLastToken.WithTrailingTrivia(newTrailingTrivia); } var parentNextToken = statement.GetLastToken().GetNextToken(); var nextTokenLine = parentNextToken.GetLine(); var statementCloseLine = statement.GetLastToken().GetEndLine(); var newParentNextToken = parentNextToken; if (nextTokenLine == statementCloseLine) { var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(statement.Parent)); var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel); newParentNextToken = newParentNextToken.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } var newStatement = ReformatStatement(document, indentationSettings, statement); var newSyntaxRoot = syntaxRoot.ReplaceSyntax( new[] { statement }, (originalNode, rewrittenNode) => originalNode == statement ? newStatement : rewrittenNode, new[] { parentLastToken, parentNextToken }, (originalToken, rewrittenToken) => { if (originalToken == parentLastToken) { return newParentLastToken; } else if (originalToken == parentNextToken) { return newParentNextToken; } else { return rewrittenToken; } }, Enumerable.Empty<SyntaxTrivia>(), (originalTrivia, rewrittenTrivia) => rewrittenTrivia); return newSyntaxRoot.WithoutFormatting(); }
/// <summary> /// Gets the number of steps that the given node is indented. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="node">The node to inspect.</param> /// <returns>The number of steps that the node is indented.</returns> public static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxNode node) { return(GetIndentationSteps(indentationSettings, node.SyntaxTree, node.GetLeadingTrivia())); }
private static SyntaxNode MoveMember(SyntaxNode syntaxRoot, MemberDeclarationSyntax member, MemberDeclarationSyntax targetMember, IndentationSettings indentationSettings) { var firstToken = syntaxRoot.GetFirstToken(); var fileHeader = GetFileHeader(firstToken.LeadingTrivia); syntaxRoot = syntaxRoot.TrackNodes(member, targetMember, firstToken.Parent); var memberToMove = syntaxRoot.GetCurrentNode(member); var targetMemberTracked = syntaxRoot.GetCurrentNode(targetMember); if (!memberToMove.HasLeadingTrivia) { var targetIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, targetMember); var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, targetIndentationLevel); memberToMove = memberToMove.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } if (!HasLeadingBlankLines(targetMember) && HasLeadingBlankLines(member)) { memberToMove = memberToMove.WithTrailingTrivia(memberToMove.GetTrailingTrivia().Add(SyntaxFactory.CarriageReturnLineFeed)); memberToMove = memberToMove.WithLeadingTrivia(GetLeadingTriviaWithoutLeadingBlankLines(memberToMove)); } syntaxRoot = syntaxRoot.InsertNodesBefore(targetMemberTracked, new[] { memberToMove }); var fieldToMoveTracked = syntaxRoot.GetCurrentNodes(member).Last(); syntaxRoot = syntaxRoot.RemoveNode(fieldToMoveTracked, SyntaxRemoveOptions.KeepNoTrivia); if (fileHeader.Any()) { var oldFirstToken = syntaxRoot.GetCurrentNode(firstToken.Parent).ChildTokens().First(); syntaxRoot = syntaxRoot.ReplaceToken(oldFirstToken, oldFirstToken.WithLeadingTrivia(StripFileHeader(oldFirstToken.LeadingTrivia))); var newFirstToken = syntaxRoot.GetFirstToken(); syntaxRoot = syntaxRoot.ReplaceToken(newFirstToken, newFirstToken.WithLeadingTrivia(fileHeader.AddRange(newFirstToken.LeadingTrivia))); } return(syntaxRoot); }
private static void BuildReplaceMapForNamespaces(UsingsHelper usingsHelper, Dictionary<UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, bool qualifyNames) { var usingsPerNamespace = usingsHelper .GetContainedUsings(usingsHelper.RootSpan) .GroupBy(ud => ud.Parent) .Select(gr => gr.ToList()); foreach (var usingList in usingsPerNamespace) { if (usingList.Count > 0) { // sort the original using declarations on Span.Start, in order to have the correct replace mapping. usingList.Sort(CompareSpanStart); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, usingList[0].Parent); if (usingList[0].Parent is NamespaceDeclarationSyntax) { indentationSteps++; } var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(usingList, indentation, false, qualifyNames); for (var i = 0; i < usingList.Count; i++) { replaceMap.Add(usingList[i], modifiedUsings[i]); } } } }
private static void BuildReplaceMapForConditionalDirectives(UsingsHelper usingsHelper, Dictionary<UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, DirectiveSpan rootSpan) { foreach (var childSpan in rootSpan.Children) { var originalUsings = usingsHelper.GetContainedUsings(childSpan); if (originalUsings.Count > 0) { // sort the original using declarations on Span.Start, in order to have the correct replace mapping. originalUsings.Sort(CompareSpanStart); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, originalUsings[0].Parent); if (originalUsings[0].Parent is NamespaceDeclarationSyntax) { indentationSteps++; } var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(childSpan, indentation, false, qualifyNames: false); for (var i = 0; i < originalUsings.Count; i++) { replaceMap.Add(originalUsings[i], modifiedUsings[i]); } } BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationSettings, childSpan); } }
private static Dictionary<SyntaxToken, SyntaxToken> GenerateBraceFixes(Document document, IndentationSettings indentationSettings, ImmutableArray<SyntaxToken> braceTokens) { var tokenReplacements = new Dictionary<SyntaxToken, SyntaxToken>(); foreach (var braceToken in braceTokens) { var braceLine = LocationHelpers.GetLineSpan(braceToken).StartLinePosition.Line; var braceReplacementToken = braceToken; var indentationSteps = DetermineIndentationSteps(indentationSettings, braceToken); var previousToken = braceToken.GetPreviousToken(); var nextToken = braceToken.GetNextToken(); if (IsAccessorWithSingleLineBlock(previousToken, braceToken)) { var newTrailingTrivia = previousToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Space); AddReplacement(tokenReplacements, previousToken, previousToken.WithTrailingTrivia(newTrailingTrivia)); braceReplacementToken = braceReplacementToken.WithLeadingTrivia(braceToken.LeadingTrivia.WithoutLeadingWhitespace()); } else { // Check if we need to apply a fix before the brace if (LocationHelpers.GetLineSpan(previousToken).StartLinePosition.Line == braceLine) { if (!braceTokens.Contains(previousToken)) { var sharedTrivia = braceReplacementToken.LeadingTrivia.WithoutTrailingWhitespace(); var previousTokenNewTrailingTrivia = previousToken.TrailingTrivia .WithoutTrailingWhitespace() .AddRange(sharedTrivia) .Add(SyntaxFactory.CarriageReturnLineFeed); AddReplacement(tokenReplacements, previousToken, previousToken.WithTrailingTrivia(previousTokenNewTrailingTrivia)); } braceReplacementToken = braceReplacementToken.WithLeadingTrivia(IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps)); } // Check if we need to apply a fix after the brace // if a closing brace is followed by a semi-colon or closing paren, no fix is needed. if ((LocationHelpers.GetLineSpan(nextToken).StartLinePosition.Line == braceLine) && (!braceToken.IsKind(SyntaxKind.CloseBraceToken) || !IsValidFollowingToken(nextToken))) { var sharedTrivia = nextToken.LeadingTrivia.WithoutTrailingWhitespace(); var newTrailingTrivia = braceReplacementToken.TrailingTrivia .WithoutTrailingWhitespace() .AddRange(sharedTrivia) .Add(SyntaxFactory.CarriageReturnLineFeed); if (!braceTokens.Contains(nextToken)) { int newIndentationSteps; if (braceToken.IsKind(SyntaxKind.OpenBraceToken)) { newIndentationSteps = indentationSteps + 1; } else if (nextToken.IsKind(SyntaxKind.CloseBraceToken)) { newIndentationSteps = Math.Max(0, indentationSteps - 1); } else { newIndentationSteps = indentationSteps; } AddReplacement(tokenReplacements, nextToken, nextToken.WithLeadingTrivia(IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, newIndentationSteps))); } braceReplacementToken = braceReplacementToken.WithTrailingTrivia(newTrailingTrivia); } } AddReplacement(tokenReplacements, braceToken, braceReplacementToken); } return tokenReplacements; }
private static int DetermineIndentationSteps(IndentationSettings indentationSettings, SyntaxToken token) { // For a closing brace use the indentation of the corresponding opening brace if (token.IsKind(SyntaxKind.CloseBraceToken)) { var depth = 1; while (depth > 0) { token = token.GetPreviousToken(); switch (token.Kind()) { case SyntaxKind.CloseBraceToken: depth++; break; case SyntaxKind.OpenBraceToken: depth--; break; } } } var startLine = GetTokenStartLinePosition(token).Line; while (!ContainsStartOfLine(token, startLine)) { token = token.GetPreviousToken(); } return IndentationHelper.GetIndentationSteps(indentationSettings, token); }
private static SyntaxNode HandleCompilationUnitDeclaration(MemberOrderHelper memberOrder, CompilationUnitSyntax compilationUnitDeclaration, ImmutableArray<OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { return OrderMember(memberOrder, compilationUnitDeclaration.Members, elementOrder, syntaxRoot, indentationSettings); }
private static void BuildReplaceMapForNamespaces(UsingsSorter usingsHelper, Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, bool qualifyNames) { var usingsPerNamespace = usingsHelper .GetContainedUsings(TreeTextSpan.Empty) .GroupBy(ud => ud.Parent) .Select(gr => gr.ToList()); foreach (var usingList in usingsPerNamespace) { if (usingList.Count > 0) { // sort the original using declarations on Span.Start, in order to have the correct replace mapping. usingList.Sort(CompareSpanStart); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, usingList[0].Parent); if (usingList[0].Parent is NamespaceDeclarationSyntax) { indentationSteps++; } var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(usingList, indentation, false, qualifyNames); for (var i = 0; i < usingList.Count; i++) { replaceMap.Add(usingList[i], modifiedUsings[i]); } } } }
private static SyntaxNode MoveMember(SyntaxNode syntaxRoot, MemberDeclarationSyntax member, MemberDeclarationSyntax targetMember, IndentationSettings indentationSettings) { var firstToken = syntaxRoot.GetFirstToken(); var fileHeader = GetFileHeader(firstToken.LeadingTrivia); syntaxRoot = syntaxRoot.TrackNodes(member, targetMember, firstToken.Parent); var memberToMove = syntaxRoot.GetCurrentNode(member); var targetMemberTracked = syntaxRoot.GetCurrentNode(targetMember); if (!memberToMove.HasLeadingTrivia) { var targetIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, targetMember); var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, targetIndentationLevel); memberToMove = memberToMove.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } if (!HasLeadingBlankLines(targetMember) && HasLeadingBlankLines(member)) { memberToMove = memberToMove.WithTrailingTrivia(memberToMove.GetTrailingTrivia().Add(SyntaxFactory.CarriageReturnLineFeed)); memberToMove = memberToMove.WithLeadingTrivia(GetLeadingTriviaWithoutLeadingBlankLines(memberToMove)); } syntaxRoot = syntaxRoot.InsertNodesBefore(targetMemberTracked, new[] { memberToMove }); var fieldToMoveTracked = syntaxRoot.GetCurrentNodes(member).Last(); syntaxRoot = syntaxRoot.RemoveNode(fieldToMoveTracked, SyntaxRemoveOptions.KeepNoTrivia); if (fileHeader.Any()) { var oldFirstToken = syntaxRoot.GetCurrentNode(firstToken.Parent).ChildTokens().First(); syntaxRoot = syntaxRoot.ReplaceToken(oldFirstToken, oldFirstToken.WithLeadingTrivia(StripFileHeader(oldFirstToken.LeadingTrivia))); var newFirstToken = syntaxRoot.GetFirstToken(); syntaxRoot = syntaxRoot.ReplaceToken(newFirstToken, newFirstToken.WithLeadingTrivia(fileHeader.AddRange(newFirstToken.LeadingTrivia))); } return syntaxRoot; }
private static SyntaxNode OrderMember(MemberOrderHelper memberOrder, SyntaxList<MemberDeclarationSyntax> members, ImmutableArray<OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { var memberIndex = members.IndexOf(memberOrder.Member); MemberOrderHelper target = default(MemberOrderHelper); for (var i = memberIndex - 1; i >= 0; --i) { var orderHelper = new MemberOrderHelper(members[i], elementOrder); if (orderHelper.Priority < memberOrder.Priority) { target = orderHelper; } else { break; } } return target.Member != null ? MoveMember(syntaxRoot, memberOrder.Member, target.Member, indentationSettings) : syntaxRoot; }
/// <summary> /// Gets the number of steps that the given node is indented. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="node">The node to inspect.</param> /// <returns>The number of steps that the node is indented.</returns> public static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxNode node) { return GetIndentationSteps(indentationSettings, node.SyntaxTree, node.GetLeadingTrivia()); }
private static SyntaxNode OrderMember(MemberOrderHelper memberOrder, SyntaxList <MemberDeclarationSyntax> members, ImmutableArray <OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { var memberIndex = members.IndexOf(memberOrder.Member); MemberOrderHelper target = default; for (var i = memberIndex - 1; i >= 0; --i) { var orderHelper = new MemberOrderHelper(members[i], elementOrder); if (orderHelper.Priority < memberOrder.Priority) { target = orderHelper; } else { break; } } return(target.Member != null?MoveMember(syntaxRoot, memberOrder.Member, target.Member, indentationSettings) : syntaxRoot); }
/// <summary> /// Gets the number of steps that the given token is indented. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="token">The token to inspect.</param> /// <returns>The number of steps that the token is indented.</returns> public static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxToken token) { return GetIndentationSteps(indentationSettings, token.SyntaxTree, token.LeadingTrivia); }
private static SyntaxNode UpdateSyntaxRoot(MemberDeclarationSyntax memberDeclaration, ImmutableArray <OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { var parentDeclaration = memberDeclaration.Parent; var memberToMove = new MemberOrderHelper(memberDeclaration, elementOrder); if (parentDeclaration is TypeDeclarationSyntax) { return(HandleTypeDeclaration(memberToMove, (TypeDeclarationSyntax)parentDeclaration, elementOrder, syntaxRoot, indentationSettings)); } if (parentDeclaration is NamespaceDeclarationSyntax) { return(HandleNamespaceDeclaration(memberToMove, (NamespaceDeclarationSyntax)parentDeclaration, elementOrder, syntaxRoot, indentationSettings)); } if (parentDeclaration is CompilationUnitSyntax) { return(HandleCompilationUnitDeclaration(memberToMove, (CompilationUnitSyntax)parentDeclaration, elementOrder, syntaxRoot, indentationSettings)); } return(syntaxRoot); }
private static TextChange FixDiagnostic(IndentationSettings indentationSettings, SourceText sourceText, Diagnostic diagnostic) { TextSpan span = diagnostic.Location.SourceSpan; TextLine startLine = sourceText.Lines.GetLineFromPosition(span.Start); bool useTabs = false; string behavior; if (diagnostic.Properties.TryGetValue(SA1027UseTabsCorrectly.BehaviorKey, out behavior)) { useTabs = behavior == SA1027UseTabsCorrectly.ConvertToTabsBehavior; } string text = sourceText.ToString(TextSpan.FromBounds(startLine.Start, span.End)); StringBuilder replacement = StringBuilderPool.Allocate(); int spaceCount = 0; int column = 0; for (int i = 0; i < text.Length; i++) { char c = text[i]; if (c == '\t') { var offsetWithinTabColumn = column % indentationSettings.TabSize; var tabWidth = indentationSettings.TabSize - offsetWithinTabColumn; if (i >= span.Start - startLine.Start) { if (useTabs) { replacement.Length = replacement.Length - spaceCount; replacement.Append('\t'); spaceCount = 0; } else { replacement.Append(' ', tabWidth); } } column += tabWidth; } else { if (i >= span.Start - startLine.Start) { replacement.Append(c); if (c == ' ') { spaceCount++; if (useTabs) { // Note that we account for column not yet being incremented var offsetWithinTabColumn = (column + 1) % indentationSettings.TabSize; if (offsetWithinTabColumn == 0) { // We reached a tab stop. replacement.Length = replacement.Length - spaceCount; replacement.Append('\t'); spaceCount = 0; } } } else { spaceCount = 0; } } if (c == '\r' || c == '\n') { // Handle newlines. We can ignore CR/LF/CRLF issues because we are only tracking column position // in a line, and not the line numbers themselves. column = 0; spaceCount = 0; } else { column++; } } } return new TextChange(span, StringBuilderPool.ReturnAndFree(replacement)); }
private static StatementSyntax ReformatStatement(Document document, IndentationSettings indentationSettings, StatementSyntax statement) { var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(statement.Parent)); // use one additional step of indentation for lambdas / anonymous methods switch (statement.Parent.Kind()) { case SyntaxKind.AnonymousMethodExpression: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.ParenthesizedLambdaExpression: parentIndentationLevel++; break; } var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel + 1); var newFirstTokenLeadingTrivia = statement.GetFirstToken().LeadingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(statementIndentationString)); var newLastTokenTrailingTrivia = statement.GetLastToken().TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); var firstToken = statement.GetFirstToken().WithLeadingTrivia(newFirstTokenLeadingTrivia); var lastToken = statement.GetLastToken().WithTrailingTrivia(newLastTokenTrailingTrivia); return statement.ReplaceTokens( new[] { statement.GetFirstToken(), statement.GetLastToken() }, (originalToken, rewrittenToken) => { if (originalToken == statement.GetFirstToken()) { return firstToken; } else if (originalToken == statement.GetLastToken()) { return lastToken; } else { return rewrittenToken; } }); }
/// <summary> /// Generates a whitespace trivia with the requested indentation. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="indentationSteps">The amount of indentation steps.</param> /// <returns>A <see cref="SyntaxTrivia"/> containing the indentation whitespace.</returns> public static SyntaxTrivia GenerateWhitespaceTrivia(IndentationSettings indentationSettings, int indentationSteps) { return SyntaxFactory.Whitespace(GenerateIndentationString(indentationSettings, indentationSteps)); }
private static BlockSyntax ReformatBlock(Document document, IndentationSettings indentationSettings, BlockSyntax block) { var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(block.Parent)); // use one additional step of indentation for lambdas / anonymous methods switch (block.Parent.Kind()) { case SyntaxKind.AnonymousMethodExpression: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.ParenthesizedLambdaExpression: parentIndentationLevel++; break; } var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel); var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel + 1); var newOpenBraceLeadingTrivia = block.OpenBraceToken.LeadingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(indentationString)); var newOpenBraceTrailingTrivia = block.OpenBraceToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); var newCloseBraceLeadingTrivia = block.CloseBraceToken.LeadingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(indentationString)); var newCloseBraceTrailingTrivia = block.CloseBraceToken.TrailingTrivia .WithoutTrailingWhitespace(); bool addNewLineAfterCloseBrace; switch (block.CloseBraceToken.GetNextToken().Kind()) { case SyntaxKind.CloseParenToken: case SyntaxKind.CommaToken: case SyntaxKind.SemicolonToken: addNewLineAfterCloseBrace = false; break; default: addNewLineAfterCloseBrace = (newCloseBraceTrailingTrivia.Count == 0) || !newCloseBraceTrailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia); break; } if (addNewLineAfterCloseBrace) { newCloseBraceTrailingTrivia = newCloseBraceTrailingTrivia.Add(SyntaxFactory.CarriageReturnLineFeed); } var openBraceToken = SyntaxFactory.Token(SyntaxKind.OpenBraceToken) .WithLeadingTrivia(newOpenBraceLeadingTrivia) .WithTrailingTrivia(newOpenBraceTrailingTrivia); var closeBraceToken = SyntaxFactory.Token(SyntaxKind.CloseBraceToken) .WithLeadingTrivia(newCloseBraceLeadingTrivia) .WithTrailingTrivia(newCloseBraceTrailingTrivia); var statements = SyntaxFactory.List<StatementSyntax>(); foreach (var statement in block.Statements) { var newLeadingTrivia = statement.GetLeadingTrivia() .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(statementIndentationString)); var newTrailingTrivia = statement.GetTrailingTrivia() .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); var modifiedStatement = statement .WithLeadingTrivia(newLeadingTrivia) .WithTrailingTrivia(newTrailingTrivia); statements = statements.Add(modifiedStatement); } return SyntaxFactory.Block(openBraceToken, statements, closeBraceToken); }
private static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxTree syntaxTree, SyntaxTriviaList leadingTrivia) { var triviaSpan = syntaxTree.GetLineSpan(leadingTrivia.FullSpan); // There is no indentation when the leading trivia doesn't begin at the start of the line. if ((triviaSpan.StartLinePosition == triviaSpan.EndLinePosition) && (triviaSpan.StartLinePosition.Character > 0)) { return 0; } var builder = StringBuilderPool.Allocate(); foreach (SyntaxTrivia trivia in leadingTrivia.Reverse()) { if (!trivia.IsKind(SyntaxKind.WhitespaceTrivia)) { break; } builder.Insert(0, trivia.ToFullString()); } var tabSize = indentationSettings.TabSize; var indentationCount = 0; for (var i = 0; i < builder.Length; i++) { indentationCount += builder[i] == '\t' ? tabSize - (indentationCount % tabSize) : 1; } StringBuilderPool.ReturnAndFree(builder); return (indentationCount + (indentationSettings.IndentationSize / 2)) / indentationSettings.IndentationSize; }
/// <summary> /// Generates a whitespace trivia with the requested indentation. /// </summary> /// <param name="indentationSettings">The indentation settings to use.</param> /// <param name="indentationSteps">The amount of indentation steps.</param> /// <returns>A <see cref="SyntaxTrivia"/> containing the indentation whitespace.</returns> public static SyntaxTrivia GenerateWhitespaceTrivia(IndentationSettings indentationSettings, int indentationSteps) { return(SyntaxFactory.Whitespace(GenerateIndentationString(indentationSettings, indentationSteps))); }
private static SyntaxNode HandleTypeDeclaration(MemberOrderHelper memberOrder, TypeDeclarationSyntax typeDeclarationNode, ImmutableArray <OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { return(OrderMember(memberOrder, typeDeclarationNode.Members, elementOrder, syntaxRoot, indentationSettings)); }
public void Step(IDocumentAccessor doc, IndentationSettings set) { var line = doc.Text; if (set.LeaveEmptyLines && line.Length == 0) return; // leave empty lines empty line = line.TrimStart(); var indent = new StringBuilder(); if (line.Length == 0) { // Special treatment for empty lines: if (blockComment || (inString && verbatim)) return; indent.Append(block.InnerIndent); indent.Append(Repeat(set.IndentString, block.OneLineBlock)); //if (block.Continuation) //indent.Append(set.IndentString); //DW this prevents indenting on blank new lines... this would be C# specific. if (doc.Text != indent.ToString()) doc.Text = indent.ToString(); return; } if (TrimEnd(doc)) line = doc.Text.TrimStart(); var oldBlock = block; var startInComment = blockComment; var startInString = inString && verbatim; #region Parse char by char lineComment = false; inChar = false; escape = false; if (!verbatim) inString = false; lastRealChar = '\n'; var lastchar = ' '; var c = ' '; var nextchar = line[0]; for (var i = 0; i < line.Length; i++) { if (lineComment) break; // cancel parsing current line lastchar = c; c = nextchar; if (i + 1 < line.Length) nextchar = line[i + 1]; else nextchar = '\n'; if (escape) { escape = false; continue; } #region Check for comment/string chars switch (c) { case '/': if (blockComment && lastchar == '*') blockComment = false; if (!inString && !inChar) { if (!blockComment && nextchar == '/') lineComment = true; if (!lineComment && nextchar == '*') blockComment = true; } break; case '#': if (!(inChar || blockComment || inString)) lineComment = true; break; case '"': if (!(inChar || lineComment || blockComment)) { inString = !inString; if (!inString && verbatim) { if (nextchar == '"') { escape = true; // skip escaped quote inString = true; } else { verbatim = false; } } else if (inString && lastchar == '@') { verbatim = true; } } break; case '\'': if (!(inString || lineComment || blockComment)) { inChar = !inChar; } break; case '\\': if ((inString && !verbatim) || inChar) escape = true; // skip next character break; } #endregion Check for comment/string chars if (lineComment || blockComment || inString || inChar) { if (wordBuilder.Length > 0) block.LastWord = wordBuilder.ToString(); wordBuilder.Length = 0; continue; } if (!char.IsWhiteSpace(c) && c != '[' && c != '/') { if (block.Bracket == '{') block.Continuation = true; } if (char.IsLetterOrDigit(c)) { wordBuilder.Append(c); } else { if (wordBuilder.Length > 0) block.LastWord = wordBuilder.ToString(); wordBuilder.Length = 0; } #region Push/Pop the blocks switch (c) { case '{': block.ResetOneLineBlock(); blocks.Push(block); block.StartLine = doc.LineNumber; if (block.LastWord == "switch") { block.Indent(set.IndentString); /* oldBlock refers to the previous line, not the previous block * The block we want is not available anymore because it was never pushed. * } else if (oldBlock.OneLineBlock) { // Inside a one-line-block is another statement // with a full block: indent the inner full block // by one additional level block.Indent(set, set.IndentString + set.IndentString); block.OuterIndent += set.IndentString; // Indent current line if it starts with the '{' character if (i == 0) { oldBlock.InnerIndent += set.IndentString; }*/ } else { block.Indent(set); } block.Bracket = '{'; break; case '}': while (block.Bracket != '{') { if (blocks.Count == 0) break; block = blocks.Pop(); } if (blocks.Count == 0) break; block = blocks.Pop(); block.Continuation = false; block.ResetOneLineBlock(); break; case '(': case '[': blocks.Push(block); if (block.StartLine == doc.LineNumber) block.InnerIndent = block.OuterIndent; else block.StartLine = doc.LineNumber; block.Indent(Repeat(set.IndentString, oldBlock.OneLineBlock) + (oldBlock.Continuation ? set.IndentString : "") + (i == line.Length - 1 ? set.IndentString : new string(' ', i + 1))); block.Bracket = c; break; case ')': if (blocks.Count == 0) break; if (block.Bracket == '(') { block = blocks.Pop(); if (IsSingleStatementKeyword(block.LastWord)) block.Continuation = false; } break; case ']': if (blocks.Count == 0) break; if (block.Bracket == '[') block = blocks.Pop(); break; case ';': case ',': block.Continuation = false; block.ResetOneLineBlock(); break; case ':': if (block.LastWord == "case" || line.StartsWith("case ", StringComparison.Ordinal) || line.StartsWith(block.LastWord + ":", StringComparison.Ordinal)) { block.Continuation = false; block.ResetOneLineBlock(); } break; } if (!char.IsWhiteSpace(c)) { // register this char as last char lastRealChar = c; } #endregion Push/Pop the blocks } #endregion Parse char by char if (wordBuilder.Length > 0) block.LastWord = wordBuilder.ToString(); wordBuilder.Length = 0; if (startInString) return; if (startInComment && line[0] != '*') return; if (doc.Text.StartsWith("//\t", StringComparison.Ordinal) || doc.Text == "//") return; if (line[0] == '}') { indent.Append(oldBlock.OuterIndent); oldBlock.ResetOneLineBlock(); oldBlock.Continuation = false; } else { indent.Append(oldBlock.InnerIndent); } if (indent.Length > 0 && oldBlock.Bracket == '(' && line[0] == ')') { indent.Remove(indent.Length - 1, 1); } else if (indent.Length > 0 && oldBlock.Bracket == '[' && line[0] == ']') { indent.Remove(indent.Length - 1, 1); } if (line[0] == ':') { oldBlock.Continuation = true; } else if (lastRealChar == ':' && indent.Length >= set.IndentString.Length) { if (block.LastWord == "case" || line.StartsWith("case ", StringComparison.Ordinal) || line.StartsWith(block.LastWord + ":", StringComparison.Ordinal)) indent.Remove(indent.Length - set.IndentString.Length, set.IndentString.Length); } else if (lastRealChar == ')') { if (IsSingleStatementKeyword(block.LastWord)) { block.OneLineBlock++; } } else if (lastRealChar == 'e' && block.LastWord == "else") { block.OneLineBlock = Math.Max(1, block.PreviousOneLineBlock); block.Continuation = false; oldBlock.OneLineBlock = block.OneLineBlock - 1; } if (doc.IsReadOnly) { // We can't change the current line, but we should accept the existing // indentation if possible (=if the current statement is not a multiline // statement). if (!oldBlock.Continuation && oldBlock.OneLineBlock == 0 && oldBlock.StartLine == block.StartLine && block.StartLine < doc.LineNumber && lastRealChar != ':') { // use indent StringBuilder to get the indentation of the current line indent.Length = 0; line = doc.Text; // get untrimmed line for (var i = 0; i < line.Length; ++i) { if (!char.IsWhiteSpace(line[i])) break; indent.Append(line[i]); } // /* */ multiline comments have an extra space - do not count it // for the block's indentation. if (startInComment && indent.Length > 0 && indent[indent.Length - 1] == ' ') { indent.Length -= 1; } block.InnerIndent = indent.ToString(); } return; } if (line[0] != '{') { if (line[0] != ')' && oldBlock.Continuation && oldBlock.Bracket == '{') indent.Append(set.IndentString); indent.Append(Repeat(set.IndentString, oldBlock.OneLineBlock)); } // this is only for blockcomment lines starting with *, // all others keep their old indentation if (startInComment) indent.Append(' '); if (indent.Length != doc.Text.Length - line.Length || !doc.Text.StartsWith(indent.ToString(), StringComparison.Ordinal) || char.IsWhiteSpace(doc.Text[indent.Length])) { doc.Text = indent + line; } }
private static SyntaxNode HandleCompilationUnitDeclaration(MemberOrderHelper memberOrder, CompilationUnitSyntax compilationUnitDeclaration, ImmutableArray <OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { return(OrderMember(memberOrder, compilationUnitDeclaration.Members, elementOrder, syntaxRoot, indentationSettings)); }
public void Indent(IndentationSettings set) { Indent(set.IndentString); }
private static SyntaxNode HandleNamespaceDeclaration(MemberOrderHelper memberOrder, NamespaceDeclarationSyntax namespaceDeclaration, ImmutableArray <OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { return(OrderMember(memberOrder, namespaceDeclaration.Members, elementOrder, syntaxRoot, indentationSettings)); }
private static string DetermineIndentation(CompilationUnitSyntax compilationUnit, IndentationSettings indentationSettings, UsingDirectivesPlacement usingDirectivesPlacement) { string usingsIndentation; if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace) { var rootNamespace = compilationUnit.Members.OfType <NamespaceDeclarationSyntax>().First(); var indentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, rootNamespace); usingsIndentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationLevel + 1); } else { usingsIndentation = string.Empty; } return(usingsIndentation); }
private static SyntaxNode HandleNamespaceDeclaration(MemberOrderHelper memberOrder, NamespaceDeclarationSyntax namespaceDeclaration, ImmutableArray<OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { return OrderMember(memberOrder, namespaceDeclaration.Members, elementOrder, syntaxRoot, indentationSettings); }
private static void BuildReplaceMapForConditionalDirectives(UsingsSorter usingsHelper, Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, TreeTextSpan rootSpan) { foreach (var childSpan in rootSpan.Children) { var originalUsings = usingsHelper.GetContainedUsings(childSpan); if (originalUsings.Count > 0) { // sort the original using declarations on Span.Start, in order to have the correct replace mapping. originalUsings.Sort(CompareSpanStart); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, originalUsings[0].Parent); if (originalUsings[0].Parent is NamespaceDeclarationSyntax) { indentationSteps++; } var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(childSpan, indentation, false, qualifyNames: false); for (var i = 0; i < originalUsings.Count; i++) { replaceMap.Add(originalUsings[i], modifiedUsings[i]); } } BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationSettings, childSpan); } }
private static SyntaxNode HandleTypeDeclaration(MemberOrderHelper memberOrder, TypeDeclarationSyntax typeDeclarationNode, ImmutableArray<OrderingTrait> elementOrder, SyntaxNode syntaxRoot, IndentationSettings indentationSettings) { return OrderMember(memberOrder, typeDeclarationNode.Members, elementOrder, syntaxRoot, indentationSettings); }