Scenario: I'm trying to use Roslyn to merge a set of C# source fragments into a single code fragment.
Issue: when parsing different classes with a leading comment, the comment above the first class (SomeClass
in the example) is not preserved. For the second class (AnotherClass
), the comment IS preserved...
The code below demonstrates the issue. Use this in a console program (& install Microsoft.CodeAnalysis.CSharp nuget package)
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Diagnostics;
using System;
namespace roslyn01
{
class Program
{
static void Main(string[] args)
{
var input = new[]
{
"// some comment\r\nclass SomeClass {}",
"// another comment\r\nclass AnotherClass {}",
};
// parse all input and collect members
var members = new List<MemberDeclarationSyntax>();
foreach (var item in input)
{
var syntaxTree = CSharpSyntaxTree.ParseText(item);
var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot();
members.AddRange(compilationUnit.Members);
}
// assemble all members in a new compilation unit
var result = SyntaxFactory.CompilationUnit()
.AddMembers(members.ToArray())
.NormalizeWhitespace()
.ToString();
var expected = @"// some comment
class SomeClass
{
}
// another comment
class AnotherClass
{
}";
Console.WriteLine(result);
// the assert fails; the first comment ('// some comment') is missing from the output
Debug.Assert(expected == result);
}
}
}
What am I missing?
You are using ToString()
instead of ToFullString()
when transforming CompilationUnitSyntax
to string
. ToString()
returns a string removing leading and trailing trivia (including comments), but ToFullString()
doesn't remove this trivia. You can see it in the code documentation:
//
// Description:
// Returns the string representation of this node, not including its leading and
// trailing trivia.
//
// Returns:
// The string representation of this node, not including its leading and trailing
// trivia.
//
// Comments:
// The length of the returned string is always the same as Span.Length
public override string ToString();
//
// Description:
// Returns full string representation of this node including its leading and trailing
// trivia.
//
// Returns:
// The full string representation of this node including its leading and trailing
// trivia.
//
// Comments:
// The length of the returned string is always the same as FullSpan.Length
public virtual string ToFullString();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With