private static T RemoveNode <T>( T declaration, Func <T, SyntaxList <MemberDeclarationSyntax> > getMembers, int index, SyntaxRemoveOptions removeOptions) where T : SyntaxNode { SyntaxList <MemberDeclarationSyntax> members = getMembers(declaration); T newDeclaration = declaration.RemoveNode(members[index], removeOptions); if (index == 0 && index < members.Count - 1) { members = getMembers(newDeclaration); MemberDeclarationSyntax nextMember = members[index]; SyntaxTriviaList leadingTrivia = nextMember.GetLeadingTrivia(); SyntaxTrivia trivia = leadingTrivia.FirstOrDefault(); if (trivia.IsEndOfLineTrivia()) { MemberDeclarationSyntax newNextMember = nextMember.WithLeadingTrivia(leadingTrivia.RemoveAt(0)); newDeclaration = newDeclaration.ReplaceNode(nextMember, newNextMember); } } return(newDeclaration); }
private static SyntaxNode RemoveNode(MemberDeclarationSyntax member) { MemberDeclarationListInfo memberList = SyntaxInfo.MemberDeclarationListInfo(member.Parent); SyntaxList <MemberDeclarationSyntax> members = memberList.Members; MemberDeclarationListInfo newMemberList = memberList.RemoveNode(member, SyntaxRemoveOptions.KeepUnbalancedDirectives); int index = members.IndexOf(member); if (index == 0 && index < members.Count - 1) { MemberDeclarationSyntax nextMember = newMemberList[index]; SyntaxTriviaList leadingTrivia = nextMember.GetLeadingTrivia(); if (leadingTrivia.FirstOrDefault().IsEndOfLineTrivia()) { MemberDeclarationSyntax newNextMember = nextMember.WithLeadingTrivia(leadingTrivia.RemoveAt(0)); newMemberList = newMemberList.ReplaceNode(nextMember, newNextMember); } } return(newMemberList.Parent); }
/// <summary> ///Method to extract the Summary from the XML Documentation of a Property inside the SyntaxTree. ///To get the summary every Property must have an XML-Documentation of the form: <summary></summary> /// </summary> private string GetXMLSummary(SyntaxTriviaList trivias) { //Get XML-Trivia from Node var xmlCommentTrivia = trivias.FirstOrDefault(t => t.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia); var xml = xmlCommentTrivia.GetStructure(); if (xml == null) { return(""); } string xmlString = xml.ToString(); //Get summary from XML-String var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlString); XmlNodeList xnList = xmlDoc.DocumentElement.SelectNodes("/summary"); string summary = xnList.Item(0).InnerText; //Edit Summary-String summary = summary.Replace("///", ""); summary = summary.Trim(); return(summary); }
private async Task <Document> CreateChangedDocumentAsync(CodeFixContext context, DocumentationCommentTriviaSyntax documentationCommentTriviaSyntax, CancellationToken cancellationToken) { StringBuilder leadingTriviaBuilder = new StringBuilder(); SyntaxToken parentToken = documentationCommentTriviaSyntax.ParentTrivia.Token; int documentationCommentIndex = parentToken.LeadingTrivia.IndexOf(documentationCommentTriviaSyntax.ParentTrivia); for (int i = 0; i < documentationCommentIndex; i++) { SyntaxTrivia trivia = parentToken.LeadingTrivia[i]; switch (trivia.Kind()) { case SyntaxKind.EndOfLineTrivia: leadingTriviaBuilder.Clear(); break; case SyntaxKind.WhitespaceTrivia: leadingTriviaBuilder.Append(trivia.ToFullString()); break; default: break; } } leadingTriviaBuilder.Append(documentationCommentTriviaSyntax.GetLeadingTrivia().ToFullString()); // this is the trivia that should appear at the beginning of each line of the comment. SyntaxTrivia leadingTrivia = SyntaxFactory.DocumentationCommentExterior(leadingTriviaBuilder.ToString()); string newLineText = context.Document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); var documentedSymbol = semanticModel.GetDeclaredSymbol(parentToken.Parent.FirstAncestorOrSelf <SyntaxNode>(SyntaxNodeExtensionsEx.IsSymbolDeclaration), context.CancellationToken); DocumentationCommentTriviaSyntax contentsOnly = RemoveExteriorTrivia(documentationCommentTriviaSyntax); contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.ChildNodes(), (originalNode, rewrittenNode) => RenderBlockElementAsMarkdown(originalNode, rewrittenNode, newLineText, documentedSymbol)); string renderedContent = contentsOnly.Content.ToFullString(); string[] lines = renderedContent.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); SyntaxList <XmlNodeSyntax> newContent = XmlSyntaxFactory.List(); for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (string.IsNullOrWhiteSpace(line)) { if (i == lines.Length - 1) { break; } line = string.Empty; } if (newContent.Count > 0) { newContent = newContent.Add(XmlSyntaxFactory.NewLine(newLineText).WithTrailingTrivia(SyntaxFactory.DocumentationCommentExterior("///"))); } newContent = newContent.Add(XmlSyntaxFactory.Text(line.TrimEnd(), xmlEscape: false)); } contentsOnly = contentsOnly.WithContent(newContent); contentsOnly = contentsOnly .ReplaceExteriorTrivia(leadingTrivia) .WithLeadingTrivia(SyntaxFactory.DocumentationCommentExterior("///")) .WithTrailingTrivia(SyntaxFactory.EndOfLine(Environment.NewLine)); string fullContent = contentsOnly.ToFullString(); SyntaxTriviaList parsedTrivia = SyntaxFactory.ParseLeadingTrivia(fullContent); SyntaxTrivia documentationTrivia = parsedTrivia.FirstOrDefault(i => i.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)); contentsOnly = documentationTrivia.GetStructure() as DocumentationCommentTriviaSyntax; if (contentsOnly == null) { return(context.Document); } // Remove unnecessary nested paragraph elements contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), MarkUnnecessaryParagraphs); contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), RemoveUnnecessaryParagraphs); SyntaxNode root = await context.Document.GetSyntaxRootAsync(cancellationToken); SyntaxNode newRoot = root.ReplaceNode(documentationCommentTriviaSyntax, contentsOnly); if (documentationCommentTriviaSyntax.IsEquivalentTo(contentsOnly)) { return(context.Document); } if (documentationCommentTriviaSyntax.ToFullString().Equals(contentsOnly.ToFullString(), StringComparison.Ordinal)) { return(context.Document); } return(context.Document.WithSyntaxRoot(newRoot)); }