protected override async Task <SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray <Diagnostic> diagnostics) { if (diagnostics.IsEmpty) { return(null); } var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, syntaxRoot.SyntaxTree, fixAllContext.CancellationToken); // 🐉 Need to eagerly evaluate this with ToList() to ensure nodes are not garbage collected between the // call to TrackNodes and subsequent enumeration. var nodes = diagnostics.Select(diagnostic => syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true).FirstAncestorOrSelf <AttributeListSyntax>()).ToList(); var newRoot = syntaxRoot.TrackNodes(nodes); foreach (var attributeList in nodes) { var indentationSteps = IndentationHelper.GetIndentationSteps(settings.Indentation, attributeList); var indentationTrivia = IndentationHelper.GenerateWhitespaceTrivia(settings.Indentation, indentationSteps); newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(attributeList), GetNewAttributeList(attributeList, indentationTrivia)); } return(newRoot); }
private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var violatingAttribute = (AttributeSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan).Parent; var attributeList = (AttributeListSyntax)violatingAttribute.Parent; var newAttributeLists = new List <AttributeListSyntax>(); var indentationOptions = IndentationOptions.FromDocument(document); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationOptions, attributeList); var indentationTrivia = IndentationHelper.GenerateWhitespaceTrivia(indentationOptions, indentationSteps); for (var i = 0; i < attributeList.Attributes.Count; i++) { var newAttributes = SyntaxFactory.SingletonSeparatedList(attributeList.Attributes[i]); var newAttributeList = SyntaxFactory.AttributeList(attributeList.Target, newAttributes); newAttributeList = (i == 0) ? newAttributeList.WithLeadingTrivia(attributeList.GetLeadingTrivia()) : newAttributeList.WithLeadingTrivia(indentationTrivia); newAttributeList = (i == (attributeList.Attributes.Count - 1)) ? newAttributeList.WithTrailingTrivia(attributeList.GetTrailingTrivia()) : newAttributeList.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed); newAttributeLists.Add(newAttributeList); } var newSyntaxRoot = syntaxRoot.ReplaceNode(attributeList, newAttributeLists); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return(newDocument); }
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 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 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 ReformatStatementAndParent(Document document, 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 indentationOptions = IndentationOptions.FromDocument(document); var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, GetStatementParent(statement.Parent)); var indentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel); newParentNextToken = newParentNextToken.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } var newStatement = ReformatStatement(document, 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()); }
private BlockSyntax ReformatBlock(CodeFixContext context, BlockSyntax block) { var indentationOptions = IndentationOptions.FromDocument(context.Document); var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, block.Parent); var indentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel); var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationOptions, 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(); // only add an end-of-line to the close brace if there is none yet. if ((newCloseBraceTrailingTrivia.Count == 0) || !newCloseBraceTrailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia)) { 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)); }
public async Task VerifyGetIndentationStepsAsync(string indentationString, int expectedIndentationSteps, int indentationSize, int tabSize) { var testSource = $"{indentationString}public class TestClass {{}}"; var document = CreateTestDocument(testSource, indentationSize, false, tabSize); var indentationOptions = IndentationOptions.FromDocument(document); var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); var firstToken = syntaxRoot.GetFirstToken(); Assert.Equal(expectedIndentationSteps, IndentationHelper.GetIndentationSteps(indentationOptions, firstToken)); }
public async Task VerifyGetIndentationStepsForTokenNotAtStartOfLineAsync() { var testSource = " public class TestClass {}"; var document = CreateTestDocument(testSource); StyleCopSettings settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, CancellationToken.None); var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); var secondToken = syntaxRoot.GetFirstToken().GetNextToken(); Assert.Equal(0, IndentationHelper.GetIndentationSteps(settings.Indentation, secondToken)); }
public async Task VerifyGetIndentationStepsAsync(string indentationString, int expectedIndentationSteps, int indentationSize, int tabSize) { var testSource = $"{indentationString}public class TestClass {{}}"; var document = CreateTestDocument(testSource, indentationSize, false, tabSize); StyleCopSettings settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, CancellationToken.None); var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); var firstToken = syntaxRoot.GetFirstToken(); Assert.Equal(expectedIndentationSteps, IndentationHelper.GetIndentationSteps(settings.Indentation, firstToken)); }
public async Task VerifyGetIndentationStepsForTokenNotAtStartOfLineAsync() { var testSource = " public class TestClass {}"; var document = CreateTestDocument(testSource); var indentationOptions = IndentationOptions.FromDocument(document); var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); var secondToken = syntaxRoot.GetFirstToken().GetNextToken(); Assert.Equal(0, IndentationHelper.GetIndentationSteps(indentationOptions, secondToken)); }
/// <summary> /// Gets a whitespace trivia containing the proper amount of indentation for new lines in the given query. /// </summary> /// <param name="indentationOptions">The indentation options 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(IndentationOptions indentationOptions, QueryExpressionSyntax queryExpression) { var firstTokenOnTextLine = IndentationHelper.GetFirstTokenOnTextLine(queryExpression.FromClause.FromKeyword); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationOptions, 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(indentationOptions, indentationSteps)); }
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); }
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 StatementSyntax ReformatStatement(Document document, StatementSyntax statement) { var indentationOptions = IndentationOptions.FromDocument(document); var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, 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(indentationOptions, 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; } })); }
private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var nodeInSourceSpan = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true); AttributeListSyntax attributeList = nodeInSourceSpan.FirstAncestorOrSelf <AttributeListSyntax>(); var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken); var indentationSteps = IndentationHelper.GetIndentationSteps(settings.Indentation, attributeList); var indentationTrivia = IndentationHelper.GenerateWhitespaceTrivia(settings.Indentation, indentationSteps); List <AttributeListSyntax> newAttributeLists = GetNewAttributeList(attributeList, indentationTrivia); var newSyntaxRoot = syntaxRoot.ReplaceNode(attributeList, newAttributeLists); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return(newDocument); }
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 async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, syntaxRoot.SyntaxTree, cancellationToken); var attributeListSyntax = (AttributeListSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan); // use the containing type to determine the indentation level, anything else is less reliable. var containingType = attributeListSyntax.Parent?.Parent; var indentationSteps = (containingType != null) ? IndentationHelper.GetIndentationSteps(settings.Indentation, containingType) + 1 : 0; var indentationTrivia = IndentationHelper.GenerateWhitespaceTrivia(settings.Indentation, indentationSteps); var tokensToReplace = new Dictionary <SyntaxToken, SyntaxToken>(); if (diagnostic.Properties.ContainsKey(SA1134AttributesMustNotShareLine.FixWithNewLineBeforeKey)) { var token = attributeListSyntax.OpenBracketToken; var prevToken = token.GetPreviousToken(); tokensToReplace[prevToken] = prevToken.WithTrailingTrivia(prevToken.TrailingTrivia.WithoutTrailingWhitespace().Add(SyntaxFactory.CarriageReturnLineFeed)); var newLeadingTrivia = token.LeadingTrivia.Insert(0, indentationTrivia); tokensToReplace[token] = token.WithLeadingTrivia(newLeadingTrivia); } if (diagnostic.Properties.ContainsKey(SA1134AttributesMustNotShareLine.FixWithNewLineAfterKey)) { var token = attributeListSyntax.CloseBracketToken; var nextToken = token.GetNextToken(); tokensToReplace[token] = token.WithTrailingTrivia(token.TrailingTrivia.WithoutTrailingWhitespace().Add(SyntaxFactory.CarriageReturnLineFeed)); var newLeadingTrivia = nextToken.LeadingTrivia.Insert(0, indentationTrivia); tokensToReplace[nextToken] = nextToken.WithLeadingTrivia(newLeadingTrivia); } var newSyntaxRoot = syntaxRoot.ReplaceTokens(tokensToReplace.Keys, (original, rewritten) => tokensToReplace[original]); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return(newDocument); }
private static string DetermineIndentation(CompilationUnitSyntax compilationUnit, IndentationSettings indentationSettings, UsingDirectivesPlacement usingDirectivesPlacement) { string usingsIndentation; if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace) { var rootNamespace = compilationUnit.Members.First(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member)); var indentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, rootNamespace); if (!rootNamespace.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration)) { indentationLevel++; } usingsIndentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationLevel); } else { usingsIndentation = string.Empty; } return(usingsIndentation); }
protected override async Task <SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray <Diagnostic> diagnostics) { if (diagnostics.IsEmpty) { return(null); } var indentationOptions = IndentationOptions.FromDocument(document); var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var nodes = diagnostics.Select(diagnostic => syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true).FirstAncestorOrSelf <AttributeListSyntax>()); var newRoot = syntaxRoot.TrackNodes(nodes); foreach (var attributeList in nodes) { var indentationSteps = IndentationHelper.GetIndentationSteps(indentationOptions, attributeList); var indentationTrivia = IndentationHelper.GenerateWhitespaceTrivia(indentationOptions, indentationSteps); newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(attributeList), GetNewAttributeList(attributeList, indentationTrivia)); } return(newRoot); }
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 async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, syntaxRoot.SyntaxTree, cancellationToken); var enumMemberDeclaration = (EnumMemberDeclarationSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan); var enumDeclaration = (EnumDeclarationSyntax)enumMemberDeclaration.Parent; var memberIndex = enumDeclaration.Members.IndexOf(enumMemberDeclaration); var precedingSeparatorToken = enumDeclaration.Members.GetSeparator(memberIndex - 1); // determine the indentation for enum members (which is parent + 1 step) var parentIndentationSteps = IndentationHelper.GetIndentationSteps(settings.Indentation, enumDeclaration); var indentation = IndentationHelper.GenerateWhitespaceTrivia(settings.Indentation, parentIndentationSteps + 1); // combine all trivia between the separator and the enum member and place them after the separator, followed by a new line. var enumMemberDeclarationFirstToken = enumMemberDeclaration.GetFirstToken(); var sharedTrivia = TriviaHelper.MergeTriviaLists(precedingSeparatorToken.TrailingTrivia, enumMemberDeclarationFirstToken.LeadingTrivia); var newTrailingTrivia = SyntaxFactory.TriviaList(sharedTrivia) .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); // replace the trivia for the tokens var replacements = new Dictionary <SyntaxToken, SyntaxToken> { [precedingSeparatorToken] = precedingSeparatorToken.WithTrailingTrivia(newTrailingTrivia), [enumMemberDeclarationFirstToken] = enumMemberDeclarationFirstToken.WithLeadingTrivia(indentation), }; var newSyntaxRoot = syntaxRoot.ReplaceTokens(replacements.Keys, (original, rewritten) => replacements[original]); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return(newDocument); }
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 void ReformatBlock(IndentationSettings indentationSettings, BlockSyntax block, Dictionary <SyntaxToken, SyntaxToken> tokenReplaceMap) { 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); } AddToReplaceMap(tokenReplaceMap, block.OpenBraceToken, block.OpenBraceToken.WithLeadingTrivia(newOpenBraceLeadingTrivia).WithTrailingTrivia(newOpenBraceTrailingTrivia)); AddToReplaceMap(tokenReplaceMap, block.CloseBraceToken, block.CloseBraceToken.WithLeadingTrivia(newCloseBraceLeadingTrivia).WithTrailingTrivia(newCloseBraceTrailingTrivia)); foreach (var statement in block.Statements) { var firstToken = statement.GetFirstToken(); var lastToken = statement.GetLastToken(); var newLeadingTrivia = firstToken.LeadingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(statementIndentationString)); var newTrailingTrivia = lastToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); AddToReplaceMap(tokenReplaceMap, firstToken, firstToken.WithLeadingTrivia(newLeadingTrivia)); AddToReplaceMap(tokenReplaceMap, lastToken, lastToken.WithTrailingTrivia(newTrailingTrivia)); } }
private static Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode syntaxRoot, CancellationToken cancellationToken) { var compilationUnit = (CompilationUnitSyntax)syntaxRoot; var indentationOptions = IndentationOptions.FromDocument(document); var usingsHelper = new UsingsHelper(document, compilationUnit); var namespaceCount = CountNamespaces(compilationUnit.Members); // Only move using declarations inside the namespace when // - SA1200 is enabled // - There are no global attributes // - There is only a single namespace declared at the top level var moveInsideNamespace = !document.Project.CompilationOptions.IsAnalyzerSuppressed(SA1200UsingDirectivesMustBePlacedWithinNamespace.DiagnosticId) && !compilationUnit.AttributeLists.Any() && compilationUnit.Members.Count == 1 && namespaceCount == 1; string usingsIndentation; if (moveInsideNamespace) { var rootNamespace = compilationUnit.Members.OfType <NamespaceDeclarationSyntax>().First(); var indentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, rootNamespace); usingsIndentation = IndentationHelper.GenerateIndentationString(indentationOptions, indentationLevel + 1); } else { usingsIndentation = string.Empty; } // - The strategy is to strip all using directive that are not inside a conditional directive and replace them later with a sorted list at the correct spot // - The using directives that are inside a conditional directive are replaced (in sorted order) on the spot. // - Conditional directives are not moved, as correctly parsing them is too tricky // - No using directives will be stripped when there are multiple namespaces. In that case everything is replaced on the spot. List <UsingDirectiveSyntax> stripList; var replaceMap = new Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax>(); // When there are multiple namespaces, do not move using statements outside of them, only sort. if (namespaceCount > 1) { BuildReplaceMapForNamespaces(usingsHelper, replaceMap, indentationOptions); stripList = new List <UsingDirectiveSyntax>(); } else { stripList = usingsHelper.GetContainedUsings(usingsHelper.RootSpan); } BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationOptions, usingsHelper.RootSpan); var usingSyntaxRewriter = new UsingSyntaxRewriter(stripList, replaceMap); var newSyntaxRoot = usingSyntaxRewriter.Visit(syntaxRoot); if (moveInsideNamespace) { newSyntaxRoot = AddUsingsToNamespace(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any()); } else if (namespaceCount <= 1) { newSyntaxRoot = AddUsingsToCompilationRoot(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any()); } newSyntaxRoot = ReAddFileHeader(syntaxRoot, newSyntaxRoot); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return(Task.FromResult(newDocument)); }
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 async Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode syntaxRoot, CancellationToken cancellationToken) { var fileHeader = GetFileHeader(syntaxRoot); var compilationUnit = (CompilationUnitSyntax)syntaxRoot; var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var indentationOptions = IndentationOptions.FromDocument(document); var usingsHelper = new UsingsHelper(settings, semanticModel, compilationUnit, fileHeader); var namespaceCount = CountNamespaces(compilationUnit.Members); // Only move using declarations inside the namespace when // - There are no global attributes // - There is only a single namespace declared at the top level // - OrderingSettings.UsingDirectivesPlacement is set to InsideNamespace UsingDirectivesPlacement usingDirectivesPlacement; switch (settings.OrderingRules.UsingDirectivesPlacement) { case UsingDirectivesPlacement.InsideNamespace: if (compilationUnit.AttributeLists.Any() || compilationUnit.Members.Count > 1 || namespaceCount > 1) { // Override the user's setting with a more conservative one usingDirectivesPlacement = UsingDirectivesPlacement.Preserve; } else if (namespaceCount == 0) { usingDirectivesPlacement = UsingDirectivesPlacement.OutsideNamespace; } else { usingDirectivesPlacement = UsingDirectivesPlacement.InsideNamespace; } break; case UsingDirectivesPlacement.OutsideNamespace: usingDirectivesPlacement = UsingDirectivesPlacement.OutsideNamespace; break; case UsingDirectivesPlacement.Preserve: default: usingDirectivesPlacement = UsingDirectivesPlacement.Preserve; break; } string usingsIndentation; if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace) { var rootNamespace = compilationUnit.Members.OfType <NamespaceDeclarationSyntax>().First(); var indentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, rootNamespace); usingsIndentation = IndentationHelper.GenerateIndentationString(indentationOptions, indentationLevel + 1); } else { usingsIndentation = string.Empty; } // - The strategy is to strip all using directive that are not inside a conditional directive and replace them later with a sorted list at the correct spot // - The using directives that are inside a conditional directive are replaced (in sorted order) on the spot. // - Conditional directives are not moved, as correctly parsing them is too tricky // - No using directives will be stripped when there are multiple namespaces. In that case everything is replaced on the spot. List <UsingDirectiveSyntax> stripList; var replaceMap = new Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax>(); // When there are multiple namespaces, do not move using statements outside of them, only sort. if (usingDirectivesPlacement == UsingDirectivesPlacement.Preserve) { BuildReplaceMapForNamespaces(usingsHelper, replaceMap, indentationOptions, false); stripList = new List <UsingDirectiveSyntax>(); } else { stripList = usingsHelper.GetContainedUsings(usingsHelper.RootSpan); } BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationOptions, usingsHelper.RootSpan); var usingSyntaxRewriter = new UsingSyntaxRewriter(stripList, replaceMap, fileHeader); var newSyntaxRoot = usingSyntaxRewriter.Visit(syntaxRoot); if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace) { newSyntaxRoot = AddUsingsToNamespace(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any()); } else if (usingDirectivesPlacement == UsingDirectivesPlacement.OutsideNamespace) { newSyntaxRoot = AddUsingsToCompilationRoot(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any()); } // Final cleanup newSyntaxRoot = StripMultipleBlankLines(newSyntaxRoot); newSyntaxRoot = ReAddFileHeader(newSyntaxRoot, fileHeader); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return(newDocument); }
private SyntaxNode ReformatElement(SyntaxNode syntaxRoot, SyntaxNode element, SyntaxToken openBraceToken, SyntaxToken closeBraceToken, IndentationOptions indentationOptions) { var tokenSubstitutions = new Dictionary <SyntaxToken, SyntaxToken>(); var parentLastToken = openBraceToken.GetPreviousToken(); var parentEndLine = parentLastToken.GetLineSpan().EndLinePosition.Line; var blockStartLine = openBraceToken.GetLineSpan().StartLinePosition.Line; // reformat parent if it is on the same line as the block. if (parentEndLine == blockStartLine) { var newTrailingTrivia = parentLastToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); tokenSubstitutions.Add(parentLastToken, parentLastToken.WithTrailingTrivia(newTrailingTrivia)); } var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, element); var indentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel); var contentIndentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel + 1); // reformat opening brace tokenSubstitutions.Add(openBraceToken, this.FormatBraceToken(openBraceToken, indentationString)); // reformat start of content var startOfContentToken = openBraceToken.GetNextToken(); if (startOfContentToken != closeBraceToken) { var newStartOfContentTokenLeadingTrivia = startOfContentToken.LeadingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(contentIndentationString)); tokenSubstitutions.Add(startOfContentToken, startOfContentToken.WithLeadingTrivia(newStartOfContentTokenLeadingTrivia)); } // reformat end of content var endOfContentToken = closeBraceToken.GetPreviousToken(); if (endOfContentToken != openBraceToken) { var newEndOfContentTokenTrailingTrivia = endOfContentToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); // check if the token already exists (occurs when there is only one token in the block) if (tokenSubstitutions.ContainsKey(endOfContentToken)) { tokenSubstitutions[endOfContentToken] = tokenSubstitutions[endOfContentToken].WithTrailingTrivia(newEndOfContentTokenTrailingTrivia); } else { tokenSubstitutions.Add(endOfContentToken, endOfContentToken.WithTrailingTrivia(newEndOfContentTokenTrailingTrivia)); } } // reformat closing brace tokenSubstitutions.Add(closeBraceToken, this.FormatBraceToken(closeBraceToken, indentationString)); var rewriter = new TokenRewriter(tokenSubstitutions); var newSyntaxRoot = rewriter.Visit(syntaxRoot); return(newSyntaxRoot); }