.netdecompilingicsharpcodeilspy

ICSharpCode Decompiler get from TypeReferenceExpression to TypeDeclaration?


I'm using ICSharpCode.Decompiler.Ast.AstBuilder (which is used by SharpDevelop, NRefactory and ILSpy under the hood; has taken inspiration from there too) from code to build an abstract syntax tree from a .NET Common Intermediate Language assembly.

var assembly = AssemblyDefinition.ReadAssembly(assemblyPath);
var astBuilder = new AstBuilder(new DecompilerContext(assembly.MainModule));
astBuilder.AddAssembly(assembly);
// astBuilder.SyntaxTree ...

The syntax tree contains TypeReferenceExpressions whenever a line like Math.Abs() is there. How can I retrieve the TypeDeclaration of the referenced type when it also exists in the same syntax tree?

The closest I got is TypeReferenceExpression.Type.ToTypeReference().Resolve() but this is very heavy to orchestrate, and I already have (I suppose) all the information in the syntax tree. I also tried manual lookup by using namespaces an identifiers but I guess there should be a better way.


Solution

  • You can use SyntaxTree.GetTypes() to enumerate all decompiled types. Since that's rather heavy, I'd build up a reference-to-declaration lookup, e.g.:

    var assembly = AssemblyDefinition.ReadAssembly(assemblyPath);
    var astBuilder = new AstBuilder(new DecompilerContext(assembly.MainModule));
    
    astBuilder.AddAssembly(assembly);
    
    var ast = astBuilder.SyntaxTree;
    
    var lookup = ast.GetTypes(true)
                    .ToDictionary(d => (TypeReference)d.Annotation<TypeDefinition>());
    

    You can then fetch the TypeReference from your TypeReferenceExpression and use it to find the type's declaration in the lookup:

    TypeReferenceExpression e = /* ... */;
    TypeDeclaration declaration;
    
    if (lookup.TryGetValue(e.Type.Annotation<TypeReference>(), out declaration))
        Console.WriteLine(declaration.GetText());  // do whatever