public async Task<Solution> EnforceAsync(Document document) { if (document == null) { throw new ArgumentNullException(nameof(document)); } IReadOnlyList<string> headerComments = document.GetOption(HeaderComments); string newLineText = document.GetOption(GlobalOptions.NewLineText); SyntaxTriviaList commentTrivia = this.commentCache.GetOrAdd( headerComments, c => BuildCommentTrivia(headerComments, newLineText)); SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); if (syntaxRoot.HasLeadingTrivia) { SyntaxTriviaList leadingTrivia = syntaxRoot.GetLeadingTrivia(); if (!leadingTrivia.IsEquivalentTo(commentTrivia)) { Log.WriteInformation("{0}: Rewriting non-conforming header comment", document.Name); syntaxRoot = syntaxRoot.WithLeadingTrivia().WithLeadingTrivia(commentTrivia); document = document.WithSyntaxRoot(syntaxRoot); } } else if (commentTrivia.Count > 0) { Log.WriteInformation("{0}: Adding missing header comment", document.Name); syntaxRoot = syntaxRoot.WithLeadingTrivia(commentTrivia); document = document.WithSyntaxRoot(syntaxRoot); } return document.Project.Solution; }
public async static Task<Solution> MakeAutoPropertyAsync(Document document, SyntaxNode root, PropertyDeclarationSyntax property, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var getterReturn = (ReturnStatementSyntax)property.AccessorList.Accessors.First(a => a.Keyword.ValueText == "get").Body.Statements.First(); var returnIdentifier = (IdentifierNameSyntax)(getterReturn.Expression is MemberAccessExpressionSyntax ? ((MemberAccessExpressionSyntax)getterReturn.Expression).Name : getterReturn.Expression); var returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; var variableDeclarator = (VariableDeclaratorSyntax)returnIdentifierSymbol.DeclaringSyntaxReferences.First().GetSyntax(); var fieldDeclaration = variableDeclarator.FirstAncestorOfType<FieldDeclarationSyntax>(); root = root.TrackNodes(returnIdentifier, fieldDeclaration, property); document = document.WithSyntaxRoot(root); root = await document.GetSyntaxRootAsync(cancellationToken); semanticModel = await document.GetSemanticModelAsync(cancellationToken); returnIdentifier = root.GetCurrentNode(returnIdentifier); returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; var newProperty = GetSimpleProperty(property, variableDeclarator) .WithTriviaFrom(property) .WithAdditionalAnnotations(Formatter.Annotation); var newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, returnIdentifierSymbol, property.Identifier.ValueText, document.Project.Solution.Workspace.Options, cancellationToken); document = newSolution.GetDocument(document.Id); root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); root = root.InsertNodesAfter(root.GetCurrentNode(property), new[] { newProperty }); var multipleVariableDeclaration = fieldDeclaration.Declaration.Variables.Count > 1; if (multipleVariableDeclaration) { var newfieldDeclaration = fieldDeclaration.WithDeclaration(fieldDeclaration.Declaration.RemoveNode(variableDeclarator, SyntaxRemoveOptions.KeepNoTrivia)); root = root.RemoveNode(root.GetCurrentNode<SyntaxNode>(property), SyntaxRemoveOptions.KeepNoTrivia); root = root.ReplaceNode(root.GetCurrentNode(fieldDeclaration), newfieldDeclaration); } else { root = root.RemoveNodes(root.GetCurrentNodes<SyntaxNode>(new SyntaxNode[] { fieldDeclaration, property }), SyntaxRemoveOptions.KeepNoTrivia); } document = document.WithSyntaxRoot(root); return document.Project.Solution; }
static async Task<Document> Fix(Document document, AwaitExpressionSyntax node, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var expression = Checker.FindExpressionForConfigureAwait(node); if (expression != null) { if (!Checker.IsConfigureAwait(expression.Expression)) { var falseExpression = SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression); var newExpression = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, expression, SyntaxFactory.IdentifierName(Checker.ConfigureAwaitIdentifier)), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(falseExpression) }))); return document.WithSyntaxRoot(root.ReplaceNode(expression, newExpression.WithAdditionalAnnotations(Formatter.Annotation))); } if (!Checker.HasFalseArgument(expression.ArgumentList)) { var falseExpression = SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression); var newExpression = SyntaxFactory.InvocationExpression(expression.Expression, SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(falseExpression) }))); return document.WithSyntaxRoot(root.ReplaceNode(expression, newExpression.WithAdditionalAnnotations(Formatter.Annotation))); } } else { var falseExpression = SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression); var newExpression = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, node.Expression, SyntaxFactory.IdentifierName(Checker.ConfigureAwaitIdentifier)), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(falseExpression) }))); return document.WithSyntaxRoot(root.ReplaceNode(node.Expression, newExpression.WithAdditionalAnnotations(Formatter.Annotation))); } throw new InvalidOperationException(); }
private async static Task<Document> UseEmptyStringAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var literal = root.FindNode(diagnostic.Location.SourceSpan).DescendantNodesAndSelf().OfType<MemberAccessExpressionSyntax>().First(); var newRoot = root.ReplaceNode(literal, SyntaxFactory.ParseExpression(EmptyString).WithLeadingTrivia(literal.GetLeadingTrivia()).WithTrailingTrivia(literal.GetTrailingTrivia())); var newDocument = document.WithSyntaxRoot(newRoot); return document.WithSyntaxRoot(newRoot); }
public async static Task<Document> IntroduceFieldFromConstructorDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var diagnosticSpan = diagnostic.Location.SourceSpan; var parameter = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<ParameterSyntax>().First(); var constructor = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<ConstructorDeclarationSyntax>().First(); var newRoot = IntroduceFieldFromConstructor(root, constructor, parameter); var newDocument = document.WithSyntaxRoot(newRoot); return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic) { var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); var node = syntaxRoot?.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true); if (node != null && node.IsKind(SyntaxKind.RegionDirectiveTrivia)) { var regionDirective = node as RegionDirectiveTriviaSyntax; var newSyntaxRoot = syntaxRoot.RemoveNodes(regionDirective.GetRelatedDirectives(), SyntaxRemoveOptions.AddElasticMarker); return document.WithSyntaxRoot(newSyntaxRoot); } return document.WithSyntaxRoot(syntaxRoot); }
private static async Task<Document> CallAsExtensionAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var diagnosticSpan = diagnostic.Location.SourceSpan; var staticInvocationExpression = root .FindToken(diagnosticSpan.Start) .Parent.AncestorsAndSelf() .OfType<InvocationExpressionSyntax>() .First(); var childNodes = staticInvocationExpression.ChildNodes(); var parameterExpressions = CallExtensionMethodAsExtensionAnalyzer.GetParameterExpressions(childNodes); var firstArgument = parameterExpressions.FirstOrDefault(); var callerMethod = childNodes.OfType<MemberAccessExpressionSyntax>().FirstOrDefault(); root = ReplaceStaticCallWithExtionMethodCall( root, staticInvocationExpression, firstArgument, callerMethod.Name, CallExtensionMethodAsExtensionAnalyzer.CreateArgumentListSyntaxFrom(parameterExpressions.Skip(1)) ).WithAdditionalAnnotations(Formatter.Annotation); var semanticModel = await document.GetSemanticModelAsync(); root = ImportNeededNamespace(root, semanticModel, callerMethod).WithAdditionalAnnotations(Formatter.Annotation); var newDocument = document.WithSyntaxRoot(root); return newDocument; }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var indentationOptions = IndentationOptions.FromDocument(document); var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var violatingTrivia = syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start); var stringBuilder = new StringBuilder(); var column = violatingTrivia.GetLineSpan().StartLinePosition.Character; foreach (var c in violatingTrivia.ToFullString()) { if (c == '\t') { var offsetWithinTabColumn = column % indentationOptions.TabSize; var spaceCount = indentationOptions.TabSize - offsetWithinTabColumn; stringBuilder.Append(' ', spaceCount); column += spaceCount; } else { stringBuilder.Append(c); column++; } } var newSyntaxRoot = syntaxRoot.ReplaceTrivia(violatingTrivia, SyntaxFactory.Whitespace(stringBuilder.ToString())); return document.WithSyntaxRoot(newSyntaxRoot); }
private static async Task<Document> RemoveUnreachableCodeAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindNode(diagnostic.Location.SourceSpan); var newDoc = document.WithSyntaxRoot(RemoveUnreachableStatement(root, node)); return newDoc; }
private async Task<Document> FormatXmlAsync(Document document, LiteralExpressionSyntax sleSyntax, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var tree = root.SyntaxTree; //Get the character position of the LiteralExpressionSyntax FileLinePositionSpan position = tree.GetLineSpan(sleSyntax.Span); int cSpace = position.StartLinePosition.Character; //Figure out the preceeding trivia since we can't get the column position from GetLineSpan var parentTrivia = sleSyntax.GetLeadingTrivia().ToFullString(); var xml = sleSyntax.GetFirstToken().ValueText; var newXmlText = FormatXml(xml); //Process each line of the formatted XML and prepend the parent trivia & spaces string[] xmlLines = newXmlText.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); for (int i = 1; i < xmlLines.Length; i++) { xmlLines[i] = parentTrivia + new String(' ', (cSpace + 2)) + xmlLines[i]; } newXmlText = String.Join("\r\n", xmlLines); var newXmlValue = "@\"" + newXmlText + "\""; var newNode = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Token(SyntaxTriviaList.Empty, SyntaxKind.StringLiteralToken, newXmlValue, newXmlText, SyntaxTriviaList.Empty)); var newRoot = root.ReplaceNode(sleSyntax, newNode); return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> DeleteDeclarationFromDocument(SyntaxNode node, Document curentDocument) { var root = await curentDocument.GetSyntaxRootAsync(); var newTypeDeclarationParent = node.Parent.RemoveNode(node, SyntaxRemoveOptions.KeepNoTrivia); var newRoot = root.ReplaceNode(node.Parent, newTypeDeclarationParent); return curentDocument.WithSyntaxRoot(newRoot); }
private async static Task<Document> RemoveThrowAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var sourceSpan = diagnostic.Location.SourceSpan; var finalizer = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType<DestructorDeclarationSyntax>().First(); return document.WithSyntaxRoot(root.RemoveNode(finalizer, SyntaxRemoveOptions.KeepNoTrivia)); }
private Task<Document> ConvertToInterpolatedString(Document document, SyntaxNode root, InvocationExpressionSyntax invocation, CancellationToken cancellationToken) { string previousString = null; var parts = new List<InterpolatedStringContentSyntax>(invocation.ArgumentList.Arguments.Count); for (int i = 0; i < invocation.ArgumentList.Arguments.Count; i++) { ArgumentSyntax argument = invocation.ArgumentList.Arguments[i]; var literal = argument.Expression as LiteralExpressionSyntax; if (literal?.IsKind(SyntaxKind.StringLiteralExpression) ?? false) { //strings needs to be collapsed, otherwise VS will insert additional whitespaces previousString += literal.Token.Text.Substring(1, literal.Token.Text.Length - 2); } else { if (previousString != null) { parts.Add(InterpolatedStringGenerator.TextPart(previousString)); previousString = null; } parts.Add(InterpolatedStringGenerator.ExpressionPart(argument.Expression.WithoutLeadingTrivia().WithoutTrailingTrivia())); } } if (previousString != null) { parts.Add(InterpolatedStringGenerator.TextPart(previousString)); } SyntaxNode interpolated = InterpolatedStringGenerator.InterpolatedString(parts); root = root.ReplaceNode(invocation, interpolated); return Task.FromResult(document.WithSyntaxRoot(root)); }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxToken token = root.FindToken(diagnostic.Location.SourceSpan.Start); var replacements = new List<SyntaxToken>(2); if (!token.IsFirstInLine()) { SyntaxToken precedingToken = token.GetPreviousToken(); if (precedingToken.TrailingTrivia.Any(SyntaxKind.WhitespaceTrivia)) { replacements.Add(precedingToken); } } SyntaxTriviaList trailingTrivia = token.TrailingTrivia; if (!trailingTrivia.Any(SyntaxKind.EndOfLineTrivia) && trailingTrivia.Any(SyntaxKind.WhitespaceTrivia)) { replacements.Add(token); } if (replacements.Count == 0) { return document; } var transformed = root.ReplaceTokens(replacements, (original, maybeRewritten) => maybeRewritten.WithoutTrailingWhitespace().WithoutFormatting()); Document updatedDocument = document.WithSyntaxRoot(transformed); return updatedDocument; }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxToken originalToken = root.FindToken(diagnostic.Location.SourceSpan.Start); SyntaxTree tree = root.SyntaxTree; SourceText sourceText = await tree.GetTextAsync(cancellationToken).ConfigureAwait(false); TextLine sourceLine = sourceText.Lines.GetLineFromPosition(originalToken.SpanStart); string lineText = sourceText.ToString(sourceLine.Span); int indentLength; for (indentLength = 0; indentLength < lineText.Length; indentLength++) { if (!char.IsWhiteSpace(lineText[indentLength])) { break; } } IndentationOptions indentationOptions = IndentationOptions.FromDocument(document); SyntaxTriviaList newTrivia = SyntaxFactory.TriviaList( SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.Whitespace(lineText.Substring(0, indentLength) + IndentationHelper.GenerateIndentationString(indentationOptions, 1))); SyntaxToken updatedToken = originalToken.WithLeadingTrivia(originalToken.LeadingTrivia.AddRange(newTrivia)); SyntaxNode updatedRoot = root.ReplaceToken(originalToken, updatedToken); return document.WithSyntaxRoot(updatedRoot); }
private Task<Solution> MakePublicAsync(Document document, SyntaxNode root, MethodDeclarationSyntax method) { var generator = SyntaxGenerator.GetGenerator(document); var newMethod = generator.WithAccessibility(method, Accessibility.Public); var newRoot = root.ReplaceNode(method, newMethod); return Task.FromResult(document.WithSyntaxRoot(newRoot).Project.Solution); }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var accessorToken = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); var accessorList = (AccessorListSyntax)accessorToken.Parent.Parent; var firstAccesor = accessorList.Accessors[0]; var secondAccessor = accessorList.Accessors[1]; var trackedRoot = syntaxRoot.TrackNodes(firstAccesor, secondAccessor); var trackedFirstAccessor = trackedRoot.GetCurrentNode(firstAccesor); var newAccessor = GetNewAccessor(accessorList, firstAccesor, secondAccessor); syntaxRoot = trackedRoot.InsertNodesBefore(trackedFirstAccessor, new[] { newAccessor }); if (HasLeadingBlankLines(secondAccessor)) { trackedFirstAccessor = syntaxRoot.GetCurrentNode(firstAccesor); var newFirstAccessor = trackedFirstAccessor.WithLeadingTrivia(new[] { SyntaxFactory.CarriageReturnLineFeed }.Concat(firstAccesor.GetFirstToken().WithoutLeadingBlankLines().LeadingTrivia)); syntaxRoot = syntaxRoot.ReplaceNode(trackedFirstAccessor, newFirstAccessor); } var trackedLastAccessor = syntaxRoot.GetCurrentNode(secondAccessor); var keepTriviaOptions = AccessorsAreOnTheSameLine(firstAccesor, secondAccessor) ? SyntaxRemoveOptions.KeepEndOfLine : SyntaxRemoveOptions.KeepNoTrivia; syntaxRoot = syntaxRoot.RemoveNode(trackedLastAccessor, keepTriviaOptions); return document.WithSyntaxRoot(syntaxRoot); }
private static async Task<Document> RemoveEmptyStatementAsync(Document document, SyntaxNode root, EmptyStatementSyntax node, CancellationToken cancellationToken) { SyntaxNode newRoot; switch (node.Parent.Kind()) { case SyntaxKind.Block: case SyntaxKind.SwitchSection: // empty statements in a block or switch section can be removed return await RemoveSemicolonTextAsync(document, node.SemicolonToken, cancellationToken).ConfigureAwait(false); case SyntaxKind.IfStatement: case SyntaxKind.ElseClause: case SyntaxKind.ForStatement: case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: // these cases are always replaced with an empty block newRoot = root.ReplaceNode(node, SyntaxFactory.Block().WithTriviaFrom(node)); return document.WithSyntaxRoot(newRoot); case SyntaxKind.LabeledStatement: // handle this case as a text manipulation for simplicity return await RemoveSemicolonTextAsync(document, node.SemicolonToken, cancellationToken).ConfigureAwait(false); default: return document; } }
private static async Task<Document> ChangeToThenByAsync(Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(syntaxNode, SyntaxFactory.IdentifierName("ThenBy")); return document.WithSyntaxRoot(newRoot); }
private Task<Solution> UseExpressionBodiedMemberAsync(Document document, SyntaxNode root, SyntaxNode statement) { var returnStatement = (ReturnStatementSyntax) statement; var expression = returnStatement.Expression; var arrowClause = SyntaxFactory.ArrowExpressionClause(expression); var property = statement.AncestorsAndSelf().OfType<PropertyDeclarationSyntax>().FirstOrDefault(); if (property != null) { var newProperty = property.RemoveNode(property.AccessorList, SyntaxRemoveOptions.KeepNoTrivia) .WithExpressionBody(arrowClause) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); root = root.ReplaceNode(property, newProperty); } var method = statement.AncestorsAndSelf().OfType<MethodDeclarationSyntax>().FirstOrDefault(); if (method != null) { root = root.ReplaceNode(method, method.RemoveNode(method.Body, SyntaxRemoveOptions.KeepNoTrivia) .WithExpressionBody(arrowClause) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))); } return Task.FromResult(document.WithSyntaxRoot(root).Project.Solution); }
private static async Task<Document> RemoveRedundantComparisonAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var comparison = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent.AncestorsAndSelf().OfType<BinaryExpressionSyntax>().First(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); bool constValue; ExpressionSyntax replacer; var rightConst = semanticModel.GetConstantValue(comparison.Right); if (rightConst.HasValue) { constValue = (bool)rightConst.Value; replacer = comparison.Left; } else { var leftConst = semanticModel.GetConstantValue(comparison.Left); constValue = (bool)leftConst.Value; replacer = comparison.Right; } if ((!constValue && comparison.IsKind(SyntaxKind.EqualsExpression)) || (constValue && comparison.IsKind(SyntaxKind.NotEqualsExpression))) replacer = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, replacer); replacer = replacer.WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(comparison, replacer); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private static async Task<Document> RemoveTrailingWhiteSpaceAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var trivia = root.FindTrivia(diagnostic.Location.SourceSpan.End - 1); SyntaxNode newRoot; if (trivia.IsKind(SyntaxKind.WhitespaceTrivia)) { newRoot = root.ReplaceTrivia(trivia, new SyntaxTrivia[] { }); } else if (trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia, SyntaxKind.MultiLineDocumentationCommentTrivia)) { var commentText = trivia.ToFullString(); var commentLines = commentText.Split(new[] { Environment.NewLine }, StringSplitOptions.None); var newComment = ""; var builder = new System.Text.StringBuilder(); builder.Append(newComment); for (int i = 0; i < commentLines.Length; i++) { var commentLine = commentLines[i]; builder.Append(Regex.Replace(commentLine, @"\s+$", "")); if (i < commentLines.Length - 1) builder.Append(Environment.NewLine); } newComment = builder.ToString(); newRoot = root.ReplaceTrivia(trivia, SyntaxFactory.SyntaxTrivia(SyntaxKind.DocumentationCommentExteriorTrivia, newComment)); } else { var triviaNoTrailingWhiteSpace = Regex.Replace(trivia.ToFullString(), @"\s+$", ""); newRoot = root.ReplaceTrivia(trivia, SyntaxFactory.ParseTrailingTrivia(triviaNoTrailingWhiteSpace)); } return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxToken token = root.FindToken(diagnostic.Location.SourceSpan.Start); if (!token.IsKind(SyntaxKind.CloseBracketToken)) { return document; } if (token.IsFirstInLine()) { return document; } SyntaxToken precedingToken = token.GetPreviousToken(); if (!precedingToken.TrailingTrivia.Any(SyntaxKind.WhitespaceTrivia)) { return document; } SyntaxToken corrected = precedingToken.WithoutTrailingWhitespace().WithoutFormatting(); SyntaxNode transformed = root.ReplaceToken(precedingToken, corrected); Document updatedDocument = document.WithSyntaxRoot(transformed); return updatedDocument; }
private async Task<Document> MakeLambdaExpressionAsync(Document document, AnonymousMethodExpressionSyntax anonMethod, CancellationToken cancellationToken) { var parent = anonMethod.Parent; var parameterList = anonMethod.ParameterList != null ? anonMethod.ParameterList : SyntaxFactory.ParameterList(); SyntaxNode body; if (anonMethod.Block != null && anonMethod.Block.Statements.Count == 1) { body = anonMethod.Block.Statements.ElementAt(0).ChildNodes().ElementAt(0); } else if (anonMethod.Block != null) { body = anonMethod.Body; } else { body = SyntaxFactory.Block(); } var lambdaExpr = SyntaxFactory. ParenthesizedLambdaExpression(parameterList, (CSharpSyntaxNode)body); var newParent = parent.ReplaceNode(anonMethod, lambdaExpr); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = root.ReplaceNode(parent, newParent); return document.WithSyntaxRoot(newRoot); }
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, 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; }
public static async Task<Document> ReplaceNodeAsync(Document document, SyntaxNode @old, SyntaxNode @new, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(@old, @new); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); var triviaList = token.LeadingTrivia; var index = triviaList.Count - 1; while (!triviaList[index].IsKind(SyntaxKind.EndOfLineTrivia)) { index--; } var lastEndOfLine = index; while (!triviaList[index].IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)) { index--; } var lastDocumentation = index; var newLeadingTrivia = triviaList.Take(lastDocumentation + 1).Concat(triviaList.Skip(lastEndOfLine + 1)); var newSyntaxRoot = syntaxRoot.ReplaceToken(token, token.WithLeadingTrivia(newLeadingTrivia)); return document.WithSyntaxRoot(newSyntaxRoot); }
private static async Task<Document> AddConfigureAwaitAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken, bool continueOnCapturedContext) { SyntaxKind continueOnCapturedContextSyntax; switch (continueOnCapturedContext) { case true: continueOnCapturedContextSyntax = SyntaxKind.TrueLiteralExpression; break; default: continueOnCapturedContextSyntax = SyntaxKind.FalseLiteralExpression; break; } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var awaitExpression = (AwaitExpressionSyntax)root.FindNode(diagnostic.Location.SourceSpan); var expression = awaitExpression.Expression; var newExpression = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, expression, SyntaxFactory.IdentifierName(nameof(Task.ConfigureAwait))), SyntaxFactory.ArgumentList( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Argument( SyntaxFactory.LiteralExpression(continueOnCapturedContextSyntax))))); var newRoot = root.ReplaceNode(expression, newExpression); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
public async Task<Solution> EnforceAsync(Document document) { if (document == null) { throw new ArgumentNullException(nameof(document)); } // The compiler will actually do the heavy lifting for us on this one: when it generates the semantic model // it creates diagnostic notes for usings that are unused with the id "CS8019". SemanticModel semanticModel = await document.GetSemanticModelAsync(); IEnumerable<Diagnostic> diagnostics = semanticModel.GetDiagnostics().Where(d => d.Id == "CS8019"); // Save the leading trivia to reattach after we have removed the unused roots SyntaxNode oldRoot = await document.GetSyntaxRootAsync(); SyntaxTriviaList leadingTrivia = oldRoot.GetLeadingTrivia(); // Now we need to go through the diagnostics in reverse order (so we don't corrupt our spans), find the // relevant SyntaxNodes, and remove them. diagnostics = diagnostics.OrderByDescending(d => d.Location.SourceSpan.Start); SyntaxNode newRoot = oldRoot; foreach (Diagnostic diagnostic in diagnostics) { newRoot = newRoot.RemoveNodes( newRoot.DescendantNodes(diagnostic.Location.SourceSpan), SyntaxRemoveOptions.KeepNoTrivia); } if (newRoot != oldRoot) { Log.WriteInformation("{0}: Removing unused usings", document.Name); document = document.WithSyntaxRoot(newRoot.WithLeadingTrivia(leadingTrivia)); } return document.Project.Solution; }
private Document CreateCodeFix(Document document, Diagnostic diagnostic, SyntaxNode syntaxRoot) { SyntaxNode newSyntaxRoot = syntaxRoot; var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan); var indentationOptions = IndentationOptions.FromDocument(document); switch (node.Kind()) { case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.EnumDeclaration: newSyntaxRoot = this.RegisterBaseTypeDeclarationCodeFix(syntaxRoot, (BaseTypeDeclarationSyntax)node, indentationOptions); break; case SyntaxKind.AccessorList: newSyntaxRoot = this.RegisterPropertyLikeDeclarationCodeFix(syntaxRoot, (BasePropertyDeclarationSyntax)node.Parent, indentationOptions); break; case SyntaxKind.Block: newSyntaxRoot = this.RegisterMethodLikeDeclarationCodeFix(syntaxRoot, (BaseMethodDeclarationSyntax)node.Parent, indentationOptions); break; case SyntaxKind.NamespaceDeclaration: newSyntaxRoot = this.RegisterNamespaceDeclarationCodeFix(syntaxRoot, (NamespaceDeclarationSyntax)node, indentationOptions); break; } return document.WithSyntaxRoot(newSyntaxRoot); }
private static async Task <Document> AddMigrationMethod(Document document, TypeDeclarationSyntax typeDecl, CancellationToken ct) { var semanticModel = await document.GetSemanticModelAsync(ct); var typeSymbol = semanticModel.GetDeclaredSymbol(typeDecl, ct); var latestMigrationMethod = MigrationHashHelper.GetMigrationMethods(typeSymbol).LastOrDefault(); var latestVersion = latestMigrationMethod?.ToVersion ?? 0; var dataArgumentTypeName = latestMigrationMethod?.ReturnType.Name ?? "JToken"; var method = GetMigrationMethod(latestVersion + 1, dataArgumentTypeName, ct); var typeDeclWithUpdatedMigrationHash = MigrationHashHelper.UpdateMigrationHash(typeDecl, ct, semanticModel); var typeDeclWithAddedMigrationMethod = AddMember(typeDeclWithUpdatedMigrationHash, method); var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(ct); var rootWithNewTypeDecl = root.ReplaceNode(typeDecl, typeDeclWithAddedMigrationMethod); return(document.WithSyntaxRoot(rootWithNewTypeDecl)); }
private static Task <Document> FixMissingStatic(Document contextDocument, SyntaxNode root, MethodDeclarationSyntax method) { return(Task.FromResult(contextDocument.WithSyntaxRoot(root.ReplaceNode(method, method.AddModifiers(Token(SyntaxKind.StaticKeyword)))))); }
private async System.Threading.Tasks.Task CommandCallbackAsync() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IWpfTextView textView = await ServiceProvider.GetWpfTextViewAsync(); if (textView == null) { return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; ITextSnapshotLine caretLine = caretPosition.GetContainingLine(); if (caretLine == null) { return; } Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } await TaskScheduler.Default; //Go to background thread SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); if (syntaxRoot == null || semanticModel == null) { return; } //TextSpan lineSpan = TextSpan.FromBounds(caretLine.Start.Position, caretLine.End.Position); //var memberNode = syntaxRoot.FindNode(lineSpan) as MemberDeclarationSyntax; // if (memberNode == null) // return; SyntaxNode fixedRoot; #region todo if (textView.Selection.IsActive && !textView.Selection.IsEmpty) // if has selection { // todo: check selection //// Find all nodes within the span and format them //var selectionSpan = TextSpan.FromBounds(textView.Selection.Start.Position, textView.Selection.End.Position); //SyntaxNode topNode = syntaxRoot.FindNode(selectionSpan); // can, return top node that intersects with selectionSpan, so we need SpanWalker here //if (topNode == null) // return; // nothing to format (e.g. selection contains only trivia) //var spanWalker = new SpanWalker(selectionSpan); //spanWalker.Visit(topNode); //if (spanWalker.NodesWithinSpan.Count == 0) // return; //fixedRoot = syntaxRoot.ReplaceNodes(spanWalker.NodesWithinSpan, (o, r) => formatter.Format(o, semanticModel)); } else { } #endregion fixedRoot = new AngleBracesBqlRewriter(semanticModel).Visit(syntaxRoot); var newDocument = document.WithSyntaxRoot(fixedRoot); SyntaxNode newSyntaxRoot = await newDocument.GetSyntaxRootAsync(); SemanticModel newSemanticModel = await newDocument.GetSemanticModelAsync(); if (newSyntaxRoot == null || newSemanticModel == null) { return; } // have to format, because cannot save all original indention BqlFormatter formatter = BqlFormatter.FromTextView(textView); var formatedRoot = formatter.Format(newSyntaxRoot, newSemanticModel); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // Return to UI thread if (!textView.TextBuffer.EditInProgress) { var formattedDocument = document.WithSyntaxRoot(formatedRoot); ApplyChanges(document, formattedDocument); } }
private static Task <Document> FixMissingPartial(Document contextDocument, SyntaxNode root, ClassDeclarationSyntax @class) { return(Task.FromResult(contextDocument.WithSyntaxRoot(root.ReplaceNode(@class, @class.AddModifiers(Token(SyntaxKind.PartialKeyword)))))); }