8

I'm working on a little piece of roslyn code to try to do some simple refactorings, inside a Visual Studio for MAC extension project.

I want to refactor this code:

public class Test
{
    private const object a = null; 


    public const int c = 0;

}

into this code

public class Test
{
    public const int c = 0;
    private const object a = null; 

}

So far I managed to get a List of ISymbol representing my constants, order them properly, and then transfom them into a list of SyntaxNode like this

var orderedMembers = orderer.OrderAll(classMembers);
var nodes = orderedMembers.Select(o => o.DeclaringSyntaxReferences.FirstOrDefault().GetSyntax())
                                  .Where(node => node != null)
                                  .ToList();

So far so good. The output is like this

public class Test
{
    public const int c = 0;
    private const object a = null; 
}

Now my last step, is adding a few lines after my last constant, to define a separation between my constants and what might follow.

It seems I can do this by adding a Trailing/Leading trivia to one of my SyntaxNode. So I tried this (hard coded for simplicity right now):

nodes[1] = nodes[1].WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);

Then I insert my new nodes into my "Test" class declaration node, and make that into a string (here "editor" is an instance of a Microsoft.CodeAnalysis.Editing.DocumentEditor representing a file I opened with vs for mac IDE):

editor.InsertMembers(classNode, 0, nodes);
var newDocument = editor.GetChangedDocument();
(await newDocument.GetTextAsync()).ToString();

and this is what it generates:

public class Test
{
    public const int c = 0;
}

So the SyntaxNode I tried to add Trivia to, does not get generated when calling the GetTextAsync on my newly edited Document.

This is the first time I've been playing with Roslyn so I guess I'm missing something important about using Trivia, but I can't seem to find what that is. Any ideas on how to add some new Lines after a defined SyntaxNode ?

Miiite
  • 1,517
  • 10
  • 16
  • I can reproduce your issue. Can you add the full code? Trivia and especially new lines is a pain but I can't see a reason that your node is deleted. – Dudi Keleti Feb 14 '19 at 14:06
  • Sure, the full code is actually available on github at https://github.com/Miiite/CodeCleaner/tree/master/CodeMaid. It's a bit larger than what I tried to describe here, but you can find the code int RefactorCommand.cs/ HandleOrdering – Miiite Feb 14 '19 at 14:59
  • You cannot add empty lines as trailing trivia, they have to be leading trivia for the next token. – Kris Vandermotten Feb 16 '19 at 08:37
  • If I update my code above to replace WithTrailingTrivia by WithLeadingTrivia, I get the same behavior, the node "disappears" when generating the output C# text file – Miiite Feb 20 '19 at 09:53
  • I don't have access to Roslyn at the moment but something feels "off" about assigning node values in an array like `nodes[1] = ...` Can you instead use `editor.replaceNode(nodes[1], nodes[1].WithTrailingTrivia())` – JoshVarty Feb 22 '19 at 22:50
  • If I try to do a "editor.ReplaceNode" right after my editor.InsertMembers(classNode, 0, nodes); line, then when I call editor.GetChangedDocument(); it raises a NullReferenceException – Miiite Feb 27 '19 at 08:54

0 Answers0