Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the base class name of a class via Roslyn?

Tags:

c#

roslyn

I am using Roslyn and I have the following class:

var source = @"
    using System;
    class MyClass : MyBaseClass {
      static void Main(string[] args) {
        Console.WriteLine(""Hello, World!"");
      }
    }";

// Parsing
SyntaxTree tree = CSharpSyntaxTree.ParseText(source);

// This uses an internal function (working)
// That gets the first node of type `SimpleBaseTypeSyntax`
SimpleBaseTypeSyntax simpleBaseType = GetNBaseClassNode(tree);

Getting the base class name

I successfully get access to node SimpleBaseTypeSyntax which contains what I need. In fact, if I use the syntax explorer, I get:

enter image description here

Node IdentifierToken has everything I need has its Text, Value and ValueText properties are "MyBaseClass"!

However, while in the syntax explorer I can see all these values, I cannot access them programmatically.

So I try retrieving the node programmatically:

IdentifierNameSyntax identifierNode =
  simpleBaseType.ChildNodes().OfType<IdentifierNameSyntax>().First();
SyntaxToken identifier = simpleBaseType.Identifier;
string name = identifier.Text;

But name is empty string. Same as identifier.Value and identifier.ValueText.

What am I doing wrong? Maybe I am doing wrong, so how would you retrieve the base class name?


Another attempt: Using the semantic model

I started thinking that I need the semantic model for this type of information:

IdentifierNameSyntax identifierNode =
  simpleBaseType .ChildNodes().OfType<IdentifierNameSyntax>().First();

SemanticModel semanticModel =
  CSharpCompilation.Create("Class")
   .AddReferences(MetadataReference.CreateFromFile(
     typeof(object).Assembly.Location))
       .AddSyntaxTrees(tree).GetSemanticModel(tree);

SymbolInfo symbolInfo = this.semanticModel.GetSymbolInfo(identifierNode);
string name = symbolInfo.Symbol.Name;

This throws exception as symbolInfo.Symbol is null.

like image 806
Andry Avatar asked Nov 30 '22 23:11

Andry


1 Answers

I actually don't know why you can't pass the BaseTypeSyntax to the semantic model via GetSymbolInfo(), but it's also returning null for me with no errors.

Anyways, here's an approach that works:

var tree = CSharpSyntaxTree.ParseText(@"
using System;
class MyBaseClass
{
}
class MyClass : MyBaseClass {
  static void Main(string[] args) {
    Console.WriteLine(""Hello, World!"");
  }
}");

var Mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var compilation = CSharpCompilation.Create("MyCompilation",
    syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);

var myClass = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().Last();
var myClassSymbol = model.GetDeclaredSymbol(myClass) as ITypeSymbol;
var baseTypeName = myClassSymbol.BaseType.Name;

You'll want to use the semantic model here because you won't be able to reliably tell if you're dealing with an interface or a base type at the syntax level.

like image 57
JoshVarty Avatar answered Dec 10 '22 05:12

JoshVarty