From 46ac2e5c40d392a81c93448c64ea8c627a210a5f Mon Sep 17 00:00:00 2001 From: JPaja Date: Fri, 11 Feb 2022 21:16:46 +0100 Subject: [PATCH 01/14] Fix: Throw on native method body --- .../Analyzers/Definition/MethodAnalyzer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodAnalyzer.cs index 3881f4497..8e27f6de6 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodAnalyzer.cs @@ -46,7 +46,7 @@ private static void ScheduleMembersForAnalysis(AnalysisContext context, MethodDe } // Schedule method body for analysis. - if (subject.CilMethodBody is not null && context.HasAnalyzers(typeof(CilMethodBody))) + if (subject.IsIL && subject.CilMethodBody is not null && context.HasAnalyzers(typeof(CilMethodBody))) { context.ScheduleForAnalysis(subject.CilMethodBody); } From 1e92861cffcd3a3b28a73a9809e0f681d43c375e Mon Sep 17 00:00:00 2001 From: JPaja Date: Fri, 11 Feb 2022 21:27:45 +0100 Subject: [PATCH 02/14] Add: Method Specification-Definition relation --- .../Analyzers/Definition/MethodSpecificationAnalyzer.cs | 7 +++++++ src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs index efa5a157c..f00644dc5 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs @@ -25,6 +25,13 @@ protected override void Analyze(AnalysisContext context, MethodSpecification sub { context.ScheduleForAnalysis(subject.DeclaringType); } + + if (subject.Resolve() is { } definition) + { + var specification = context.Workspace.Index.GetOrCreateNode(subject); + var definitionNode = context.Workspace.Index.GetOrCreateNode(definition); + definitionNode.ForwardRelations.Add(DotNetRelations.ReferenceSpecification, specification); + } } } } diff --git a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs index f77f52605..d4ea5b351 100644 --- a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs +++ b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs @@ -47,6 +47,14 @@ public static class DotNetRelations "ReferenceMember", new Guid("ce11d2f6-a423-429d-ad37-2f073fdf63be")); + /// + /// Describes the relationship between a method definition and its specification. + /// + public static readonly ObjectRelation ReferenceSpecification = new( + "ReferenceSpecification", + new Guid("3824566f-3df4-4188-8e67-ed2d745df84a")); + + /// /// Describes the relationship between a type definition and its reference. /// From 40a1b6936b4e755353a92583a208652837d5bb0c Mon Sep 17 00:00:00 2001 From: JPaja Date: Fri, 11 Feb 2022 21:39:28 +0100 Subject: [PATCH 03/14] Fix: Avoid resolving when parent is not in workspace context --- src/AsmResolver.DotNet/MemberReference.cs | 2 ++ .../Reference/ExportedTypeAnalyzer.cs | 9 +++++++++ .../Reference/MemberReferenceAnalyzer.cs | 20 ++++++++++++++++++- .../Reference/TypeReferenceAnalyzer.cs | 9 +++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/AsmResolver.DotNet/MemberReference.cs b/src/AsmResolver.DotNet/MemberReference.cs index 000940b0a..c63450885 100644 --- a/src/AsmResolver.DotNet/MemberReference.cs +++ b/src/AsmResolver.DotNet/MemberReference.cs @@ -136,6 +136,8 @@ public IList CustomAttributes } } + public object Scope { get; set; } + /// /// Resolves the reference to a member definition. /// diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs index 1807b7e72..197278a0f 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs @@ -1,4 +1,6 @@ using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using System.Linq; namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference { @@ -7,6 +9,8 @@ namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference /// public class ExportedTypeAnalyzer : ObjectAnalyzer { + private readonly SignatureComparer _comparer = new(); + /// protected override void Analyze(AnalysisContext context, ExportedType subject) { @@ -18,6 +22,11 @@ protected override void Analyze(AnalysisContext context, ExportedType subject) if (context.Workspace is not DotNetWorkspace workspace) return; + if (subject.Scope?.GetAssembly() is not { } assembly) + return; + if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) + return; + var definition = subject.Resolve(); if (definition is not { Module: { Assembly: { } } }) return; diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs index 938daf4f1..937c43e07 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs @@ -1,4 +1,6 @@ using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using System.Linq; namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference { @@ -7,6 +9,8 @@ namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference /// public class MemberReferenceAnalyzer : ObjectAnalyzer { + private readonly SignatureComparer _comparer = new(); + /// protected override void Analyze(AnalysisContext context, MemberReference subject) { @@ -24,6 +28,11 @@ protected override void Analyze(AnalysisContext context, MemberReference subject if (context.Workspace is not DotNetWorkspace workspace) return; + if (GetParentAssembly(subject.Parent) is not { } assembly) + return; + if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) + return; + var definition = subject.Resolve(); if (definition is not { Module: { Assembly: { } } }) return; @@ -35,5 +44,14 @@ protected override void Analyze(AnalysisContext context, MemberReference subject var candidateNode = index.GetOrCreateNode(subject); node.ForwardRelations.Add(DotNetRelations.ReferenceMember, candidateNode); } - } + + private AssemblyDescriptor? GetParentAssembly(IMemberRefParent? parent) + => parent switch + { + ITypeDescriptor type => type.Scope?.GetAssembly(), + MethodDefinition method => method.Module?.Assembly, + IResolutionScope scope => scope.GetAssembly(), + _ => null + }; +} } diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs index c192427a7..a4099c9eb 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs @@ -1,4 +1,6 @@ using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using System.Linq; namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference { @@ -7,6 +9,8 @@ namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference /// public class TypeReferenceAnalyzer : ObjectAnalyzer { + private readonly SignatureComparer _comparer = new(); + /// protected override void Analyze(AnalysisContext context, TypeReference subject) { @@ -18,6 +22,11 @@ protected override void Analyze(AnalysisContext context, TypeReference subject) if (context.Workspace is not DotNetWorkspace workspace) return; + if (subject.Scope?.GetAssembly() is not { } assembly) + return; + if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) + return; + var definition = subject.Resolve(); if (definition is not { Module: { Assembly: { } } }) return; From 48a3586d66e0f8b962fc190c514785780b69a218 Mon Sep 17 00:00:00 2001 From: JPaja Date: Fri, 11 Feb 2022 21:45:04 +0100 Subject: [PATCH 04/14] Revert: MemberReference change --- src/AsmResolver.DotNet/MemberReference.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/AsmResolver.DotNet/MemberReference.cs b/src/AsmResolver.DotNet/MemberReference.cs index c63450885..000940b0a 100644 --- a/src/AsmResolver.DotNet/MemberReference.cs +++ b/src/AsmResolver.DotNet/MemberReference.cs @@ -136,8 +136,6 @@ public IList CustomAttributes } } - public object Scope { get; set; } - /// /// Resolves the reference to a member definition. /// From a1c3e3f40d3a9e375af786304d7c0819074f646d Mon Sep 17 00:00:00 2001 From: JPaja Date: Fri, 11 Feb 2022 21:51:10 +0100 Subject: [PATCH 05/14] Add: Type Definition-Specification relation --- .../Definition/MethodSpecificationAnalyzer.cs | 2 +- .../Analyzers/Definition/TypeSpecificationAnalyzer.cs | 7 +++++++ src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs | 11 +++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs index f00644dc5..558527e5b 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs @@ -30,7 +30,7 @@ protected override void Analyze(AnalysisContext context, MethodSpecification sub { var specification = context.Workspace.Index.GetOrCreateNode(subject); var definitionNode = context.Workspace.Index.GetOrCreateNode(definition); - definitionNode.ForwardRelations.Add(DotNetRelations.ReferenceSpecification, specification); + definitionNode.ForwardRelations.Add(DotNetRelations.ReferenceMethodSpecification, specification); } } } diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/TypeSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/TypeSpecificationAnalyzer.cs index f3cf5fba8..f79c6db04 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/TypeSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/TypeSpecificationAnalyzer.cs @@ -21,6 +21,13 @@ protected override void Analyze(AnalysisContext context, TypeSpecification subje { context.ScheduleForAnalysis(subject.DeclaringType); } + + if (subject.Resolve() is { } definition) + { + var specification = context.Workspace.Index.GetOrCreateNode(subject); + var definitionNode = context.Workspace.Index.GetOrCreateNode(definition); + definitionNode.ForwardRelations.Add(DotNetRelations.ReferenceTypeSpecification, specification); + } } } } diff --git a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs index d4ea5b351..825b8a2a7 100644 --- a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs +++ b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs @@ -50,8 +50,8 @@ public static class DotNetRelations /// /// Describes the relationship between a method definition and its specification. /// - public static readonly ObjectRelation ReferenceSpecification = new( - "ReferenceSpecification", + public static readonly ObjectRelation ReferenceMethodSpecification = new( + "ReferenceMethodSpecification", new Guid("3824566f-3df4-4188-8e67-ed2d745df84a")); @@ -62,6 +62,13 @@ public static class DotNetRelations "ReferenceType", new Guid("3cc86779-338c-4165-a00c-da547a2e8549")); + /// + /// Describes the relationship between a type definition and its specification. + /// + public static readonly ObjectRelation ReferenceTypeSpecification = new( + "ReferenceTypeSpecification", + new Guid("e60a2deb-b608-4775-93ad-c073eac934e5")); + /// /// Describes the relationship between a exported type and its definition. /// From dda44b34996b26b29ea4c31057df9debe8bf2d10 Mon Sep 17 00:00:00 2001 From: JPaja Date: Fri, 11 Feb 2022 22:06:20 +0100 Subject: [PATCH 06/14] Add: TypeSpecification worksapce test --- .../ReferenceRelationTest.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs index 386c136e5..7df0226c8 100644 --- a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs +++ b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs @@ -189,6 +189,47 @@ public void MethodTest() node.ForwardRelations.GetObjects(DotNetRelations.ReferenceMember)); } + + [Fact] + public void TypeSpecificationTest() + { + var assembly1 = new AssemblyDefinition("Assembly1", new Version(1, 0, 0, 0)); + var module1 = new ModuleDefinition("Assembly1"); + var assembly2 = new AssemblyDefinition("Assembly1", new Version(1, 0, 0, 0)); + var module2 = new ModuleDefinition("Assembly2"); + + var type1 = new TypeDefinition("Namespace", "Type", TypeAttributes.Class); + var type2 = new TypeDefinition("Namespace", "Type2", TypeAttributes.Class); + + var factory = module2.CorLibTypeFactory; + var method = new MethodDefinition("Method", MethodAttributes.Static, MethodSignature.CreateInstance(factory.Void)); + var body = new CilMethodBody(method); + + assembly1.Modules.Add(module1); + assembly2.Modules.Add(module2); + + module1.TopLevelTypes.Add(type1); + module2.TopLevelTypes.Add(type2); + + type2.Methods.Add(method); + + var typeSpecification = new TypeSpecification(type1.ToTypeSignature()); + + body.Instructions.Add(new CilInstruction(CilOpCodes.Sizeof, typeSpecification)); + body.Instructions.Add(new CilInstruction(CilOpCodes.Pop)); + method.MethodBody = body; + + var workspace = new DotNetWorkspace(); + workspace.Assemblies.Add(assembly1); + workspace.Assemblies.Add(assembly2); + + workspace.Analyze(); + + var node = workspace.Index.GetOrCreateNode(type1); + Assert.Contains(typeSpecification, + node.ForwardRelations.GetObjects(DotNetRelations.ReferenceTypeSpecification)); + } + [Fact] public void FieldTest() { From 26e4f122f38a30c8e3e872aabea7445760390b2d Mon Sep 17 00:00:00 2001 From: JPaja Date: Fri, 11 Feb 2022 22:16:40 +0100 Subject: [PATCH 07/14] Add: MethodSpecification worksapce test --- .../ReferenceRelationTest.cs | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs index 7df0226c8..afc5e4ef6 100644 --- a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs +++ b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs @@ -189,7 +189,6 @@ public void MethodTest() node.ForwardRelations.GetObjects(DotNetRelations.ReferenceMember)); } - [Fact] public void TypeSpecificationTest() { @@ -230,6 +229,53 @@ public void TypeSpecificationTest() node.ForwardRelations.GetObjects(DotNetRelations.ReferenceTypeSpecification)); } + [Fact] + public void MethodSpecificationTest() + { + var assembly1 = new AssemblyDefinition("Assembly1", new Version(1, 0, 0, 0)); + var module1 = new ModuleDefinition("Assembly1"); + var assembly2 = new AssemblyDefinition("Assembly1", new Version(1, 0, 0, 0)); + var module2 = new ModuleDefinition("Assembly2"); + + var type1 = new TypeDefinition("Namespace", "Type", TypeAttributes.Class); + var type2 = new TypeDefinition("Namespace", "Type2", TypeAttributes.Class); + + var factory = module2.CorLibTypeFactory; + var method1 = new MethodDefinition("Method1", MethodAttributes.Static, MethodSignature.CreateInstance(factory.Void)); + var method2 = new MethodDefinition("Method2", MethodAttributes.Static, MethodSignature.CreateInstance(factory.Void)); + var body = new CilMethodBody(method2); + + assembly1.Modules.Add(module1); + assembly2.Modules.Add(module2); + + module1.TopLevelTypes.Add(type1); + module2.TopLevelTypes.Add(type2); + + type1.Methods.Add(method1); + type2.Methods.Add(method2); + + var typeSpecification = new TypeSpecification(type1.ToTypeSignature()); + var methodRef = new MemberReference(typeSpecification, method1.Name, method1.Signature); + var mehtodSpecification = new MethodSpecification(methodRef, new GenericInstanceMethodSignature()); + + body.Instructions.Add(new CilInstruction(CilOpCodes.Call, mehtodSpecification)); + method2.MethodBody = body; + + var workspace = new DotNetWorkspace(); + workspace.Assemblies.Add(assembly1); + workspace.Assemblies.Add(assembly2); + + workspace.Analyze(); + + var typeNode = workspace.Index.GetOrCreateNode(type1); + var methodNode = workspace.Index.GetOrCreateNode(method1); + + Assert.Contains(mehtodSpecification, + methodNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceMethodSpecification)); + Assert.Contains(typeSpecification, + typeNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceTypeSpecification)); + } + [Fact] public void FieldTest() { From 03c89aed646088ef339a4214b8aefad74ab50dda Mon Sep 17 00:00:00 2001 From: JPaja Date: Sat, 19 Feb 2022 14:22:45 +0100 Subject: [PATCH 08/14] Fix: MethodSpecification relation --- .../Analyzers/Definition/MethodSpecificationAnalyzer.cs | 4 ++-- src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs index 558527e5b..0ba54b0bc 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs @@ -26,10 +26,10 @@ protected override void Analyze(AnalysisContext context, MethodSpecification sub context.ScheduleForAnalysis(subject.DeclaringType); } - if (subject.Resolve() is { } definition) + if (subject.Method is not null) { var specification = context.Workspace.Index.GetOrCreateNode(subject); - var definitionNode = context.Workspace.Index.GetOrCreateNode(definition); + var definitionNode = context.Workspace.Index.GetOrCreateNode(subject.Method); definitionNode.ForwardRelations.Add(DotNetRelations.ReferenceMethodSpecification, specification); } } diff --git a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs index 825b8a2a7..98ff59915 100644 --- a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs +++ b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs @@ -48,9 +48,9 @@ public static class DotNetRelations new Guid("ce11d2f6-a423-429d-ad37-2f073fdf63be")); /// - /// Describes the relationship between a method definition and its specification. + /// Describes the relationship between a method and its specification. /// - public static readonly ObjectRelation ReferenceMethodSpecification = new( + public static readonly ObjectRelation ReferenceMethodSpecification = new( "ReferenceMethodSpecification", new Guid("3824566f-3df4-4188-8e67-ed2d745df84a")); From 3f55f6c317ba8492c0cb97ecb6c12df9d53c4b48 Mon Sep 17 00:00:00 2001 From: JPaja Date: Sat, 19 Feb 2022 15:33:09 +0100 Subject: [PATCH 09/14] Fix: MethodSpecification variable name --- .../Analyzers/Definition/MethodSpecificationAnalyzer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs index 0ba54b0bc..53f9938fe 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs @@ -29,8 +29,8 @@ protected override void Analyze(AnalysisContext context, MethodSpecification sub if (subject.Method is not null) { var specification = context.Workspace.Index.GetOrCreateNode(subject); - var definitionNode = context.Workspace.Index.GetOrCreateNode(subject.Method); - definitionNode.ForwardRelations.Add(DotNetRelations.ReferenceMethodSpecification, specification); + var methodNode = context.Workspace.Index.GetOrCreateNode(subject.Method); + methodNode.ForwardRelations.Add(DotNetRelations.ReferenceMethodSpecification, specification); } } } From 89a6a306d81d810e413468086c4a48e64fa65dcf Mon Sep 17 00:00:00 2001 From: JPaja Date: Sat, 19 Feb 2022 16:20:42 +0100 Subject: [PATCH 10/14] Move MethodSpecification to Reference folder --- .../{Definition => Reference}/MethodSpecificationAnalyzer.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/AsmResolver.Workspaces.DotNet/Analyzers/{Definition => Reference}/MethodSpecificationAnalyzer.cs (100%) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs similarity index 100% rename from src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/MethodSpecificationAnalyzer.cs rename to src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs From 102faf9296d4a5314d4110472a0eb77aecebbd9a Mon Sep 17 00:00:00 2001 From: JPaja Date: Sat, 19 Feb 2022 16:20:59 +0100 Subject: [PATCH 11/14] Optimize TypeSpeicifaction Resolve and move to Reference folder --- .../TypeSpecificationAnalyzer.cs | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) rename src/AsmResolver.Workspaces.DotNet/Analyzers/{Definition => Reference}/TypeSpecificationAnalyzer.cs (51%) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/TypeSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs similarity index 51% rename from src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/TypeSpecificationAnalyzer.cs rename to src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs index f79c6db04..d739a693d 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Definition/TypeSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs @@ -1,3 +1,4 @@ +using System.Linq; using AsmResolver.DotNet; using AsmResolver.DotNet.Signatures; using AsmResolver.DotNet.Signatures.Types; @@ -9,9 +10,12 @@ namespace AsmResolver.Workspaces.DotNet.Analyzers.Definition /// public class TypeSpecificationAnalyzer : ObjectAnalyzer { + private readonly SignatureComparer _comparer = new(); + /// protected override void Analyze(AnalysisContext context, TypeSpecification subject) { + if (subject.Signature is not null && context.HasAnalyzers(typeof(TypeSignature))) { context.ScheduleForAnalysis(subject.Signature); @@ -22,12 +26,23 @@ protected override void Analyze(AnalysisContext context, TypeSpecification subje context.ScheduleForAnalysis(subject.DeclaringType); } - if (subject.Resolve() is { } definition) - { - var specification = context.Workspace.Index.GetOrCreateNode(subject); - var definitionNode = context.Workspace.Index.GetOrCreateNode(definition); - definitionNode.ForwardRelations.Add(DotNetRelations.ReferenceTypeSpecification, specification); - } + if (context.Workspace is not DotNetWorkspace workspace) + return; + + if (subject.Scope?.GetAssembly() is not { } assembly) + return; + if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) + return; + + var definition = subject.Resolve(); + if (definition is not { Module: { Assembly: { } } }) + return; + if (!workspace.Assemblies.Contains(definition.Module.Assembly)) + return; + + var specification = context.Workspace.Index.GetOrCreateNode(subject); + var typeNode = context.Workspace.Index.GetOrCreateNode(definition); + typeNode.ForwardRelations.Add(DotNetRelations.ReferenceTypeSpecification, specification); } } } From 602f06bc6f4cbb7d06f999ca3adccfcf0d74d8bc Mon Sep 17 00:00:00 2001 From: JPaja Date: Sat, 19 Feb 2022 19:36:24 +0100 Subject: [PATCH 12/14] Fix: Specification Analyzers --- .../Reference/MethodSpecificationAnalyzer.cs | 3 +-- .../Analyzers/Reference/TypeSpecificationAnalyzer.cs | 4 ++-- src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs | 11 ++--------- .../ReferenceRelationTest.cs | 8 +++++--- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs index 53f9938fe..b11082dd3 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs @@ -1,8 +1,7 @@ using AsmResolver.DotNet; using AsmResolver.DotNet.Signatures; -using AsmResolver.DotNet.Signatures.Types; -namespace AsmResolver.Workspaces.DotNet.Analyzers.Definition +namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference { /// /// Provides a default implementation for an analyzer. diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs index d739a693d..89cdab5ad 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs @@ -3,7 +3,7 @@ using AsmResolver.DotNet.Signatures; using AsmResolver.DotNet.Signatures.Types; -namespace AsmResolver.Workspaces.DotNet.Analyzers.Definition +namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference { /// /// Provides a default implementation for an analyzer. @@ -42,7 +42,7 @@ protected override void Analyze(AnalysisContext context, TypeSpecification subje var specification = context.Workspace.Index.GetOrCreateNode(subject); var typeNode = context.Workspace.Index.GetOrCreateNode(definition); - typeNode.ForwardRelations.Add(DotNetRelations.ReferenceTypeSpecification, specification); + typeNode.ForwardRelations.Add(DotNetRelations.ReferenceType, specification); } } } diff --git a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs index 98ff59915..83114d429 100644 --- a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs +++ b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs @@ -56,19 +56,12 @@ public static class DotNetRelations /// - /// Describes the relationship between a type definition and its reference. + /// Describes the relationship between a type definition and its reference or specification. /// - public static readonly ObjectRelation ReferenceType = new( + public static readonly ObjectRelation ReferenceType = new( "ReferenceType", new Guid("3cc86779-338c-4165-a00c-da547a2e8549")); - /// - /// Describes the relationship between a type definition and its specification. - /// - public static readonly ObjectRelation ReferenceTypeSpecification = new( - "ReferenceTypeSpecification", - new Guid("e60a2deb-b608-4775-93ad-c073eac934e5")); - /// /// Describes the relationship between a exported type and its definition. /// diff --git a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs index afc5e4ef6..eb3d7ba7b 100644 --- a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs +++ b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs @@ -226,7 +226,7 @@ public void TypeSpecificationTest() var node = workspace.Index.GetOrCreateNode(type1); Assert.Contains(typeSpecification, - node.ForwardRelations.GetObjects(DotNetRelations.ReferenceTypeSpecification)); + node.ForwardRelations.GetObjects(DotNetRelations.ReferenceType)); } [Fact] @@ -270,10 +270,12 @@ public void MethodSpecificationTest() var typeNode = workspace.Index.GetOrCreateNode(type1); var methodNode = workspace.Index.GetOrCreateNode(method1); + var methodRefNode = methodNode.ForwardRelations.GetNodes(DotNetRelations.ReferenceMember).First(); + Assert.Contains(mehtodSpecification, - methodNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceMethodSpecification)); + methodRefNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceMethodSpecification)); Assert.Contains(typeSpecification, - typeNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceTypeSpecification)); + typeNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceType)); } [Fact] From 91eef33234d63de002a0cc696d42d42807774bc9 Mon Sep 17 00:00:00 2001 From: JPaja Date: Tue, 22 Feb 2022 00:48:38 +0100 Subject: [PATCH 13/14] Clean up reference analyzers --- .../Analyzers/AnalyzerUtilities.cs | 17 +++++++++++++ .../Reference/AssemblyReferenceAnalyzer.cs | 5 ++-- .../Reference/ExportedTypeAnalyzer.cs | 13 ++-------- .../Reference/MemberReferenceAnalyzer.cs | 25 +++---------------- .../Reference/TypeReferenceAnalyzer.cs | 13 ++-------- .../Reference/TypeSpecificationAnalyzer.cs | 13 ++-------- 6 files changed, 29 insertions(+), 57 deletions(-) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/AnalyzerUtilities.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/AnalyzerUtilities.cs index 52fa73a17..7bc93f796 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/AnalyzerUtilities.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/AnalyzerUtilities.cs @@ -55,5 +55,22 @@ internal static IEnumerable FindBaseMethods(this MethodDefinit } } } + + public static AssemblyDescriptor? GetAssembly(IMetadataMember member) => member switch + { + AssemblyDescriptor assembly => assembly, + MemberReference {Parent: { } parent} => GetAssembly(parent), + ITypeDescriptor {Scope: { } scope} => scope.GetAssembly(), + IResolutionScope scope => scope.GetAssembly(), + IModuleProvider {Module: {Assembly: { } assembly}} => assembly, + _ => null + }; + + public static bool ContainsSubjectAssembly(this Workspace workspace, IMetadataMember member) + => workspace is DotNetWorkspace dotNetWorkspace + && GetAssembly(member) is { } assembly + && dotNetWorkspace.Assemblies + .Any(a => _comparer.Equals(a, assembly)); + } } diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/AssemblyReferenceAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/AssemblyReferenceAnalyzer.cs index aebdca457..efc5c46a9 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/AssemblyReferenceAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/AssemblyReferenceAnalyzer.cs @@ -13,8 +13,9 @@ protected override void Analyze(AnalysisContext context, AssemblyReference subje if (context.Workspace is not DotNetWorkspace workspace) return; - var definition = subject.Resolve(); - if (definition is null || !workspace.Assemblies.Contains(definition)) + if(!context.Workspace.ContainsSubjectAssembly(subject)) + return; + if (subject.Resolve() is not {} definition) return; var index = context.Workspace.Index; diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs index 197278a0f..71cec661a 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/ExportedTypeAnalyzer.cs @@ -19,18 +19,9 @@ protected override void Analyze(AnalysisContext context, ExportedType subject) context.ScheduleForAnalysis(subject.DeclaringType); } - if (context.Workspace is not DotNetWorkspace workspace) + if(!context.Workspace.ContainsSubjectAssembly(subject)) return; - - if (subject.Scope?.GetAssembly() is not { } assembly) - return; - if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) - return; - - var definition = subject.Resolve(); - if (definition is not { Module: { Assembly: { } } }) - return; - if (!workspace.Assemblies.Contains(definition.Module.Assembly)) + if (subject.Resolve() is not {} definition) return; var index = context.Workspace.Index; diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs index 937c43e07..7a011b54d 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MemberReferenceAnalyzer.cs @@ -9,7 +9,6 @@ namespace AsmResolver.Workspaces.DotNet.Analyzers.Reference /// public class MemberReferenceAnalyzer : ObjectAnalyzer { - private readonly SignatureComparer _comparer = new(); /// protected override void Analyze(AnalysisContext context, MemberReference subject) @@ -25,33 +24,15 @@ protected override void Analyze(AnalysisContext context, MemberReference subject context.ScheduleForAnalysis(subject.Signature); } - if (context.Workspace is not DotNetWorkspace workspace) + if(!context.Workspace.ContainsSubjectAssembly(subject)) return; - - if (GetParentAssembly(subject.Parent) is not { } assembly) - return; - if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) - return; - - var definition = subject.Resolve(); - if (definition is not { Module: { Assembly: { } } }) + if (subject.Resolve() is not {} definition) return; - if (!workspace.Assemblies.Contains(definition.Module.Assembly)) - return; //TODO: Maybe add some warning log? var index = context.Workspace.Index; var node = index.GetOrCreateNode(definition); var candidateNode = index.GetOrCreateNode(subject); node.ForwardRelations.Add(DotNetRelations.ReferenceMember, candidateNode); } - - private AssemblyDescriptor? GetParentAssembly(IMemberRefParent? parent) - => parent switch - { - ITypeDescriptor type => type.Scope?.GetAssembly(), - MethodDefinition method => method.Module?.Assembly, - IResolutionScope scope => scope.GetAssembly(), - _ => null - }; -} + } } diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs index a4099c9eb..99bba5505 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeReferenceAnalyzer.cs @@ -19,18 +19,9 @@ protected override void Analyze(AnalysisContext context, TypeReference subject) context.ScheduleForAnalysis(subject.DeclaringType); } - if (context.Workspace is not DotNetWorkspace workspace) + if(!context.Workspace.ContainsSubjectAssembly(subject)) return; - - if (subject.Scope?.GetAssembly() is not { } assembly) - return; - if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) - return; - - var definition = subject.Resolve(); - if (definition is not { Module: { Assembly: { } } }) - return; - if (!workspace.Assemblies.Contains(definition.Module.Assembly)) + if (subject.Resolve() is not {} definition) return; var index = context.Workspace.Index; diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs index 89cdab5ad..fdd8a06a4 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/TypeSpecificationAnalyzer.cs @@ -26,18 +26,9 @@ protected override void Analyze(AnalysisContext context, TypeSpecification subje context.ScheduleForAnalysis(subject.DeclaringType); } - if (context.Workspace is not DotNetWorkspace workspace) + if(!context.Workspace.ContainsSubjectAssembly(subject)) return; - - if (subject.Scope?.GetAssembly() is not { } assembly) - return; - if (!workspace.Assemblies.Any(a => _comparer.Equals(a, assembly))) - return; - - var definition = subject.Resolve(); - if (definition is not { Module: { Assembly: { } } }) - return; - if (!workspace.Assemblies.Contains(definition.Module.Assembly)) + if (subject.Resolve() is not {} definition) return; var specification = context.Workspace.Index.GetOrCreateNode(subject); From b2f90d29d3308055a8823be3590af6631b0f1293 Mon Sep 17 00:00:00 2001 From: JPaja Date: Thu, 24 Feb 2022 22:44:13 +0100 Subject: [PATCH 14/14] Fix: MethodSpecification relation --- .../Reference/MethodSpecificationAnalyzer.cs | 2 +- src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs | 12 +++--------- .../ReferenceRelationTest.cs | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs index b11082dd3..aa477d6c3 100644 --- a/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs +++ b/src/AsmResolver.Workspaces.DotNet/Analyzers/Reference/MethodSpecificationAnalyzer.cs @@ -29,7 +29,7 @@ protected override void Analyze(AnalysisContext context, MethodSpecification sub { var specification = context.Workspace.Index.GetOrCreateNode(subject); var methodNode = context.Workspace.Index.GetOrCreateNode(subject.Method); - methodNode.ForwardRelations.Add(DotNetRelations.ReferenceMethodSpecification, specification); + methodNode.ForwardRelations.Add(DotNetRelations.ReferenceMember, specification); } } } diff --git a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs index 83114d429..a938335fe 100644 --- a/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs +++ b/src/AsmResolver.Workspaces.DotNet/DotNetRelations.cs @@ -41,19 +41,13 @@ public static class DotNetRelations new Guid("52a81339-0850-4f81-b059-30d7aacc430f")); /// - /// Describes the relationship between a method or field definition and its reference. + /// Describes the relationship between a method or field definition and its reference + /// or method definition/reference to its specification. /// - public static readonly ObjectRelation ReferenceMember = new( + public static readonly ObjectRelation ReferenceMember = new( "ReferenceMember", new Guid("ce11d2f6-a423-429d-ad37-2f073fdf63be")); - /// - /// Describes the relationship between a method and its specification. - /// - public static readonly ObjectRelation ReferenceMethodSpecification = new( - "ReferenceMethodSpecification", - new Guid("3824566f-3df4-4188-8e67-ed2d745df84a")); - /// /// Describes the relationship between a type definition and its reference or specification. diff --git a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs index eb3d7ba7b..4aef2b5d7 100644 --- a/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs +++ b/test/AsmResolver.Workspaces.DotNet.Tests/ReferenceRelationTest.cs @@ -273,7 +273,7 @@ public void MethodSpecificationTest() var methodRefNode = methodNode.ForwardRelations.GetNodes(DotNetRelations.ReferenceMember).First(); Assert.Contains(mehtodSpecification, - methodRefNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceMethodSpecification)); + methodRefNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceMember)); Assert.Contains(typeSpecification, typeNode.ForwardRelations.GetObjects(DotNetRelations.ReferenceType)); }