Joey
Joey

Reputation: 354644

Obtain case label constant in Roslyn

I'm trying to gather the switch section label constants from a SwitchStatement with Roslyn. But while I can see in the Syntax Visualizer that the CaseSwitchLabelSyntax has a Value property with the corresponding constant and the declared symbol (SourceLabelSymbol) has a SwitchCaseLabelConstant property, I cannot seem to get that information from what I have in my code.

// SwitchStatementSyntax node;
// SemanticModel model;

foreach (var section in node.Sections) {
  foreach (var label in section.Labels) {
    var labelSymbol = model.GetDeclaredSymbol(label);
    // Here I'm stuck
  }
}

I could probably look whether the SwitchLabelSyntax is a CaseSwitchLabelSyntax or a DefaultSwitchLabelSyntax and cast accordingly. SourceLabelSymbol is actually internal, so I cannot access its properties. model.GetConstantValue(label) returns null.

But given that Roslyn always hands out interfaces I believe that there's a reason for that and wildly casting around feels a bit hacky to me. Is there a better option?

Note: I'm doing this to translate C# syntax into another language. Technically, first into a separate AST that is then converted to text again. Above code is from within a CSharpSyntaxWalker and I could probably just store my partially converted switch statement away, continue visiting its descendants and build it up piecewise.

But that means having more state, building statements in half a dozen distinct locations which leads to hard-to-read and -follow code. I'd rather avoid it here, if possible.

Upvotes: 3

Views: 370

Answers (1)

Pavel Krymets
Pavel Krymets

Reputation: 6293

Closest from API is semanticModel.GetConstantValue method, but still you need to pass Value node to it like this:

section.Labels
       .OfType<CaseSwitchLabelSyntax>()
       .Select(l => semanticModel.GetConstantValue(l.Value))
       .ToArray()

As you can see filtering out CaseSwitchLabelSyntax is required anyway.

Upvotes: 3

Related Questions