Replace the little things in node in Roslyn

For example, I have the following documentation comment in my C # code file:

/// add k+5 

I want to REPLACE it with node

 _tst.AddElement(k+5); 

How to do this using C # / Roslyn? I found how to add this line, but did not find how to replace it. My code that node adds:

 public static MethodDeclarationSyntax getChangedNode(MethodDeclarationSyntax method) { var newmethod = method; var TestEntryArgName = "_tst"; /* Adding _tst.AddElement(i); */ foreach (var s in newmethod.Body.DescendantNodes()) { SyntaxTrivia st = SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " "); bool fl = false; bool before = true; var lt = s.GetLeadingTrivia(); foreach (var triviaEntry in lt) { if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia) { fl = true; st = triviaEntry; break; } } if (!fl) { lt = s.GetTrailingTrivia(); before = false; foreach (var triviaEntry in lt) { if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia) { fl = true; st = triviaEntry; break; } } if (!fl) continue; } var commentContents = st.ToString(); char[] delim = { ' ', '\n', '\t', '\r' }; var ar = commentContents.Split(delim, StringSplitOptions.RemoveEmptyEntries); if (ar.Length != 2 || ar[0] != "add") continue; var lineToAdd = TestEntryArgName + ".AddElement(" + ar[1] + ")"; var linelist = new List<ExpressionStatementSyntax>(); linelist.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(lineToAdd))); var childlist = s.Parent.ChildNodes(); foreach (var si in childlist) { if (s != si) continue; if (before) newmethod = newmethod.InsertNodesBefore(si, linelist); else newmethod = newmethod.InsertNodesAfter(si, linelist); break; } break; } return newmethod; } 

I need to replace all such comments in my method. This function inserts only node and does it only once.

Change At this point, I have the following solution, but it seems too complicated and not obvious ...

  public static MethodDeclarationSyntax getChangedNode(MethodDeclarationSyntax method) { var TestEntryArgName = "__tst"; /* Adding last param */ var parlist = method.ChildNodes().OfType<ParameterListSyntax>().First(); var newparlist = parlist.AddParameters(SyntaxFactory.Parameter( SyntaxFactory.Identifier(TestEntryArgName)) .WithType(SyntaxFactory.ParseTypeName("Heap "))); var newmethod = method.ReplaceNode(parlist, newparlist); /* Adding __tst.AddElement(i); */ while (true) { IEnumerable<SyntaxNode> desc; bool triviaFound; desc = newmethod.Body.DescendantNodes(); triviaFound = false; foreach (var s in desc) { SyntaxTrivia st = SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " "); bool fl = false; bool before = true; var lt = s.GetLeadingTrivia(); foreach (var triviaEntry in lt) { if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia) { fl = true; st = triviaEntry; break; } } if (!fl) { lt = s.GetTrailingTrivia(); before = false; foreach (var triviaEntry in lt) { if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia) { fl = true; st = triviaEntry; break; } } if (!fl) continue; } var commentContents = st.ToString(); char[] delim = { ' ', '\n', '\t', '\r' }; var ar = commentContents.Split(delim, StringSplitOptions.RemoveEmptyEntries); if (ar.Length != 2 || ar[0] != "add") continue; var lineToAdd = TestEntryArgName + ".AddElement(" + ar[1] + ")"; var linelist = new List<ExpressionStatementSyntax>(); linelist.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(lineToAdd))); var childlist = s.Parent.ChildNodes(); foreach (var si in childlist) { if (s != si) continue; if (before) newmethod = newmethod.InsertNodesBefore(si, linelist); else newmethod = newmethod.InsertNodesAfter(si, linelist); break; } var newTrvias = newmethod.DescendantTrivia().Where((t) => { if (t.Kind() != SyntaxKind.SingleLineDocumentationCommentTrivia) return false; var arr = t.ToString().Split(delim, StringSplitOptions.RemoveEmptyEntries); return arr.Length == 2 && arr[0] == "add"; }); newmethod = newmethod.ReplaceTrivia(newTrvias.First(), SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " ")); triviaFound = true; break; } if (!triviaFound) break; } return newmethod; } 
+6
source share
2 answers

What you are looking for is probably CSharpSyntaxRewriter. This is a class in roslyn that visits every node, token, and little things in the syntax model of your code. You can make your own rewriter that overrides VisitTrivia and returns the expression you want to receive. For instance:

  public class MyRewriter : CSharpSyntaxRewriter { public MyRewriter(): base(true) { } public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) { if(trivia.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia) { string xml = trivia.ToFullString(); var TestEntryArgName = "__tst"; char[] delim = { ' ', '\n', '\t', '\r' }; var ar = xml.Split(delim, StringSplitOptions.RemoveEmptyEntries); if (ar.Length != 3 || ar[1] != "add") { return base.VisitTrivia(trivia); } var lineToAdd = TestEntryArgName + ".AddElement(" + ar[2] + ")"; var expression = SyntaxFactory.SyntaxTrivia(SyntaxKind.SingleLineCommentTrivia, lineToAdd); return expression; } return base.VisitTrivia(trivia); } } 

sample use:

  var myRewriter = new MyRewriter(); string code = ""; using (StreamReader sr = new StreamReader("Program.cs")) { code = sr.ReadToEnd(); } var tree = CSharpSyntaxTree.ParseText(code); var node = tree.GetRoot(); using(StreamWriter sw = new StreamWriter("Program.cs")) { sw.Write(myRewriter.Visit(node)); } 
+3
source

I found a simple solution, and I think it suits me, but, I know, it cannot be called the β€œright” solution because it deals with the source code. Anyway:

 public static MethodDeclarationSyntax getChangedNode(MethodDeclarationSyntax newmethod) { /* Adding __tst.AddElement(i); */ while (true) { var desc = newmethod.Body.DescendantTrivia().Where((t) => t.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)); var triviaFound = false; foreach (var s in desc) { var commentContents = s.ToString(); char[] delim = { ' ', '\n', '\t', '\r' }; var ar = commentContents.Split(delim, StringSplitOptions.RemoveEmptyEntries); if (ar.Length != 2 || ar[0] != "add") continue; var lineToAdd = "\r\n__tst.AddElement(" + ar[1] + ");\r\n"; newmethod = CSharpSyntaxTree.ParseText(newmethod.GetText().Replace(s.FullSpan, lineToAdd)) .GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First(); triviaFound = true; break; } if (!triviaFound) break; } return newmethod; } 
+1
source

All Articles