从Roslyn的goto案例中获取符号

时间:2016-08-02 15:17:26

标签: c# roslyn

我正在尝试从GotoStatementSyntax获取Symbol的标签,下面的代码适用于带标签的语句,但不适用于案例标签:

    public override void VisitGotoStatement(GotoStatementSyntax node)
    {
        var symbol = Model.GetSymbolInfo(node.Expression).Symbol;
    }

我发现2012年不支持here。它仍然是这种情况还是有办法从goto case语句中获取符号?

1 个答案:

答案 0 :(得分:1)

实际上有两种获取标签声明的方法。

  1. 您可以使用SemanticModel.LookupLabels方法获取相关的标签符号。找出正确的名称参数有点棘手:

    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();
    
  2. GotoStatementSyntax解析为IBranchStatement操作,其中包含对目标标签符号的引用:

    var label = ((IBranchStatement)Model.GetOperation(node)).Target;
    
  3. 两个代码段都为您提供相同的ILabelSymbol

    这是我用来重复问题的LinqPad脚本:

    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);
        }
    }