Search code examples
c#abstract-syntax-treeroslyncode-analysisroslyn-code-analysis

Gets TypeSyntax's namespace from external assembly


I'm trying to retrieve some type's namespace with Roslyn API, but my code is not working with external assemblies (types from NuGet packages, or from another external assembly):

var typeInfo = semanticModel.GetTypeInfo(typeSyntax);
var isFromSource = typeInfo.Type.Locations.Length > 0;

if (isFromSource)
{
    var symbolInfo = semanticModel.GetSymbolInfo(typeSyntax);

    //type's namespace:
    return symbolInfo.Symbol.ContainingNamespace.ToString();
}
else
{
    //Type is from some external assembly
    return "";
}

How can i return the type's namespace in this case?

EDIT: I'm retrieving solution's documents with:

using (var ws = MSBuildWorkspace.Create())
{
    var solution = await ws.OpenSolutionAsync(solutionPath);

    return solution.Projects.SelectMany(p => p.Documents);
}

Solution

  • Are you sure there are no compilation errors when processing the syntax and the type is correctly resolved?

    The ContainingNamespace property should provide the namespace also for the types from external assemblies as long as the type can be resolved.

    In case it helps, you can find here a snippet which displays the namespace for an external type (RestClient class is from RestSharp nuget package):

    using System;
    using System.Linq;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.CSharp.Syntax;
    using RestSharp;
    
    namespace Playground
    {
        public static class Program
        {
            public static void Main()
            {
                const string code =
    @"using RestSharp;
    
    namespace Playground
    {
        public class Foo
        {
            public void Bar(RestClient restClient)
            {
            }
        }
    }";
                var tree = CSharpSyntaxTree.ParseText(code);
                var compilation = CreateCompilation(tree);
                var semanticModel = compilation.GetSemanticModel(tree);
                var syntaxNode = GetParameterTypeSyntaxNode(tree);
    
                Console.WriteLine(GetNamespace(syntaxNode, semanticModel));
            }
    
            private static TypeSyntax GetParameterTypeSyntaxNode(SyntaxTree tree) =>
                tree.GetRoot()
                    .DescendantNodes()
                    .OfType<MethodDeclarationSyntax>()
                    .First()
                    .ParameterList
                    .Parameters
                    .First()
                    .Type;
    
            private static INamespaceSymbol GetNamespace(SyntaxNode node, SemanticModel semanticModel) =>
                semanticModel.GetTypeInfo(node).Type?.ContainingNamespace;
    
            private static CSharpCompilation CreateCompilation(SyntaxTree tree) =>
                CSharpCompilation
                    .Create("HiThere", options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
                    .AddReferences(MetadataReference.CreateFromFile(typeof(string).Assembly.Location))
                    .AddReferences(MetadataReference.CreateFromFile(typeof(RestClient).Assembly.Location))
                    .AddSyntaxTrees(tree);
        }
    }