Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Java.Interop.Tools.*] IMetadataResolver not TypeDefinitionCache #842

Merged
merged 1 commit into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@ public static class MethodDefinitionRocks
{
[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static MethodDefinition GetBaseDefinition (this MethodDefinition method) =>
GetBaseDefinition (method, cache: null);
GetBaseDefinition (method, resolver: null);

public static MethodDefinition GetBaseDefinition (this MethodDefinition method, TypeDefinitionCache? cache)
public static MethodDefinition GetBaseDefinition (this MethodDefinition method, TypeDefinitionCache? cache) =>
GetBaseDefinition (method, (IMetadataResolver?) cache);

public static MethodDefinition GetBaseDefinition (this MethodDefinition method, IMetadataResolver? resolver)
{
if (method.IsStatic || method.IsNewSlot || !method.IsVirtual)
return method;

foreach (var baseType in method.DeclaringType.GetBaseTypes (cache)) {
foreach (var baseType in method.DeclaringType.GetBaseTypes (resolver)) {
foreach (var m in baseType.Methods) {
if (!m.IsConstructor &&
m.Name == method.Name &&
(m.IsVirtual || m.IsAbstract) &&
AreParametersCompatibleWith (m.Parameters, method.Parameters, cache)) {
AreParametersCompatibleWith (m.Parameters, method.Parameters, resolver)) {
return m;
}
}
Expand All @@ -33,14 +36,17 @@ public static MethodDefinition GetBaseDefinition (this MethodDefinition method,

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static IEnumerable<MethodDefinition> GetOverriddenMethods (MethodDefinition method, bool inherit) =>
GetOverriddenMethods (method, inherit, cache: null);
GetOverriddenMethods (method, inherit, resolver: null);

public static IEnumerable<MethodDefinition> GetOverriddenMethods (MethodDefinition method, bool inherit, TypeDefinitionCache? cache) =>
GetOverriddenMethods (method, inherit, (IMetadataResolver?) cache);

public static IEnumerable<MethodDefinition> GetOverriddenMethods (MethodDefinition method, bool inherit, TypeDefinitionCache? cache)
public static IEnumerable<MethodDefinition> GetOverriddenMethods (MethodDefinition method, bool inherit, IMetadataResolver? resolver)
{
yield return method;
if (inherit) {
MethodDefinition baseMethod = method;
while ((baseMethod = method.GetBaseDefinition (cache)) != null && baseMethod != method) {
while ((baseMethod = method.GetBaseDefinition (resolver)) != null && baseMethod != method) {
yield return method;
method = baseMethod;
}
Expand All @@ -49,9 +55,12 @@ public static IEnumerable<MethodDefinition> GetOverriddenMethods (MethodDefiniti

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static bool AreParametersCompatibleWith (this Collection<ParameterDefinition> a, Collection<ParameterDefinition> b) =>
AreParametersCompatibleWith (a, b, cache: null);
AreParametersCompatibleWith (a, b, resolver: null);

public static bool AreParametersCompatibleWith (this Collection<ParameterDefinition> a, Collection<ParameterDefinition> b, TypeDefinitionCache? cache) =>
AreParametersCompatibleWith (a, b, (IMetadataResolver?) cache);

public static bool AreParametersCompatibleWith (this Collection<ParameterDefinition> a, Collection<ParameterDefinition> b, TypeDefinitionCache? cache)
public static bool AreParametersCompatibleWith (this Collection<ParameterDefinition> a, Collection<ParameterDefinition> b, IMetadataResolver? resolver)
{
if (a.Count != b.Count)
return false;
Expand All @@ -60,21 +69,21 @@ public static bool AreParametersCompatibleWith (this Collection<ParameterDefinit
return true;

for (int i = 0; i < a.Count; i++)
if (!IsParameterCompatibleWith (a [i].ParameterType, b [i].ParameterType, cache))
if (!IsParameterCompatibleWith (a [i].ParameterType, b [i].ParameterType, resolver))
return false;

return true;
}

static bool IsParameterCompatibleWith (IModifierType a, IModifierType b, TypeDefinitionCache? cache)
static bool IsParameterCompatibleWith (IModifierType a, IModifierType b, IMetadataResolver? cache)
{
if (!IsParameterCompatibleWith (a.ModifierType, b.ModifierType, cache))
return false;

return IsParameterCompatibleWith (a.ElementType, b.ElementType, cache);
}

static bool IsParameterCompatibleWith (TypeSpecification a, TypeSpecification b, TypeDefinitionCache? cache)
static bool IsParameterCompatibleWith (TypeSpecification a, TypeSpecification b, IMetadataResolver? cache)
{
if (a is GenericInstanceType)
return IsParameterCompatibleWith ((GenericInstanceType) a, (GenericInstanceType) b, cache);
Expand All @@ -85,7 +94,7 @@ static bool IsParameterCompatibleWith (TypeSpecification a, TypeSpecification b,
return IsParameterCompatibleWith (a.ElementType, b.ElementType, cache);
}

static bool IsParameterCompatibleWith (GenericInstanceType a, GenericInstanceType b, TypeDefinitionCache? cache)
static bool IsParameterCompatibleWith (GenericInstanceType a, GenericInstanceType b, IMetadataResolver? cache)
{
if (!IsParameterCompatibleWith (a.ElementType, b.ElementType, cache))
return false;
Expand All @@ -103,7 +112,7 @@ static bool IsParameterCompatibleWith (GenericInstanceType a, GenericInstanceTyp
return true;
}

static bool IsParameterCompatibleWith (TypeReference a, TypeReference b, TypeDefinitionCache? cache)
static bool IsParameterCompatibleWith (TypeReference a, TypeReference b, IMetadataResolver? cache)
{
if (a is TypeSpecification || b is TypeSpecification) {
if (a.GetType () != b.GetType ())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
using System.Collections.Generic;
using Mono.Cecil;

using Java.Interop.Tools.Diagnostics;

namespace Java.Interop.Tools.Cecil
{
/// <summary>
/// A class for caching lookups from TypeReference -> TypeDefinition.
/// Generally its lifetime should match an AssemblyResolver instance.
/// </summary>
public class TypeDefinitionCache
public class TypeDefinitionCache : IMetadataResolver
{
readonly Dictionary<TypeReference, TypeDefinition> cache = new Dictionary<TypeReference, TypeDefinition> ();
readonly Dictionary<TypeReference, TypeDefinition?> types = new Dictionary<TypeReference, TypeDefinition?> ();
readonly Dictionary<FieldReference, FieldDefinition?> fields = new Dictionary<FieldReference, FieldDefinition?> ();
readonly Dictionary<MethodReference, MethodDefinition?> methods = new Dictionary<MethodReference, MethodDefinition?> ();

public virtual TypeDefinition Resolve (TypeReference typeReference)
public virtual TypeDefinition? Resolve (TypeReference typeReference)
{
if (cache.TryGetValue (typeReference, out var typeDefinition))
if (types.TryGetValue (typeReference, out var typeDefinition))
return typeDefinition;
return cache [typeReference] = typeReference.Resolve ();
return types [typeReference] = typeReference.Resolve ();
}

public virtual FieldDefinition? Resolve (FieldReference field)
{
if (fields.TryGetValue (field, out var fieldDefinition))
return fieldDefinition;
return fields [field] = field.Resolve ();
}

public virtual MethodDefinition? Resolve (MethodReference method)
{
if (methods.TryGetValue (method, out var methodDefinition))
return methodDefinition;
return methods [method] = method.Resolve ();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,62 +9,74 @@ public static class TypeDefinitionRocks {

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static TypeDefinition? GetBaseType (this TypeDefinition type) =>
GetBaseType (type, cache: null);
GetBaseType (type, resolver: null);

public static TypeDefinition? GetBaseType (this TypeDefinition type, TypeDefinitionCache? cache)
public static TypeDefinition? GetBaseType (this TypeDefinition type, TypeDefinitionCache? cache) =>
GetBaseType (type, (IMetadataResolver?) cache);

public static TypeDefinition? GetBaseType (this TypeDefinition type, IMetadataResolver? resolver)
{
var bt = type.BaseType;
if (bt == null)
return null;
if (cache != null)
return cache.Resolve (bt);
if (resolver != null)
return resolver.Resolve (bt);
return bt.Resolve ();
}

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static IEnumerable<TypeDefinition> GetTypeAndBaseTypes (this TypeDefinition type) =>
GetTypeAndBaseTypes (type, cache: null);
GetTypeAndBaseTypes (type, resolver: null);

public static IEnumerable<TypeDefinition> GetTypeAndBaseTypes (this TypeDefinition type, TypeDefinitionCache? cache) =>
GetTypeAndBaseTypes (type, (IMetadataResolver?) cache);

public static IEnumerable<TypeDefinition> GetTypeAndBaseTypes (this TypeDefinition type, TypeDefinitionCache? cache)
public static IEnumerable<TypeDefinition> GetTypeAndBaseTypes (this TypeDefinition type, IMetadataResolver? resolver)
{
TypeDefinition? t = type;

while (t != null) {
yield return t;
t = t.GetBaseType (cache);
t = t.GetBaseType (resolver);
}
}

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static IEnumerable<TypeDefinition> GetBaseTypes (this TypeDefinition type) =>
GetBaseTypes (type, cache: null);
GetBaseTypes (type, resolver: null);

public static IEnumerable<TypeDefinition> GetBaseTypes (this TypeDefinition type, TypeDefinitionCache? cache)
public static IEnumerable<TypeDefinition> GetBaseTypes (this TypeDefinition type, TypeDefinitionCache? cache) =>
GetBaseTypes (type, (IMetadataResolver?) cache);

public static IEnumerable<TypeDefinition> GetBaseTypes (this TypeDefinition type, IMetadataResolver? resolver)
{
TypeDefinition? t = type;

while ((t = t.GetBaseType (cache)) != null) {
while ((t = t.GetBaseType (resolver)) != null) {
yield return t;
}
}

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static bool IsAssignableFrom (this TypeReference type, TypeReference c) =>
IsAssignableFrom (type, c, cache: null);
IsAssignableFrom (type, c, resolver: null);

public static bool IsAssignableFrom (this TypeReference type, TypeReference c, TypeDefinitionCache? cache) =>
IsAssignableFrom (type, c, (IMetadataResolver?) cache);

public static bool IsAssignableFrom (this TypeReference type, TypeReference c, TypeDefinitionCache? cache)
public static bool IsAssignableFrom (this TypeReference type, TypeReference c, IMetadataResolver? resolver)
{
if (type.FullName == c.FullName)
return true;
var d = c.Resolve ();
var d = (resolver?.Resolve (c)) ?? c.Resolve ();
if (d == null)
return false;
foreach (var t in d.GetTypeAndBaseTypes (cache)) {
foreach (var t in d.GetTypeAndBaseTypes (resolver)) {
if (type.FullName == t.FullName)
return true;
foreach (var ifaceImpl in t.Interfaces) {
var i = ifaceImpl.InterfaceType;
if (IsAssignableFrom (type, i, cache))
if (IsAssignableFrom (type, i, resolver))
return true;
}
}
Expand All @@ -73,11 +85,13 @@ public static bool IsAssignableFrom (this TypeReference type, TypeReference c, T

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static bool IsSubclassOf (this TypeDefinition type, string typeName) =>
IsSubclassOf (type, typeName, cache: null);
IsSubclassOf (type, typeName, resolver: null);

public static bool IsSubclassOf (this TypeDefinition type, string typeName, TypeDefinitionCache? cache)
public static bool IsSubclassOf (this TypeDefinition type, string typeName, TypeDefinitionCache? cache) =>
IsSubclassOf (type, typeName, (IMetadataResolver?) cache);
public static bool IsSubclassOf (this TypeDefinition type, string typeName, IMetadataResolver? resolver)
{
foreach (var t in type.GetTypeAndBaseTypes (cache)) {
foreach (var t in type.GetTypeAndBaseTypes (resolver)) {
if (t.FullName == typeName) {
return true;
}
Expand All @@ -87,11 +101,14 @@ public static bool IsSubclassOf (this TypeDefinition type, string typeName, Type

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static bool ImplementsInterface (this TypeDefinition type, string interfaceName) =>
ImplementsInterface (type, interfaceName, cache: null);
ImplementsInterface (type, interfaceName, resolver: null);

public static bool ImplementsInterface (this TypeDefinition type, string interfaceName, TypeDefinitionCache? cache)
public static bool ImplementsInterface (this TypeDefinition type, string interfaceName, TypeDefinitionCache? cache) =>
ImplementsInterface (type, interfaceName, (IMetadataResolver?) cache);

public static bool ImplementsInterface (this TypeDefinition type, string interfaceName, IMetadataResolver? resolver)
{
foreach (var t in type.GetTypeAndBaseTypes (cache)) {
foreach (var t in type.GetTypeAndBaseTypes (resolver)) {
foreach (var i in t.Interfaces) {
if (i.InterfaceType.FullName == interfaceName) {
return true;
Expand All @@ -103,34 +120,43 @@ public static bool ImplementsInterface (this TypeDefinition type, string interfa

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static string GetPartialAssemblyName (this TypeReference type) =>
GetPartialAssemblyName (type, cache: null);
GetPartialAssemblyName (type, resolver: null);

public static string GetPartialAssemblyName (this TypeReference type, TypeDefinitionCache? cache) =>
GetPartialAssemblyName (type, (IMetadataResolver?) cache);

public static string GetPartialAssemblyName (this TypeReference type, TypeDefinitionCache? cache)
public static string GetPartialAssemblyName (this TypeReference type, IMetadataResolver? resolver)
{
TypeDefinition def = cache != null ? cache.Resolve (type) : type.Resolve ();
TypeDefinition? def = (resolver?.Resolve (type)) ?? type.Resolve ();
return (def ?? type).Module.Assembly.Name.Name;
}

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static string GetPartialAssemblyQualifiedName (this TypeReference type) =>
GetPartialAssemblyQualifiedName (type, cache: null);
GetPartialAssemblyQualifiedName (type, resolver: null);

public static string GetPartialAssemblyQualifiedName (this TypeReference type, TypeDefinitionCache? cache)
public static string GetPartialAssemblyQualifiedName (this TypeReference type, TypeDefinitionCache? cache) =>
GetPartialAssemblyQualifiedName (type, (IMetadataResolver?) cache);

public static string GetPartialAssemblyQualifiedName (this TypeReference type, IMetadataResolver? resolver)
{
return string.Format ("{0}, {1}",
// Cecil likes to use '/' as the nested type separator, while
// Reflection uses '+' as the nested type separator. Use Reflection.
type.FullName.Replace ('/', '+'),
type.GetPartialAssemblyName (cache));
type.GetPartialAssemblyName (resolver));
}

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public static string GetAssemblyQualifiedName (this TypeReference type) =>
GetAssemblyQualifiedName (type, cache: null);
GetAssemblyQualifiedName (type, resolver: null);

public static string GetAssemblyQualifiedName (this TypeReference type, TypeDefinitionCache? cache) =>
GetAssemblyQualifiedName (type, (IMetadataResolver?) cache);

public static string GetAssemblyQualifiedName (this TypeReference type, TypeDefinitionCache? cache)
public static string GetAssemblyQualifiedName (this TypeReference type, IMetadataResolver? resolver)
{
TypeDefinition def = cache != null ? cache.Resolve (type) : type.Resolve ();
TypeDefinition? def = (resolver?.Resolve (type)) ?? type.Resolve ();
return string.Format ("{0}, {1}",
// Cecil likes to use '/' as the nested type separator, while
// Reflection uses '+' as the nested type separator. Use Reflection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ namespace Java.Interop.Tools.JavaCallableWrappers {
public class JavaCallableWrapperGenerator {

class JavaFieldInfo {
public JavaFieldInfo (MethodDefinition method, string fieldName, TypeDefinitionCache cache)
public JavaFieldInfo (MethodDefinition method, string fieldName, IMetadataResolver resolver)
{
this.FieldName = fieldName;
InitializerName = method.Name;
TypeName = JavaNativeTypeManager.ReturnTypeFromSignature (GetJniSignature (method, cache)).Type;
TypeName = JavaNativeTypeManager.ReturnTypeFromSignature (GetJniSignature (method, resolver)).Type;
IsStatic = method.IsStatic;
Access = method.Attributes & MethodAttributes.MemberAccessMask;
Annotations = GetAnnotationsString ("\t", method.CustomAttributes);
Expand All @@ -54,15 +54,20 @@ public string GetJavaAccess ()
List<Signature> methods = new List<Signature> ();
List<Signature> ctors = new List<Signature> ();
List<JavaCallableWrapperGenerator> children;
readonly TypeDefinitionCache cache;
readonly IMetadataResolver cache;

[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object []> log)
: this (type, null, log, cache: null)
: this (type, null, log, resolver: null)
{ }

public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object[]> log, TypeDefinitionCache cache)
: this (type, null, log, cache)
: this (type, log, (IMetadataResolver) cache)
{
}

public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object[]> log, IMetadataResolver resolver)
: this (type, null, log, resolver)
{
if (type.HasNestedTypes) {
children = new List<JavaCallableWrapperGenerator> ();
Expand Down Expand Up @@ -103,11 +108,11 @@ void AddNestedTypes (TypeDefinition type)
HasExport |= children.Any (t => t.HasExport);
}

JavaCallableWrapperGenerator (TypeDefinition type, string outerType, Action<string, object[]> log, TypeDefinitionCache cache)
JavaCallableWrapperGenerator (TypeDefinition type, string outerType, Action<string, object[]> log, IMetadataResolver resolver)
{
this.type = type;
this.log = log;
this.cache = cache ?? new TypeDefinitionCache ();
this.cache = resolver ?? new TypeDefinitionCache ();

if (type.IsEnum || type.IsInterface || type.IsValueType)
Diagnostic.Error (4200, LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4200, type.FullName);
Expand Down Expand Up @@ -655,7 +660,7 @@ public Signature (MethodDefinition method, RegisterAttribute register, string ma
Annotations = JavaCallableWrapperGenerator.GetAnnotationsString ("\t", method.CustomAttributes);
}

public Signature (MethodDefinition method, ExportAttribute export, TypeDefinitionCache cache)
public Signature (MethodDefinition method, ExportAttribute export, IMetadataResolver cache)
: this (method.Name, GetJniSignature (method, cache), "__export__", null, null, export.SuperArgumentsString)
{
IsExport = true;
Expand All @@ -666,7 +671,7 @@ public Signature (MethodDefinition method, ExportAttribute export, TypeDefinitio
Annotations = JavaCallableWrapperGenerator.GetAnnotationsString ("\t", method.CustomAttributes);
}

public Signature (MethodDefinition method, ExportFieldAttribute exportField, TypeDefinitionCache cache)
public Signature (MethodDefinition method, ExportFieldAttribute exportField, IMetadataResolver cache)
: this (method.Name, GetJniSignature (method, cache), "__export__", null, null, null)
{
if (method.HasParameters)
Expand Down
Loading