Search code examples
c#parsingroslyn

Roslyn - Property declaration parse errors


Currently I am writing a small class member declaration sorter for C# code.

During tests I stumbled upon the following code example, comprising PropertyDeclarations, which is not parsed successfully (the example is the content of the variable programText of course, not the whole code below):

The code

private void ParseIt()
{
    string programText = @"

public class Image : ViewModifyDataBase
{

    public BoolParameter IsTransformSelfCentered { get; init; } = new(new BaseModels.BoolParameter(false));

    public ValueParameter<double> OffsetX { get; init; } = new(new BaseModels.ValueParameter<double>(0, double.MinValue, double.MaxValue));

    public ValueParameter<double> OffsetY { get; init; } = new(new BaseModels.ValueParameter<double>(0, double.MinValue, double.MaxValue));

}
    ";

    var tree = CSharpSyntaxTree.ParseText(programText);
    var icml = tree.GetRoot().DescendantNodes().Where(nd => nd.Kind() == SyntaxKind.IncompleteMember).ToList();
    // Unfortunately icml is not empty:         
    foreach(var elem in icml)
    {
        Console.WriteLine($"IncompleteMember: {elem.ToFullString()}");
    }
}

gives the following output

IncompleteMember: new BaseModels.BoolParameter
IncompleteMember: (false));

IncompleteMember: new BaseModels.ValueParameter<double>
IncompleteMember: (0, 
IncompleteMember: double.
IncompleteMember: MinValue, 
IncompleteMember: double.
IncompleteMember: MaxValue));

IncompleteMember: new BaseModels.ValueParameter<double>
IncompleteMember: (0, 
IncompleteMember: double.
IncompleteMember: MinValue, 
IncompleteMember: double.
IncompleteMember: MaxValue));

The code snippet taken above to analyze nevertheless compiles well with normal VisualStudio (as part of a larger file) and also RoslynQuoter produces no warnings.

What can I do to accomplish a correct parse in my code too? Are there special parameter settings in ParseText() necessary?

EDIT: My roslyn (and other) versions:

  <ItemGroup>
    <PackageReference Include="AvalonEdit" Version="6.3.0.90" />
    <PackageReference Include="Microsoft.Build.Locator" Version="1.2.2" />
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="2.9.8" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" />
    <PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="3.3.1" />
    <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.3.1" />
  </ItemGroup>

ANOTHER EDIT: (My new settings according to your advice):

  <ItemGroup>
    <PackageReference Include="AvalonEdit" Version="6.3.0.90" />
    <PackageReference Include="Microsoft.Build.Locator" Version="1.2.2" />
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.7.0" />
    <PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.7.0" />
    <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.7.0" />
  </ItemGroup>

Solution

  • Converting my comment to an answer:

    The OP was using older versions of the Microsoft.CodeAnalysis.* NuGet packages that predated the introduction of the target-typed new() operator - introduced in C# 9.0.

    As of 2023Q3, the current versions of those NuGet packages is 4.7.0, so update to those.

    However, instead of having PackageReferences for individual Microsoft.CodeAnalysis.etc... packages, you only need to reference Microsoft.CodeAnalysis and it will automatically pull-in the others:

      <ItemGroup>
        <PackageReference Include="AvalonEdit" Version="6.3.0.90" />
        <PackageReference Include="Microsoft.Build.Locator" Version="1.2.2" />
        <PackageReference Include="Microsoft.CodeAnalysis" Version="4.7.0" />
      </ItemGroup>
    

    (you may-or-may not need PrivateAssets="all" depending on how you're using Roslyn)