private static Task<Document> GetTransformedDocumentAsync(CodeFixContext context, SyntaxNode syntaxRoot, SyntaxNode node, SyntaxTriviaList leadingTrivia) { var newTriviaList = leadingTrivia; newTriviaList = newTriviaList.Insert(0, SyntaxFactory.CarriageReturnLineFeed); var newNode = node.WithLeadingTrivia(newTriviaList); var newSyntaxRoot = syntaxRoot.ReplaceNode(node, newNode); var newDocument = context.Document.WithSyntaxRoot(newSyntaxRoot); return Task.FromResult(newDocument); }
public Task<SyntaxNode> ProcessAsync(Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken) { var leadingTrivia = syntaxNode.GetLeadingTrivia(); SyntaxTriviaList newTrivia = leadingTrivia; var illegalHeaders = GetIllegalHeaders(document); // We also want to add the filename (without path but with extension) to this list. // because we are mutating the list, once we remove a header, we won't remove any others... for (int idx = 0; idx < illegalHeaders.Length; idx++) { var illegalHeader = illegalHeaders[idx]; foreach (var trivia in newTrivia) { // If we have an illegal header here... if (trivia.ToFullString().IndexOf(illegalHeader, StringComparison.OrdinalIgnoreCase) >= 0) { if (trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)) { // For multiline comment trivia we need to process them line by line and remove all the illegal headers. // We then need to re-create the multiline comment and append it to the list. var modifiedTrivia = RemoveIllegalHeadersFromMultilineComment(newTrivia, trivia, illegalHeader); // We need to go back and re-try the current illegal header if we have modified the multiline trivia. if (modifiedTrivia != newTrivia) { newTrivia = modifiedTrivia; idx--; } break; } else { var index = newTrivia.IndexOf(trivia); newTrivia = RemoveTriviaAtIndex(newTrivia, index); // We need to re-try the current illegal header to make sure there are no other comments containing it // further down the trivia list idx--; break; } } } } if (leadingTrivia.Equals(newTrivia)) return Task.FromResult(syntaxNode); return Task.FromResult(syntaxNode.WithLeadingTrivia(newTrivia)); }
public static SyntaxNode WithLeadingComments(this SyntaxGenerator @this, SyntaxNode node, string comments, Language language) { comments = comments .Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None) .Select(x => language == Language.CSharp ? "// " + x : "' " + x) .Aggregate(new StringBuilder(), (sb, next) => sb.AppendLine(next), x => x.ToString()); node = node.WithLeadingTrivia( language == Language.CSharp ? SyntaxFactory.ParseLeadingTrivia(comments) : VB.SyntaxFactory.ParseLeadingTrivia(comments)); return node; }
public SyntaxNode Process(SyntaxNode syntaxNode, string languageName) { // SetHeaders if (!SetHeaders()) return syntaxNode; var triviaList = syntaxNode.GetLeadingTrivia(); SyntaxTrivia start; SyntaxTrivia end; if (!TryGetStartAndEndOfXmlHeader(triviaList, out start, out end)) return syntaxNode; var filteredList = Filter(triviaList, start, end); return syntaxNode.WithLeadingTrivia(filteredList); }
public override SyntaxNode Visit(SyntaxNode node) { node = base.Visit(node); if (node == null) { return null; } var needsRewrite = node.HasLeadingTrivia && node.GetLeadingTrivia().Any( y => y.Kind() == SyntaxKind.SingleLineCommentTrivia && !y.IsDirective && !y.ContainsDiagnostics); if (!needsRewrite) { return node; } return node.WithLeadingTrivia(this.FixCommentWhitespace(node.GetLeadingTrivia())); }
private SyntaxNode AddCopyrightHeader(SyntaxNode syntaxNode) { var list = new List<SyntaxTrivia>(); foreach (var headerLine in _header) { list.Add(CreateLineComment(headerLine)); list.Add(CreateNewLine()); } list.Add(CreateNewLine()); var triviaList = RemoveExistingHeader(syntaxNode.GetLeadingTrivia()); var i = 0; MovePastBlankLines(triviaList, ref i); while (i < triviaList.Count) { list.Add(triviaList[i]); i++; } return syntaxNode.WithLeadingTrivia(CreateTriviaList(list)); }
private static SyntaxNode CommentLine(SyntaxNode nodeLine) { return nodeLine.WithLeadingTrivia(nodeLine.GetLeadingTrivia().Add(SyntaxFactory.Comment("//"))); }
private SyntaxNode ApplyDocComment(SyntaxNode node, string docCommentId) { if (docCommentId == null) return node; // Look up the comment text string docCommentText = GetDocCommentForId(docCommentId); // Get the SyntaxTrivia for the comment SyntaxTree newTree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(docCommentText); var newTrivia = newTree.GetRoot().GetLeadingTrivia(); if (node.HasLeadingTrivia) { SyntaxTriviaList triviaList = node.GetLeadingTrivia(); // Check to see if there are any existing doc comments var docComments = triviaList .Where(n => n.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) || n.IsKind(SyntaxKind.MultiLineDocumentationCommentTrivia)) .Select(t => t.GetStructure()) .OfType<DocumentationCommentTriviaSyntax>() .ToList(); // Append the doc comment (even if the API already has /// comments) node = node.InsertTriviaBefore(triviaList.First(), newTrivia); } else // no leading trivia { node = node.WithLeadingTrivia(newTrivia); } return node.WithAdditionalAnnotations(Simplifier.Annotation); }
private SyntaxNode ApplyDocComment(SyntaxNode node, string docCommentId) { if (!_lookup.ContainsKey(docCommentId)) { return node; } var simplifiedTrivia = _lookup[docCommentId]; return node.WithLeadingTrivia(simplifiedTrivia); }
private static SyntaxNode ReplaceHeader(Document document, SyntaxNode root, StyleCopSettings settings) { // Skip single line comments, whitespace, and end of line trivia until a blank line is encountered. SyntaxTriviaList trivia = root.GetLeadingTrivia(); bool onBlankLine = false; while (trivia.Any()) { bool done = false; switch (trivia[0].Kind()) { case SyntaxKind.SingleLineCommentTrivia: trivia = trivia.RemoveAt(0); onBlankLine = false; break; case SyntaxKind.WhitespaceTrivia: trivia = trivia.RemoveAt(0); break; case SyntaxKind.EndOfLineTrivia: trivia = trivia.RemoveAt(0); if (onBlankLine) { done = true; } else { onBlankLine = true; } break; default: done = true; break; } if (done) { break; } } string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); return root.WithLeadingTrivia(CreateNewHeader(document.Name, settings, newLineText).Add(SyntaxFactory.CarriageReturnLineFeed).Add(SyntaxFactory.CarriageReturnLineFeed).AddRange(trivia)); }
public SyntaxNode TraverseAndConvert(SyntaxNode node, SyntaxNode newNode) { // Step 1: Handle current node // Find out if this node is a documentable API declaration // If not, skip to go to the child nodes. string docCommentId = GetAPIForNode(node); if (docCommentId != null) { // Look up the comment text string docCommentText = GetDocCommentForId(docCommentId); // Get the SyntaxTrivia for the comment SyntaxTree newTree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(docCommentText); var newTrivia = newTree.GetRoot().GetLeadingTrivia(); // Read a doc comment from a syntax tree. //var classNode = (ClassDeclarationSyntax)newTree.GetRoot().ChildNodes().First(); //var newTrivia = classNode.GetLeadingTrivia(); //var docCommentTrivia = newTrivia.Single(t => t.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia || // t.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia); // Find out if there is an existing comment or doc comment if (node.HasLeadingTrivia) { SyntaxTriviaList triviaList = node.GetLeadingTrivia(); SyntaxTrivia firstComment = triviaList.Last(); foreach (var trivia in triviaList.Reverse()) { SyntaxKind kind = trivia.Kind(); switch (kind) { case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.MultiLineCommentTrivia: // Found existing comment firstComment = trivia; break; case SyntaxKind.MultiLineDocumentationCommentTrivia: case SyntaxKind.SingleLineDocumentationCommentTrivia: // Found existing XML doc comment firstComment = trivia; break; default: break; } } // Append the doc comment newNode = node.InsertTriviaBefore(firstComment, newTrivia); } else // no leading trivia { newNode = node.WithLeadingTrivia(newTrivia); } } else // not an API node { newNode = node; } if (node.ChildNodes().Count() > 0) { newNode = newNode.ReplaceNodes(newNode.ChildNodes(), TraverseAndConvert); } return newNode; }
private static Document InsertInheritdocComment(Document document, Diagnostic diagnostic, SyntaxNode root, SyntaxNode syntaxNode, CancellationToken cancellationToken) { SyntaxTriviaList leadingTrivia = syntaxNode.GetLeadingTrivia(); int insertionIndex = leadingTrivia.Count; while (insertionIndex > 0 && !leadingTrivia[insertionIndex - 1].HasBuiltinEndLine()) { insertionIndex--; } string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var documentationComment = XmlSyntaxFactory.DocumentationComment( newLineText, XmlSyntaxFactory.EmptyElement(XmlCommentHelper.InheritdocXmlTag)); var trivia = SyntaxFactory.Trivia(documentationComment); SyntaxTriviaList newLeadingTrivia = leadingTrivia.Insert(insertionIndex, trivia); SyntaxNode newElement = syntaxNode.WithLeadingTrivia(newLeadingTrivia); return document.WithSyntaxRoot(root.ReplaceNode(syntaxNode, newElement)); }
private static SyntaxNode ReplaceWellFormedMultiLineCommentHeader(Document document, SyntaxNode root, StyleCopSettings settings, int commentIndex, XmlFileHeader header) { SyntaxTriviaList trivia = root.GetLeadingTrivia(); var commentTrivia = trivia[commentIndex]; // Is the comment pushed in by a prefix? var commentIndentation = string.Empty; if (commentIndex > 0) { var prefixTrivia = trivia[commentIndex - 1]; if (prefixTrivia.IsKind(SyntaxKind.WhitespaceTrivia)) { commentIndentation = prefixTrivia.ToFullString(); } } var triviaString = commentTrivia.ToFullString(); var startIndex = triviaString.IndexOf("/*", StringComparison.Ordinal) + 2; var endIndex = triviaString.LastIndexOf("*/", StringComparison.Ordinal); var commentContext = triviaString.Substring(startIndex, endIndex - startIndex).Trim(' ', '\t').TrimEnd(); var triviaStringParts = commentContext.Replace("\r\n", "\n").Split('\n'); // Assume we have comments that have a leading * string interlinePadding = " *"; int minExpectedLength = (commentIndentation + interlinePadding).Length; string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); // Examine second line to see if we should have stars or not if it's blank // set the interline padding to be blank also. if ((triviaStringParts.Length > 2) && (triviaStringParts[1].Length > minExpectedLength) && string.IsNullOrWhiteSpace(triviaStringParts[1].Substring(0, minExpectedLength))) { interlinePadding = " "; } // Pad line that used to be next to a /* triviaStringParts[0] = commentIndentation + interlinePadding + " " + triviaStringParts[0]; StringBuilder sb = StringBuilderPool.Allocate(); var copyrightText = commentIndentation + interlinePadding + " " + GetCopyrightText(commentIndentation + interlinePadding, settings.DocumentationRules.CopyrightText, newLineText); var newHeader = WrapInXmlComment(commentIndentation + interlinePadding, copyrightText, document.Name, settings, newLineText); sb.Append(commentIndentation); sb.Append("/*"); if (header.GetElement("copyright") == null) { // No copyright element at the moment so add us. sb.Append(newHeader.Substring(minExpectedLength)); sb.Append(newLineText); // Append the original stuff foreach (var oldLine in triviaStringParts) { sb.Append(oldLine.TrimEnd()); sb.Append(newLineText); } } else { bool firstLine = true; bool inCopyright = false; foreach (var oldLine in triviaStringParts) { var openingTag = oldLine.Contains("<copyright "); var closingTag = oldLine.Contains("</copyright>") || (openingTag && oldLine.Trim().EndsWith("/>")); if (openingTag) { inCopyright = !closingTag; sb.Append(newHeader.Substring(firstLine ? minExpectedLength : 0)); sb.Append(newLineText); } if (inCopyright) { inCopyright = !closingTag; } else { sb.Append(oldLine.Substring(firstLine ? minExpectedLength : 0)); sb.Append(newLineText); } firstLine = false; } } sb.Append(commentIndentation); sb.Append(" */"); // Get rid of any trailing spaces. var lines = sb.ToString().Split(new string[] { newLineText }, StringSplitOptions.None); sb.Clear(); for (int i = 0; i < lines.Length; i++) { sb.Append((i == 0 ? string.Empty : newLineText) + lines[i].TrimEnd()); } var newTrivia = SyntaxFactory.SyntaxTrivia(SyntaxKind.MultiLineCommentTrivia, StringBuilderPool.ReturnAndFree(sb)); return root.WithLeadingTrivia(trivia.Replace(commentTrivia, newTrivia)); }
private static SyntaxNode AddHeader(SyntaxNode root, string name, StyleCopSettings settings) { var newTrivia = CreateNewHeader(name, settings).Add(SyntaxFactory.CarriageReturnLineFeed).Add(SyntaxFactory.CarriageReturnLineFeed); newTrivia = newTrivia.AddRange(root.GetLeadingTrivia()); return root.WithLeadingTrivia(newTrivia); }
private static SyntaxNode AddHeader(Document document, SyntaxNode root, string name, StyleCopSettings settings) { string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var newLineTrivia = SyntaxFactory.EndOfLine(newLineText); var newTrivia = CreateNewHeader("//", name, settings, newLineText).Add(newLineTrivia).Add(newLineTrivia); newTrivia = newTrivia.AddRange(root.GetLeadingTrivia()); return root.WithLeadingTrivia(newTrivia); }
protected override SyntaxNode InsertAttributeListIntoContainer(int index, SyntaxNode list, SyntaxNode container) { // If the attribute list is being inserted at the first index and the container is not the compilation unit, copy leading trivia // to the list that is being inserted. if (index == 0 && !(container is CompilationUnitSyntax)) { var firstToken = container.GetFirstToken(); if (firstToken.HasLeadingTrivia) { var trivia = firstToken.LeadingTrivia; container = container.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(SyntaxTriviaList.Empty)); list = list.WithLeadingTrivia(trivia); } } if (container is CompilationUnitSyntax) { var compilationUnit = (CompilationUnitSyntax)container; var newAttributeLists = compilationUnit.AttributeLists.Insert(index, (AttributeListSyntax)list); return compilationUnit.WithAttributeLists(newAttributeLists); } else if (container is EnumDeclarationSyntax) { var enumDeclaration = (EnumDeclarationSyntax)container; var newAttributeLists = enumDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return enumDeclaration.WithAttributeLists(newAttributeLists); } else if (container is ClassDeclarationSyntax) { var classDeclaration = (ClassDeclarationSyntax)container; var newAttributeLists = classDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return classDeclaration.WithAttributeLists(newAttributeLists); } else if (container is StructDeclarationSyntax) { var structDeclaration = (StructDeclarationSyntax)container; var newAttributeLists = structDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return structDeclaration.WithAttributeLists(newAttributeLists); } else if (container is InterfaceDeclarationSyntax) { var interfaceDeclaration = (InterfaceDeclarationSyntax)container; var newAttributeLists = interfaceDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return interfaceDeclaration.WithAttributeLists(newAttributeLists); } else if (container is MethodDeclarationSyntax) { var method = (MethodDeclarationSyntax)container; var newAttributeLists = method.AttributeLists.Insert(index, (AttributeListSyntax)list); return method.WithAttributeLists(newAttributeLists); } else if (container is OperatorDeclarationSyntax) { var operationDeclaration = (OperatorDeclarationSyntax)container; var newAttributeLists = operationDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return operationDeclaration.WithAttributeLists(newAttributeLists); } else if (container is ConversionOperatorDeclarationSyntax) { var conversion = (ConversionOperatorDeclarationSyntax)container; var newAttributeLists = conversion.AttributeLists.Insert(index, (AttributeListSyntax)list); return conversion.WithAttributeLists(newAttributeLists); } else if (container is ConstructorDeclarationSyntax) { var constructor = (ConstructorDeclarationSyntax)container; var newAttributeLists = constructor.AttributeLists.Insert(index, (AttributeListSyntax)list); return constructor.WithAttributeLists(newAttributeLists); } else if (container is DestructorDeclarationSyntax) { var destructor = (DestructorDeclarationSyntax)container; var newAttributeLists = destructor.AttributeLists.Insert(index, (AttributeListSyntax)list); return destructor.WithAttributeLists(newAttributeLists); } else if (container is PropertyDeclarationSyntax) { var property = (PropertyDeclarationSyntax)container; var newAttributeLists = property.AttributeLists.Insert(index, (AttributeListSyntax)list); return property.WithAttributeLists(newAttributeLists); } else if (container is EventDeclarationSyntax) { var eventDeclaration = (EventDeclarationSyntax)container; var newAttributeLists = eventDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return eventDeclaration.WithAttributeLists(newAttributeLists); } else if (container is IndexerDeclarationSyntax) { var indexer = (IndexerDeclarationSyntax)container; var newAttributeLists = indexer.AttributeLists.Insert(index, (AttributeListSyntax)list); return indexer.WithAttributeLists(newAttributeLists); } else if (container is FieldDeclarationSyntax) { var field = (FieldDeclarationSyntax)container; var newAttributeLists = field.AttributeLists.Insert(index, (AttributeListSyntax)list); return field.WithAttributeLists(newAttributeLists); } else if (container is EventFieldDeclarationSyntax) { var eventFieldDeclaration = (EventFieldDeclarationSyntax)container; var newAttributeLists = eventFieldDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return eventFieldDeclaration.WithAttributeLists(newAttributeLists); } else if (container is DelegateDeclarationSyntax) { var delegateDeclaration = (DelegateDeclarationSyntax)container; var newAttributeLists = delegateDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list); return delegateDeclaration.WithAttributeLists(newAttributeLists); } else if (container is EnumMemberDeclarationSyntax) { var member = (EnumMemberDeclarationSyntax)container; var newAttributeLists = member.AttributeLists.Insert(index, (AttributeListSyntax)list); return member.WithAttributeLists(newAttributeLists); } else if (container is ParameterSyntax) { var parameter = (ParameterSyntax)container; var newAttributeLists = parameter.AttributeLists.Insert(index, (AttributeListSyntax)list); return parameter.WithAttributeLists(newAttributeLists); } else if (container is VariableDeclaratorSyntax || container is VariableDeclarationSyntax) { return InsertAttributeListIntoContainer(index, list, container.Parent); } throw Exceptions.ThrowEUnexpected(); }
private static SyntaxNode ReplaceHeader(Document document, SyntaxNode root, StyleCopSettings settings, bool isMalformedHeader) { // If the header is well formed Xml then we parse out the copyright otherwise // Skip single line comments, whitespace, and end of line trivia until a blank line is encountered. SyntaxTriviaList trivia = root.GetLeadingTrivia(); bool onBlankLine = false; bool inCopyright = isMalformedHeader; int? copyrightTriviaIndex = null; var removalList = new System.Collections.Generic.List<int>(); var leadingSpaces = string.Empty; string possibleLeadingSpaces = string.Empty; // Need to do this with index so we get the line endings correct. for (int i = 0; i < trivia.Count; i++) { var triviaLine = trivia[i]; bool done = false; switch (triviaLine.Kind()) { case SyntaxKind.SingleLineCommentTrivia: if (possibleLeadingSpaces != string.Empty) { leadingSpaces = possibleLeadingSpaces; } if (!isMalformedHeader) { var openingTag = triviaLine.ToFullString().Contains("<copyright "); var closingTag = triviaLine.ToFullString().Contains("</copyright>") || (openingTag && triviaLine.ToFullString().Trim().EndsWith("/>")); if (openingTag) { inCopyright = !closingTag; copyrightTriviaIndex = i; } else if (inCopyright) { removalList.Add(i); inCopyright = !closingTag; } } else { removalList.Add(i); } onBlankLine = false; break; case SyntaxKind.WhitespaceTrivia: if (leadingSpaces == string.Empty) { possibleLeadingSpaces = triviaLine.ToFullString(); } if (inCopyright) { removalList.Add(i); } break; case SyntaxKind.EndOfLineTrivia: if (inCopyright) { removalList.Add(i); } if (onBlankLine) { done = true; } else { onBlankLine = true; } break; default: done = true; break; } if (done) { break; } } // Remove copyright lines in reverse order. for (int i = removalList.Count - 1; i >= 0; i--) { trivia = trivia.RemoveAt(removalList[i]); } string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var newLineTrivia = SyntaxFactory.EndOfLine(newLineText); var newHeaderTrivia = CreateNewHeader(leadingSpaces + "//", document.Name, settings, newLineText); if (!isMalformedHeader && copyrightTriviaIndex.HasValue) { // Does the copyright element have leading whitespace? If so remove it. if ((copyrightTriviaIndex.Value > 0) && trivia[copyrightTriviaIndex.Value - 1].IsKind(SyntaxKind.WhitespaceTrivia)) { copyrightTriviaIndex = copyrightTriviaIndex - 1; trivia = trivia.RemoveAt(copyrightTriviaIndex.Value); } // Replace copyright element in place. return root.WithLeadingTrivia(trivia.ReplaceRange(trivia[copyrightTriviaIndex.Value], newHeaderTrivia)); } else { // Add blank line if we don't already have comments at top of file. if (!FirstLineIsComment(trivia)) { newHeaderTrivia = newHeaderTrivia.Add(newLineTrivia); } // Insert header at top of the file. return root.WithLeadingTrivia(newHeaderTrivia.Add(newLineTrivia).AddRange(trivia)); } }
private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, SyntaxNode node) { SyntaxNode newSyntaxRoot = root; Debug.Assert(!node.HasLeadingTrivia, "The trivia should be trailing trivia of the previous node"); SyntaxNode newNode = node.WithLeadingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed); newSyntaxRoot = newSyntaxRoot.ReplaceNode(node, newNode); return Task.FromResult(document.WithSyntaxRoot(newSyntaxRoot)); }