0

I'm using Roslyn to parse a C# project. I have a 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?

JesseTG
  • 2,025
  • 1
  • 24
  • 48

2 Answers2

1

Easiest way would be to loop over all SyntaxTrees and use the compilation's SemanticModel to identify error types.

Something like...

// 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
        }
    }
}

Unknown namespaces require a bit more finessing after your crawl, since you can't really tell whether Foo.Bar is referring to "a type Bar in Foo" or "a namespace Foo.Bar" without metadata. It's possible I'm forgetting some place where Roslyn will smuggle type-referring syntax nodes... but TypeName is what I recall.

Kevin Montrose
  • 22,191
  • 9
  • 88
  • 137
  • That did it, thanks! This retrieves both unknown types and unknown namespaces; in my use case, as long as I can get information about both I don't need to make a distinction. I'm outputting diagnostics for humans, not for other programs. – JesseTG Jul 07 '20 at 17:54
0

you can use semanticModel.GetSymbolInfo(identifierNameSyntax) which returns a SymbolInfo. SymbolInfo.Symbol is an ISymbol, so you can use ISymbol.ContainingNamespace to get the namespace an identifier belongs to.