Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Class FullName (including namespace) from Roslyn ClassDeclarationSyntax

Tags:

c#

roslyn

I've a ClassDeclarationSyntax from a syntax tree in roslyn. I read it like this:

var tree = SyntaxTree.ParseText(sourceCode);
var root = (CompilationUnitSyntax)tree.GetRoot();

var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>();

The identifier only contains the name of the class but no information about the namespace, so the fullType Name is missing. Like "MyClass" but noch "Namespace1.MyClass"

what is the recommended way to get the namespace / FulltypeName of the Syntax?

like image 807
Boas Enkler Avatar asked Dec 08 '13 20:12

Boas Enkler


3 Answers

you can do this using the helper class I wrote:

NamespaceDeclarationSyntax namespaceDeclarationSyntax = null;
if (!SyntaxNodeHelper.TryGetParentSyntax(classDeclarationSyntax, out namespaceDeclarationSyntax))
{
    return; // or whatever you want to do in this scenario
}

var namespaceName = namespaceDeclarationSyntax.Name.ToString();
var fullClassName = namespaceName + "." + classDeclarationSyntax.Identifier.ToString();

and the helper:

static class SyntaxNodeHelper
{
    public static bool TryGetParentSyntax<T>(SyntaxNode syntaxNode, out T result) 
        where T : SyntaxNode
    {
        // set defaults
        result = null;

        if (syntaxNode == null)
        {
            return false;
        }

        try
        {
            syntaxNode = syntaxNode.Parent;

            if (syntaxNode == null)
            {
                return false;
            }

            if (syntaxNode.GetType() == typeof (T))
            {
                result = syntaxNode as T;
                return true;
            }

            return TryGetParentSyntax<T>(syntaxNode, out result);
        }
        catch
        {
            return false;
        }
    }
}

There is nothing overly complex going on here... it makes sense that the namespace would be "up" the syntax tree (because the class is contained within the namespace) so you simply need to travel "up" the syntax tree until you find the namespace and append that to the identifier of the ClassDeclarationSyntax.

like image 67
Jordan Avatar answered Oct 19 '22 15:10

Jordan


I know I am rather late in the game, but I stumbled upon one of given the answers which did not work in my case where I had to deal with nested classes. So therefore here is a method that will handle nested classes as well:

public static class ClassDeclarationSyntaxExtensions
{
    public const string NESTED_CLASS_DELIMITER = "+";
    public const string NAMESPACE_CLASS_DELIMITER = ".";

    public static string GetFullName(this ClassDeclarationSyntax source)
    {
        Contract.Requires(null != source);

        var items = new List<string>();
        var parent = source.Parent;
        while (parent.IsKind(SyntaxKind.ClassDeclaration))
        {
            var parentClass = parent as ClassDeclarationSyntax;
            Contract.Assert(null != parentClass);
            items.Add(parentClass.Identifier.Text);

            parent = parent.Parent;
        }

        var nameSpace = parent as NamespaceDeclarationSyntax;
        Contract.Assert(null != nameSpace);
        var sb = new StringBuilder().Append(nameSpace.Name).Append(NAMESPACE_CLASS_DELIMITER);
        items.Reverse();
        items.ForEach(i => { sb.Append(i).Append(NESTED_CLASS_DELIMITER); });
        sb.Append(source.Identifier.Text);

        var result = sb.ToString();
        return result;
    }
}
like image 24
Ronald Rink 'd-fens' Avatar answered Oct 19 '22 16:10

Ronald Rink 'd-fens'


There's also an elegant way when using pattern matching + recursion:

// method with pattern matching
public static string GetNamespaceFrom(SyntaxNode s) =>
    s.Parent switch
    {
        NamespaceDeclarationSyntax namespaceDeclarationSyntax => namespaceDeclarationSyntax.Name.ToString(),
        null => string.Empty, // or whatever you want to do
        _ => GetNamespaceFrom(s.Parent)
    };

// somewhere call it passing the class declaration syntax:
string ns = GetNamespaceFrom(classDeclarationSyntax);
like image 2
Arley Pádua Avatar answered Oct 19 '22 17:10

Arley Pádua