从已解析源外部声明的类型的标识符中获取 SymbolInfo

Get SymbolInfo from identifier of type declared outside parsed source

我想用Roslyn来解析C#代码,我想获取代码中每个引用类型的限定名。

例如我想解析这段代码:

using System;

namespace RoslynTest
{
    public class Test
    {
        public static void Main()
        {
            String a = "Hello, World!";
            Console.WriteLine(a);
        }
    }
}

为了解析它,我使用了以下代码:

SyntaxTree tree = CSharpSyntaxTree.ParseText(source);

CSharpCompilation compilation = CSharpCompilation.Create("test", new[] { tree });
SemanticModel semanticModel = compilation.GetSemanticModel(tree, false);

CompilationUnitSyntax root = (CompilationUnitSyntax)tree.GetRoot();

IEnumerable<IdentifierNameSyntax> identifiers = root.DescendantNodes()
    .Where(s => s is IdentifierNameSyntax)
    .Cast<IdentifierNameSyntax>();

foreach (IdentifierNameSyntax i in identifiers)
{
    SymbolInfo info = semanticModel.GetSymbolInfo(i);

    if (info.Symbol == null)
    {
        Console.WriteLine("Unknown :(");
    }
    else
    {
        Console.WriteLine(info.Symbol.ContainingNamespace?.Name + "." + info.Symbol.ContainingType?.Name + "." + info.Symbol.Name);
    }
}

在此示例中,当我到达描述 "String" 的 IdentifierNameSyntax 时,info.Symbol 将为空。我想要一些方法来知道全名 System.String,并且与引用的其他类型相同。

您的实际问题是没有 String 类型。

如果您查看 SemanticModel 中的编译错误,您会看到与此相关的错误。

您需要在 Compilation 中添加对 mscorlib 的引用,以便 System.String 存在。 一旦你这样做,info.Symbol 将不会为空。

另外,切入正题:

IEnumerable<IdentifierNameSyntax> identifiers = 
root.DescendantNodes().OfType<IdentifierNameSyntax>();

而不是:

IEnumerable<IdentifierNameSyntax> identifiers = root.DescendantNodes()
    .Where(s => s is IdentifierNameSyntax)
    .Cast<IdentifierNameSyntax>();