Skip to content

Commit

Permalink
Fix: Implementation base type gathering
Browse files Browse the repository at this point in the history
  • Loading branch information
JPaja committed Oct 16, 2021
1 parent 3f2b44d commit a8677f6
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,38 @@ internal static class ImplementationAnalyzerUtilities
{
private static readonly SignatureComparer _comparer = new ();

private static IEnumerable<ITypeDefOrRef> GetBaseTypes(WorkspaceIndexNode baseNode)
{
var visited = new HashSet<WorkspaceIndexNode>();
var agenda = new Queue<WorkspaceIndexNode>();
agenda.Enqueue(baseNode);
while (agenda.Count != 0)
{
var node = agenda.Dequeue();
if(!visited.Add(node))
continue;
var baseTypeNodes = node.ForwardRelations.GetNodes(DotNetRelations.BaseType);
foreach (var baseTypeNode in baseTypeNodes)
{
var baseType = (ITypeDefOrRef)baseTypeNode.Subject;
agenda.Enqueue(baseTypeNode);
var baseTypeDefinitions = baseTypeNode.BackwardRelations.GetNodes(DotNetRelations.ReferenceType);
foreach (var baseTypeDefinition in baseTypeDefinitions)
agenda.Enqueue(baseTypeDefinition);
yield return baseType;
}
}
}

internal static IEnumerable<MethodDefinition> FindBaseMethods(this MethodDefinition subject,
WorkspaceIndex index)
{
if (subject.DeclaringType is not { } declaringType)
yield break;

var baseTypes = index
.GetOrCreateNode(declaringType) // Get indexed declaring type.
.ForwardRelations.GetObjects(DotNetRelations.BaseType) // Get types that this declaring type is implementing.
.ToArray();
var declaringTypeNode = index.GetOrCreateNode(declaringType);

var baseTypes = GetBaseTypes(declaringTypeNode).ToArray();

foreach (var baseType in baseTypes)
{
Expand Down
4 changes: 2 additions & 2 deletions src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ public static class DotNetRelations
new Guid("ce11d2f6-a423-429d-ad37-2f073fdf63be"));

/// <summary>
/// Describes the relationship between a type definition and its reference.
/// Describes the relationship between a type definition and its reference or specification.
/// </summary>
public static readonly ObjectRelation<TypeDefinition, TypeReference> ReferenceType = new(
public static readonly ObjectRelation<TypeDefinition, ITypeDefOrRef> ReferenceType = new(
"ReferenceType",
new Guid("3cc86779-338c-4165-a00c-da547a2e8549"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,23 @@ public void InterfaceImplementation()
var abstractMethod = abstractType.Methods.First(m=>m.Name == nameof(MyAboveAbstractClass.TestAboveAbstract));

var implType1 = (TypeDefinition)module.LookupMember(typeof(MyDerivedAboveClass).MetadataToken);
var implMethod1 = abstractType.Methods.First(m => m.Name == nameof(MyAboveAbstractClass.TestAboveAbstract));
var implMethod1 = implType1.Methods.First(m => m.Name == nameof(MyAboveAbstractClass.TestAboveAbstract));

var implType2 = (TypeDefinition)module.LookupMember(typeof(MyDerivedInbetweenClass).MetadataToken);
var implMethod2 = abstractType.Methods.First(m => m.Name == nameof(MyAboveAbstractClass.TestAboveAbstract));
var implMethod2 = implType2.Methods.First(m => m.Name == nameof(MyAboveAbstractClass.TestAboveAbstract));

var implType3 = (TypeDefinition)module.LookupMember(typeof(MyDerivedClassGeneric).MetadataToken);
var implMethod3 = abstractType.Methods.First(m => m.Name == nameof(MyAboveAbstractClass.TestAboveAbstract));
var implMethod3 = implType3.Methods.First(m => m.Name == nameof(MyAboveAbstractClass.TestAboveAbstract));


var workspace = new DotNetWorkspace();
workspace.Assemblies.Add(_fixture.WorkspacesAssembly);
workspace.Analyze();

var node = workspace.Index.GetOrCreateNode(abstractMethod);
var implMethods = node.BackwardRelations.GetObjects(DotNetRelations.ImplementationMethod);
var implMethods = node.BackwardRelations.GetObjects(DotNetRelations.ImplementationMethod).ToArray();

Assert.Equal(3, implMethods.Length);
Assert.Contains(implMethod1, implMethods);
Assert.Contains(implMethod2, implMethods);
Assert.Contains(implMethod3, implMethods);
Expand Down

0 comments on commit a8677f6

Please sign in to comment.