Skip to content

[Java.Interop.Tools.Cecil] Unroll TypeDefinitionRocks iterators. #1244

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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 @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ public static MethodDefinition GetBaseDefinition (this MethodDefinition method,
if (method.IsStatic || method.IsNewSlot || !method.IsVirtual)
return method;

foreach (var baseType in method.DeclaringType.GetBaseTypes (resolver)) {
TypeDefinition? baseType = method.DeclaringType;

while ((baseType = baseType.GetBaseType (resolver)) != null) {
foreach (var m in baseType.Methods) {
if (!m.IsConstructor &&
m.Name == method.Name &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,19 @@ public static bool IsAssignableFrom (this TypeReference type, TypeReference c, I
var d = resolver.Resolve (c);
if (d == null)
return false;
foreach (var t in d.GetTypeAndBaseTypes (resolver)) {

TypeDefinition? t = d;

while (t is not null) {
if (type.FullName == t.FullName)
return true;
foreach (var ifaceImpl in t.Interfaces) {
var i = ifaceImpl.InterfaceType;
if (IsAssignableFrom (type, i, resolver))
return true;
}

t = t.GetBaseType (resolver);
}
return false;
}
Expand All @@ -84,20 +89,44 @@ public static bool IsSubclassOf (this TypeDefinition type, string typeName, Type
IsSubclassOf (type, typeName, (IMetadataResolver) cache);
public static bool IsSubclassOf (this TypeDefinition type, string typeName, IMetadataResolver resolver)
{
foreach (var t in type.GetTypeAndBaseTypes (resolver)) {
TypeDefinition? t = type;

while (t is not null) {
if (t.FullName == typeName) {
return true;
}

t = t.GetBaseType (resolver);
}
return false;
}

public static bool IsSubclassOfAny (this TypeDefinition type, IList<string> typeNames, IMetadataResolver resolver, out string? subclassType)
{
subclassType = null;

TypeDefinition? t = type;

while (t is not null) {
if (typeNames.Contains (t.FullName)) {
subclassType = t.FullName;
return true;
}

t = t.GetBaseType (resolver);
}

return false;
}

public static bool HasJavaPeer (this TypeDefinition type, IMetadataResolver resolver)
{
if (type.IsInterface && type.ImplementsInterface ("Java.Interop.IJavaPeerable", resolver))
return true;
if (type.IsInterface)
return type.ImplementsInterface ("Java.Interop.IJavaPeerable", resolver);

foreach (var t in type.GetTypeAndBaseTypes (resolver)) {
TypeDefinition? t = type;

while (t is not null) {
switch (t.FullName) {
case "Java.Lang.Object":
case "Java.Lang.Throwable":
Expand All @@ -107,6 +136,8 @@ public static bool HasJavaPeer (this TypeDefinition type, IMetadataResolver reso
default:
break;
}

t = t.GetBaseType (resolver);
}
return false;
}
Expand All @@ -119,13 +150,36 @@ public static bool ImplementsInterface (this TypeDefinition type, string interfa

public static bool ImplementsInterface (this TypeDefinition type, string interfaceName, IMetadataResolver resolver)
{
foreach (var t in type.GetTypeAndBaseTypes (resolver)) {
TypeDefinition? t = type;

while (t is not null) {
foreach (var i in t.Interfaces) {
if (i.InterfaceType.FullName == interfaceName) {
return true;
}
}

t = t.GetBaseType (resolver);
}
return false;
}

public static bool ImplementsAnyInterface (this TypeDefinition type, IList<string> interfaceNames, IMetadataResolver resolver, out string? implementedInterface)
{
implementedInterface = null;
TypeDefinition? t = type;

while (t is not null) {
foreach (var i in t.Interfaces) {
if (interfaceNames.Contains (i.InterfaceType.FullName)) {
implementedInterface = i.InterfaceType.FullName;
return true;
}
}

t = t.GetBaseType (resolver);
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ namespace Java.Interop.Tools.JavaCallableWrappers.Adapters;

public class CecilImporter
{
static IList<string> android_manifest_types = ["Android.App.Activity", "Android.App.Application", "Android.App.Service", "Android.Content.BroadcastReceiver", "Android.Content.ContentProvider"];

// Don't expose internal "outerType" parameter to the public API
public static CallableWrapperType CreateType (TypeDefinition type, IMetadataResolver resolver, CallableWrapperReaderOptions? options = null)
=> CreateType (type, resolver, options, null);
Expand All @@ -38,11 +40,7 @@ static CallableWrapperType CreateType (TypeDefinition type, IMetadataResolver re
options ??= new CallableWrapperReaderOptions ();

if (string.IsNullOrEmpty (package) &&
(type.IsSubclassOf ("Android.App.Activity", resolver) ||
type.IsSubclassOf ("Android.App.Application", resolver) ||
type.IsSubclassOf ("Android.App.Service", resolver) ||
type.IsSubclassOf ("Android.Content.BroadcastReceiver", resolver) ||
type.IsSubclassOf ("Android.Content.ContentProvider", resolver)))
(type.IsSubclassOfAny (android_manifest_types, resolver, out var _)))
Diagnostic.Error (4203, CecilExtensions.LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4203, jniName);

var cwt = new CallableWrapperType (name, package, type.GetPartialAssemblyQualifiedName (resolver)) {
Expand Down Expand Up @@ -124,7 +122,9 @@ static CallableWrapperType CreateType (TypeDefinition type, IMetadataResolver re
type,
};

foreach (var bt in type.GetBaseTypes (resolver)) {
TypeDefinition? bt = type;

while ((bt = bt.GetBaseType (resolver)) != null) {
ctorTypes.Add (bt);
var rattr = CecilExtensions.GetTypeRegistrationAttributes (bt).FirstOrDefault ();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>11.0</LangVersion>
<LangVersion>12.0</LangVersion>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SignAssembly>true</SignAssembly>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ public static bool IsApplication (TypeDefinition type, TypeDefinitionCache cache

public static bool IsApplication (TypeDefinition type, IMetadataResolver resolver)
{
return type.GetBaseTypes (resolver).Any (b => b.FullName == "Android.App.Application");
return type.IsSubclassOf ("Android.App.Application", resolver);
}

[Obsolete ("Use the TypeDefinitionCache overload for better performance.", error: true)]
Expand All @@ -449,7 +449,7 @@ public static bool IsInstrumentation (TypeDefinition type, TypeDefinitionCache c

public static bool IsInstrumentation (TypeDefinition type, IMetadataResolver resolver)
{
return type.GetBaseTypes (resolver).Any (b => b.FullName == "Android.App.Instrumentation");
return type.IsSubclassOf ("Android.App.Instrumentation", resolver);
}

// moved from JavaTypeInfo
Expand Down Expand Up @@ -529,6 +529,8 @@ public static string ToJniName (TypeDefinition type, IMetadataResolver resolver)
return x;
}

static IList<string> java_interface_types = ["Android.Runtime.IJavaObject", "Java.Interop.IJavaPeerable"];

static string? ToJniName (TypeDefinition type, ExportParameterKind exportKind, IMetadataResolver cache)
{
if (type == null)
Expand All @@ -540,8 +542,7 @@ public static string ToJniName (TypeDefinition type, IMetadataResolver resolver)
if (type.FullName == "System.String")
return "java/lang/String";

if (!type.ImplementsInterface ("Android.Runtime.IJavaObject", cache) &&
!type.ImplementsInterface ("Java.Interop.IJavaPeerable", cache)) {
if (!type.ImplementsAnyInterface (java_interface_types, cache, out var _)) {
return GetSpecialExportJniType (type.FullName, exportKind);
}

Expand Down Expand Up @@ -734,9 +735,10 @@ internal static bool IsNonStaticInnerClass (TypeDefinition? type, IMetadataResol
if (!type.DeclaringType.HasJavaPeer (cache))
return false;

foreach (var baseType in type.GetBaseTypes (cache)) {
if (baseType == null)
continue;
TypeDefinition? baseType = type;

while ((baseType = baseType.GetBaseType (cache)) != null) {

if (!baseType.AnyCustomAttributes (typeof (RegisterAttribute)))
continue;

Expand Down