Reputation: 22680
I'm trying to get Symbol for label from GotoStatementSyntax, below code works for labeled statements, but not for case labels:
public override void VisitGotoStatement(GotoStatementSyntax node)
{
var symbol = Model.GetSymbolInfo(node.Expression).Symbol;
}
I found here that is was not supported in 2012. Is it still the case or there is a way to get a symbol from goto case statement?
Upvotes: 2
Views: 227
Reputation: 10940
There are actually two ways of getting the labeled statements.
You can use the SemanticModel.LookupLabels
method to get the associated label symbol. Finding out the correct name parameter is a bit tricky though:
var name = node.CaseOrDefaultKeyword.ValueText != null
? string.Join(" ", new[] { node.CaseOrDefaultKeyword.Text, node.Expression?.ToString() }.Where(x => x != null)) + ":"
: node.Expression.ToString();
var label = Model.LookupLabels(node.SpanStart, name).OfType<ILabelSymbol>().SingleOrDefault();
A GotoStatementSyntax
resolves to an IBranchStatement
operation, which contains a reference to the targeted label symbol:
var label = ((IBranchStatement)Model.GetOperation(node)).Target;
Both code snippets give you the same ILabelSymbol
.
Here's the LinqPad script I used to repro the question:
async Task Test()
{
var ws = new AdhocWorkspace();
var proj = ws.AddProject("test", "C#");
var tree = SyntaxFactory.ParseSyntaxTree(@"
public class Program
{
public static void Main()
{
var i = System.Environment.GetCommandLineArgs().Length;
switch (i)
{
case 1: goto case 2;
case 2: goto default;
case 3: goto wat;
default: break;
}
wat:
return;
}
}");
var root = tree.GetRoot();
var doc = proj.AddDocument("file1.cs", root);
proj = doc.Project.AddMetadataReference(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));
var compilation = await proj.GetCompilationAsync();
var model = compilation.GetSemanticModel(tree);
var walker = new Walker { Model = model };
walker.Visit(root);
}
class Walker : CSharpSyntaxWalker
{
public SemanticModel Model { get; set; }
public override void VisitGotoStatement(GotoStatementSyntax node)
{
var name = node.CaseOrDefaultKeyword.ValueText != null
? string.Join(" ", new[] { node.CaseOrDefaultKeyword.Text, node.Expression?.ToString() }.Where(x => x != null)) + ":"
: node.Expression.ToString();
var label = Model.LookupLabels(node.SpanStart, name).OfType<ILabelSymbol>().SingleOrDefault();
var label2 = ((IBranchStatement)Model.GetOperation(node)).Target;
// (label == label2).Dump();
base.VisitGotoStatement(node);
}
}
Upvotes: 1