Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find types that inherit from given INamedTypeSymbol

Tags:

c#

roslyn

Given an INamedTypeSymbol (that comes from an referenced assembly, not source) how can I find all types (in both source and referenced assemblies) that inherit from this type?

In my particular case, I'm looking for all types that inherit from NUnit.Framework.TestAttribute. I can get access to the named type symbol as follows:

var ws = MSBuildWorkspace.Create();
var soln = ws.OpenSolutionAsync(@"C:\Users\...\SampleInheritanceStuff.sln").Result;
var proj = soln.Projects.Single();
var compilation = proj.GetCompilationAsync().Result;

string TEST_ATTRIBUTE_METADATA_NAME = "NUnit.Framework.TestAttribute";
var testAttributeType = compilation.GetTypeByMetadataName(TEST_ATTRIBUTE_METADATA_NAME);

//Now how do I find types that inherit from this type?

I've taken a look at SymbolFinder, Compilation and INamedTypeSymbol but I haven't had any luck.

Edit: The FindDerivedClassesAsync method looks close to what I need. (I'm not 100% sure that it finds derived classes in referenced assemblies). However it's internal, so I've opened an issue.

like image 541
JoshVarty Avatar asked Aug 28 '15 01:08

JoshVarty


1 Answers

The FindDerivedClassesAsync is indeed what you are looking for.
It finds derived classes in referenced assemblies, as you can see in the source code for DependentTypeFinder (notice the locationsInMetadata variable).

As for using it, you can always do it with reflection in the meantime:

 private static readonly Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>> FindDerivedClassesAsync
            = new Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>>(() => (Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>)Delegate.CreateDelegate(typeof(Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>), DependentTypeFinder.Value.GetMethod("FindDerivedClassesAsync", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)));

(code borrowed from Tunnel Vision Laboratories Github)

Good luck!

UPDATE:

This method has been made public by now. (source)

like image 55
Jony Adamit Avatar answered Nov 15 '22 11:11

Jony Adamit