如何获取 Roslyn 找不到的所有 C# 类型或命名空间?

How to get all C# types or namespaces that Roslyn couldn't find?

我正在使用 Roslyn 来解析 C# 项目。我有一个 Microsoft.CodeAnalysis.Compilation object that represents this project. However, this project might not have been compiled successfully; there may be several reasons for this, but I'm specifically interested in any references to a type or a namespace that couldn't be resolved. How can I use my Compilation object to retrieve all unknown namespaces or types as IErrorTypeSymbols?

最简单的方法是遍历所有 SyntaxTree 并使用编译的 SemanticModel 来识别错误类型。

类似...

// assumes `comp` is a Compilation

// visit all syntax trees in the compilation
foreach(var tree in comp.SyntaxTrees)
{
    // get the semantic model for this tree
    var model = comp.GetSemanticModel(tree);
    
    // find everywhere in the AST that refers to a type
    var root = tree.GetRoot();
    var allTypeNames = root.DescendantNodesAndSelf().OfType<TypeSyntax>();
    
    foreach(var typeName in allTypeNames)
    {
        // what does roslyn think the type _name_ actually refers to?
        var effectiveType = model.GetTypeInfo(typeName);
        if(effectiveType.Type != null && effectiveType.Type.TypeKind == TypeKind.Error)
        {
            // if it's an error type (ie. couldn't be resolved), cast and proceed
            var errorType = (IErrorTypeSymbol)effectiveType.Type;

            // do what you want here
        }
    }
}

未知的名称空间需要在抓取后进行更多的处理,因为如果没有,您无法真正判断 Foo.Bar 是指“Foo 中的 Bar 类型”还是“名称空间 Foo.Bar”元数据。有可能我忘记了 Roslyn 会走私类型引用语法节点的某个地方……但我记得 TypeName

您可以使用 semanticModel.GetSymbolInfo(identifierNameSyntax),其中 returns 一个 SymbolInfo。 SymbolInfo.Symbol 是一个 ISymbol,因此您可以使用 ISymbol.ContainingNamespace 来获取标识符所属的命名空间。