Trovare tutte le dichiarazioni di class che ereditare da un’altra con Roslyn

Ho un’istanza CSharpCompilation contenente una matrice di SyntaxTree e sto cercando di trovare tutte le dichiarazioni di class che ereditano da una class

per esempio

 // Not in syntax tree but referenced in project public class Base{} // In syntax tree, how to find all such classs? public class MyClass : Base {} 

Ho provato alcune cose ma sono un po ‘confuso con tutte le opzioni e non riesco a trovare il modo giusto per farlo.

Ho provato ad ottenere i simboli ma questo non funziona per i tipi ereditati

 SyntaxTree[] trees = context.CSharpCompilation.SyntaxTrees; IEnumerable symbols = context.CSharpCompilation.GetSymbolsWithName(x => x == typeof(Base).Name, SymbolFilter.Type); 

Piuttosto nuovo per Roslyn e sarebbe molto grato per qualsiasi suggerimento o suggerimento su come raggiungere questo objective.

Per prima cosa devi ottenere il simbolo per Base. Se questo è un tipo particolare che conosci in anticipo, puoi utilizzare Compilation.GetTypeByMetadataName per questo. Quel collegamento ti mostrerà anche oltre 100 esempi di quel metodo in uso.

Da lì, dipende da cosa stai cercando di fare. Se stai facendo questo da un analizzatore (che sospetto dal “context.CSharpCompilation” nel tuo codice), e stai cercando di identificare e quindi controllare alcune proprietà di questi tipi derivati, potresti usare RegisterSymbolAction per SymbolKind. NamedType, quindi controlla BaseType di ogni tipo (possibilmente ricorsivamente, in base a ciò che stai cercando di ottenere) per vedere se trovi il tipo scoperto da GetTypeByMetadataName sopra.

Se si sta eseguendo un’analisi a livello di soluzione al di fuori del contesto di un analizzatore, esiste un aiuto per questo nella base di codice di Roslyn, ma è interno. Esiste una richiesta esistente per rendere pubbliche ITypeSymbolExtensions, quindi ho menzionato questo thread in quella richiesta e suggerito di espanderlo per includere INamedTypeSymbolExtensions.

Così sono arrivato a quanto segue che controllerà in modo ricorsivo tutte le classi per il tipo ereditato

 public class BaseClassRewriter : CSharpSyntaxRewriter { private readonly SemanticModel _model; public BaseClassRewriter(SemanticModel model) { _model = model; } public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) { var symbol = _model.GetDeclaredSymbol(node); if (InheritsFrom(symbol)) { // hit! } } private bool InheritsFrom(INamedTypeSymbol symbol) { while (true) { if (symbol.ToString() == typeof(T).FullName) { return true; } if (symbol.BaseType != null) { symbol = symbol.BaseType; continue; } break; } return false; } } 
 var classDecSynList = classDecSynList.Where(x=> (((IdentifierNameSyntax(x.BaseList.Types.FirstOrDefault())) .Identifier.ValueText=="Base")); 

Supponendo che tu abbia tutta la lista di syntax della dichiarazione di class;