Generate a 'readonly record struct' using Roslyn

99 views Asked by At

I can't generate a readonly record struct using Roslyn.

My code:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

var tree = SyntaxFactory.CompilationUnit()
    .AddMembers(
            SyntaxFactory.RecordDeclaration(
                SyntaxFactory.Token(SyntaxKind.RecordKeyword),
                SyntaxFactory.Identifier("A"))
            .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
            .AddModifiers(
                        SyntaxFactory.Token(SyntaxKind.PublicKeyword),
                        SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword))
            .WithClassOrStructKeyword(
                SyntaxFactory.Token(SyntaxKind.StructKeyword))
            .WithParameterList(
                SyntaxFactory.ParameterList()))
    .NormalizeWhitespace();

Console.WriteLine(tree.ToFullString());

var refApis = AppDomain.CurrentDomain.GetAssemblies()
    .Where(a => !a.IsDynamic)
    .Select(a => MetadataReference.CreateFromFile(a.Location));

var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);

var compilation = CSharpCompilation.Create("something", new SyntaxTree[] { tree.SyntaxTree }, refApis, options);
var diag = compilation.GetDiagnostics().Where(e => e.Severity == DiagnosticSeverity.Error).ToList();

foreach (var d in diag)
{
    Console.WriteLine(d);
}

Console.ReadLine();

I get such a result "public readonly record struct A();" and such an error "(1,31): error CS0106: The "readonly" modifier is invalid for this element."

1

There are 1 answers

0
Youssef13 On BEST ANSWER

The problem is that the record declaration you're creating has SyntaxKind.RecordDeclaration instead of SyntaxKind.RecordStructDeclaration. Even if you are adding the struct keyword, it doesn't change the SyntaxKind that was originally created. To fix this, you'll need to do it as follows:

            SyntaxFactory.RecordDeclaration(
                SyntaxKind.RecordStructDeclaration,
                SyntaxFactory.Token(SyntaxKind.RecordKeyword),
                SyntaxFactory.Identifier("A"))

instead of

            SyntaxFactory.RecordDeclaration(
                SyntaxFactory.Token(SyntaxKind.RecordKeyword),
                SyntaxFactory.Identifier("A"))