From c7cdf36621199d064388ebb103605e73832b0657 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst <jonathan.pobst@microsoft.com> Date: Mon, 14 Oct 2024 09:58:47 -1000 Subject: [PATCH 1/3] [generator] Only use `[JniTypeSignatureAttribute]` for `JavaInterop1`. --- .../Adapters/ApiImporterOptions.cs | 9 +++ .../Adapters/ManagedApiImporter.cs | 68 +++++++++---------- .../Java.Interop.Tools.JavaTypeSystem.csproj | 1 - .../Unit-Tests/ManagedTests.cs | 26 +++---- tools/generator/CodeGenerator.cs | 2 +- .../CecilApiImporter.cs | 40 ++++++----- .../JavaTypeResolutionFixups.cs | 9 ++- 7 files changed, 87 insertions(+), 68 deletions(-) create mode 100644 src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs diff --git a/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs new file mode 100644 index 000000000..7778f3527 --- /dev/null +++ b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.ObjectModel; + +namespace Java.Interop.Tools.JavaTypeSystem; + +public class ApiImporterOptions +{ + public Collection<string> SupportedRegisterAttributes { get; } = ["Android.Runtime.RegisterAttribute"]; +} diff --git a/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs index abf05d815..41e57b56a 100644 --- a/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs +++ b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs @@ -13,13 +13,13 @@ public static class ManagedApiImporter [Obsolete ("Use the TypeDefinitionCache overload for better performance.", error: true)] public static JavaTypeCollection Parse (AssemblyDefinition assembly, JavaTypeCollection collection) => throw new NotSupportedException (); - public static JavaTypeCollection Parse (AssemblyDefinition assembly, JavaTypeCollection collection, TypeDefinitionCache resolver) + public static JavaTypeCollection Parse (AssemblyDefinition assembly, JavaTypeCollection collection, TypeDefinitionCache resolver, ApiImporterOptions options) { var types_to_add = new List<JavaTypeModel> (); foreach (var md in assembly.Modules) foreach (var td in md.Types) { - if (!ShouldSkipType (td, resolver) && ParseType (td, collection) is JavaTypeModel type) + if (!ShouldSkipType (td, resolver, options) && ParseType (td, collection, options) is JavaTypeModel type) types_to_add.Add (type); } @@ -33,7 +33,7 @@ public static JavaTypeCollection Parse (AssemblyDefinition assembly, JavaTypeCol return collection; } - public static JavaTypeModel? ParseType (TypeDefinition type, JavaTypeCollection collection) + public static JavaTypeModel? ParseType (TypeDefinition type, JavaTypeCollection collection, ApiImporterOptions options) { if (!type.IsPublic && !type.IsNested) return null; @@ -41,13 +41,13 @@ public static JavaTypeCollection Parse (AssemblyDefinition assembly, JavaTypeCol if (!ShouldImport (type)) return null; - var model = type.IsInterface ? (JavaTypeModel?) ParseInterface (type, collection) : ParseClass (type, collection); + var model = type.IsInterface ? (JavaTypeModel?) ParseInterface (type, collection, options) : ParseClass (type, collection, options); if (model is null) return null; foreach (var nested in type.NestedTypes) - if (ParseType (nested, collection) is JavaTypeModel nested_model) + if (ParseType (nested, collection, options) is JavaTypeModel nested_model) model.NestedTypes.Add (nested_model); return model; @@ -89,11 +89,11 @@ static bool ShouldImport (TypeDefinition td) return true; } - public static JavaClassModel? ParseClass (TypeDefinition type, JavaTypeCollection collection) + public static JavaClassModel? ParseClass (TypeDefinition type, JavaTypeCollection collection, ApiImporterOptions options) { // TODO: type parameters? var obs_attr = GetObsoleteAttribute (type.CustomAttributes); - var reg_attr = GetRegisterAttribute (type.CustomAttributes); + var reg_attr = GetRegisterAttribute (type.CustomAttributes, options); if (reg_attr is null) return null; @@ -101,7 +101,7 @@ static bool ShouldImport (TypeDefinition td) var encoded_fullname = ((string) reg_attr.ConstructorArguments [0].Value).Replace ('/', '.'); var (package, nested_name) = DecodeRegisterJavaFullName (encoded_fullname); - var base_jni = GetBaseTypeJni (type); + var base_jni = GetBaseTypeJni (type, options); var model = new JavaClassModel ( javaPackage: GetOrCreatePackage (collection, package, type.Namespace), @@ -118,20 +118,20 @@ static bool ShouldImport (TypeDefinition td) annotatedVisibility: string.Empty ); ; - ParseImplementedInterfaces (type, model); + ParseImplementedInterfaces (type, model, options); foreach (var method in type.Methods.Where (m => !m.IsConstructor)) - if (ParseMethod (method, model) is JavaMethodModel m) + if (ParseMethod (method, model, options) is JavaMethodModel m) model.Methods.Add (m); return model; } - public static JavaInterfaceModel? ParseInterface (TypeDefinition type, JavaTypeCollection collection) + public static JavaInterfaceModel? ParseInterface (TypeDefinition type, JavaTypeCollection collection, ApiImporterOptions options) { // TODO: type paramters? var obs_attr = GetObsoleteAttribute (type.CustomAttributes); - var reg_attr = GetRegisterAttribute (type.CustomAttributes); + var reg_attr = GetRegisterAttribute (type.CustomAttributes, options); if (reg_attr is null) return null; @@ -149,22 +149,22 @@ static bool ShouldImport (TypeDefinition td) annotatedVisibility: "" ); - ParseImplementedInterfaces (type, model); + ParseImplementedInterfaces (type, model, options); foreach (var method in type.Methods) - if (ParseMethod (method, model) is JavaMethodModel m) + if (ParseMethod (method, model, options) is JavaMethodModel m) model.Methods.Add (m); return model; } - public static JavaMethodModel? ParseMethod (MethodDefinition method, JavaTypeModel declaringType) + public static JavaMethodModel? ParseMethod (MethodDefinition method, JavaTypeModel declaringType, ApiImporterOptions options) { if (method.IsPrivate || method.IsAssembly) return null; var obs_attr = GetObsoleteAttribute (method.CustomAttributes); - var reg_attr = GetRegisterAttribute (method.CustomAttributes); + var reg_attr = GetRegisterAttribute (method.CustomAttributes, options); if (reg_attr is null) return null; @@ -225,7 +225,7 @@ static void AddReferenceTypeRecursive (JavaTypeModel type, JavaTypeCollection co AddReferenceTypeRecursive (nested, collection); } - static bool ShouldSkipType (TypeDefinition type, TypeDefinitionCache cache) + static bool ShouldSkipType (TypeDefinition type, TypeDefinitionCache cache, ApiImporterOptions options) { // We want to use Java's collection types instead of our managed adapter. // eg: 'Java.Util.ArrayList' over 'Android.Runtime.JavaList' @@ -246,28 +246,28 @@ static bool ShouldSkipType (TypeDefinition type, TypeDefinitionCache cache) ? type.Module.GetType (type.FullName.Substring (0, type.FullName.IndexOf ('`'))) : null; - if (ShouldSkipGeneric (type, non_generic_type, cache)) + if (ShouldSkipGeneric (type, non_generic_type, cache, options)) return true; return false; } - static bool ShouldSkipGeneric (TypeDefinition? a, TypeDefinition? b, TypeDefinitionCache cache) + static bool ShouldSkipGeneric (TypeDefinition? a, TypeDefinition? b, TypeDefinitionCache cache, ApiImporterOptions options) { if (a == null || b == null) return false; if (!a.ImplementsInterface ("Android.Runtime.IJavaObject", cache) || !b.ImplementsInterface ("Android.Runtime.IJavaObject", cache)) return false; - return GetRegisteredJavaTypeName (a) == GetRegisteredJavaTypeName (b); + return GetRegisteredJavaTypeName (a, options) == GetRegisteredJavaTypeName (b, options); } - static string? TypeReferenceToJavaType (TypeReference type) + static string? TypeReferenceToJavaType (TypeReference type, ApiImporterOptions options) { - var retval = GetRegisteredJavaName (type); + var retval = GetRegisteredJavaName (type, options); if (retval != null && type is GenericInstanceType generic) { - var parameters = generic.GenericArguments.Select (ga => GetRegisteredJavaName (ga.Resolve ())).ToArray (); + var parameters = generic.GenericArguments.Select (ga => GetRegisteredJavaName (ga.Resolve (), options)).ToArray (); if (parameters.WhereNotNull ().Any ()) retval += $"<{string.Join (", ", parameters.WhereNotNull ())}>"; @@ -276,14 +276,14 @@ static bool ShouldSkipGeneric (TypeDefinition? a, TypeDefinition? b, TypeDefinit return retval; } - static string? GetRegisteredJavaName (TypeReference type) + static string? GetRegisteredJavaName (TypeReference type, ApiImporterOptions options) { var td = type.Resolve (); - return GetRegisteredJavaTypeName (td); + return GetRegisteredJavaTypeName (td, options); } - static void ParseImplementedInterfaces (TypeDefinition type, JavaTypeModel model) + static void ParseImplementedInterfaces (TypeDefinition type, JavaTypeModel model, ApiImporterOptions options) { foreach (var iface_impl in type.Interfaces) { var iface = iface_impl.InterfaceType; @@ -292,7 +292,7 @@ static void ParseImplementedInterfaces (TypeDefinition type, JavaTypeModel model if (iface_def is null || iface_def.IsNotPublic) continue; - if (GetRegisterAttribute (iface_def.CustomAttributes) is CustomAttribute reg_attr) { + if (GetRegisterAttribute (iface_def.CustomAttributes, options) is CustomAttribute reg_attr) { var jni = (string) reg_attr.ConstructorArguments [0].Value; var name = jni.Replace ('/', '.').Replace ('$', '.'); @@ -301,7 +301,7 @@ static void ParseImplementedInterfaces (TypeDefinition type, JavaTypeModel model } } - static string GetBaseTypeJni (TypeDefinition type) + static string GetBaseTypeJni (TypeDefinition type, ApiImporterOptions options) { // Find a Java base type, ignoring generic types, if nothing else it will be Java.Lang.Object TypeDefinition? base_type = type; @@ -319,7 +319,7 @@ static string GetBaseTypeJni (TypeDefinition type) if (base_type.HasGenericParameters || base_type.IsGenericInstance) continue; - if (GetRegisterAttribute (base_type.CustomAttributes) is CustomAttribute reg_attr) + if (GetRegisterAttribute (base_type.CustomAttributes, options) is CustomAttribute reg_attr) return (string) reg_attr.ConstructorArguments [0].Value; } @@ -329,19 +329,19 @@ static string GetBaseTypeJni (TypeDefinition type) static CustomAttribute? GetObsoleteAttribute (Collection<CustomAttribute> attributes) => attributes.FirstOrDefault (a => a.AttributeType.FullNameCorrected () == "System.ObsoleteAttribute"); - static CustomAttribute? GetRegisterAttribute (Collection<CustomAttribute> attributes) => + static CustomAttribute? GetRegisterAttribute (Collection<CustomAttribute> attributes, ApiImporterOptions options) => attributes.FirstOrDefault (a => { var attrType = a.AttributeType.FullNameCorrected (); - return attrType == "Android.Runtime.RegisterAttribute" || - attrType == "Java.Interop.JniTypeSignatureAttribute"; + + return options.SupportedRegisterAttributes.Contains (attrType); }); - static string? GetRegisteredJavaTypeName (TypeDefinition type) + static string? GetRegisteredJavaTypeName (TypeDefinition type, ApiImporterOptions options) { if (GetSpecialCase (type) is string s) return s; - if (GetRegisterAttribute (type.CustomAttributes) is CustomAttribute reg_attr) + if (GetRegisterAttribute (type.CustomAttributes, options) is CustomAttribute reg_attr) return ((string) reg_attr.ConstructorArguments [0].Value).Replace ('/', '.'); return null; diff --git a/src/Java.Interop.Tools.JavaTypeSystem/Java.Interop.Tools.JavaTypeSystem.csproj b/src/Java.Interop.Tools.JavaTypeSystem/Java.Interop.Tools.JavaTypeSystem.csproj index bce32d0ca..968d1a813 100644 --- a/src/Java.Interop.Tools.JavaTypeSystem/Java.Interop.Tools.JavaTypeSystem.csproj +++ b/src/Java.Interop.Tools.JavaTypeSystem/Java.Interop.Tools.JavaTypeSystem.csproj @@ -3,7 +3,6 @@ <PropertyGroup> <TargetFramework>$(DotNetTargetFramework)</TargetFramework> <Nullable>enable</Nullable> - <LangVersion>8.0</LangVersion> </PropertyGroup> <Import Project="..\..\TargetFrameworkDependentValues.props" /> diff --git a/tests/generator-Tests/Unit-Tests/ManagedTests.cs b/tests/generator-Tests/Unit-Tests/ManagedTests.cs index cd24b0b9b..004b2c990 100644 --- a/tests/generator-Tests/Unit-Tests/ManagedTests.cs +++ b/tests/generator-Tests/Unit-Tests/ManagedTests.cs @@ -138,7 +138,7 @@ public void Method () { var type = module.GetType ("Com.Mypackage.Foo"); var @class = CecilApiImporter.CreateClass (type, options); - var method = CecilApiImporter.CreateMethod (@class, type.Methods.First (m => m.Name == "Bar")); + var method = CecilApiImporter.CreateMethod (@class, type.Methods.First (m => m.Name == "Bar"), options); Assert.IsTrue (method.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "method.Validate failed!"); Assert.AreEqual ("public", method.Visibility); @@ -159,8 +159,8 @@ public void Method_Matches_True () var type = module.GetType ("Com.Mypackage.Foo"); var @class = CecilApiImporter.CreateClass (type, options); var unknownTypes = type.Methods.First (m => m.Name == "UnknownTypes"); - var methodA = CecilApiImporter.CreateMethod (@class, unknownTypes); - var methodB = CecilApiImporter.CreateMethod (@class, unknownTypes); + var methodA = CecilApiImporter.CreateMethod (@class, unknownTypes, options); + var methodB = CecilApiImporter.CreateMethod (@class, unknownTypes, options); Assert.IsTrue (methodA.Matches (methodB), "Methods should match!"); } @@ -172,8 +172,8 @@ public void Method_Matches_False () var unknownTypesA = type.Methods.First (m => m.Name == "UnknownTypes"); var unknownTypesB = type.Methods.First (m => m.Name == "UnknownTypesReturn"); unknownTypesB.Name = "UnknownTypes"; - var methodA = CecilApiImporter.CreateMethod (@class, unknownTypesA); - var methodB = CecilApiImporter.CreateMethod (@class, unknownTypesB); + var methodA = CecilApiImporter.CreateMethod (@class, unknownTypesA, options); + var methodB = CecilApiImporter.CreateMethod (@class, unknownTypesB, options); //Everything the same besides return type Assert.IsFalse (methodA.Matches (methodB), "Methods should not match!"); } @@ -183,7 +183,7 @@ public void MethodWithParameters () { var type = module.GetType ("Com.Mypackage.Foo"); var @class = CecilApiImporter.CreateClass (type, options); - var method = CecilApiImporter.CreateMethod (@class, type.Methods.First (m => m.Name == "BarWithParams")); + var method = CecilApiImporter.CreateMethod (@class, type.Methods.First (m => m.Name == "BarWithParams"), options); Assert.IsTrue (method.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "method.Validate failed!"); Assert.AreEqual ("(ZID)Ljava/lang/String;", method.JniSignature); Assert.AreEqual ("java.lang.String", method.Return); @@ -213,7 +213,7 @@ public void Ctor () { var type = module.GetType ("Com.Mypackage.Foo"); var @class = CecilApiImporter.CreateClass (type, options); - var ctor = CecilApiImporter.CreateCtor (@class, type.Methods.First (m => m.IsConstructor && !m.IsStatic)); + var ctor = CecilApiImporter.CreateCtor (@class, type.Methods.First (m => m.IsConstructor && !m.IsStatic), options); Assert.IsTrue (ctor.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "ctor.Validate failed!"); Assert.AreEqual ("public", ctor.Visibility); @@ -227,7 +227,7 @@ public void Field () { var type = module.GetType ("Com.Mypackage.Foo"); var @class = CecilApiImporter.CreateClass (type, options); - var field = CecilApiImporter.CreateField (type.Fields.First (f => f.Name == "Value")); + var field = CecilApiImporter.CreateField (type.Fields.First (f => f.Name == "Value"), options); Assert.IsTrue (field.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "field.Validate failed!"); Assert.AreEqual ("Value", field.Name); @@ -279,23 +279,23 @@ public void TypeNullability () var type = module.GetType ("NullableTestTypes.NullableClass"); var gen = CecilApiImporter.CreateClass (module.GetType ("NullableTestTypes.NullableClass"), options); - var not_null_field = CecilApiImporter.CreateField (type.Fields.First (f => f.Name == "not_null_field")); + var not_null_field = CecilApiImporter.CreateField (type.Fields.First (f => f.Name == "not_null_field"), options); Assert.AreEqual (true, not_null_field.NotNull); - var null_field = CecilApiImporter.CreateField (type.Fields.First (f => f.Name == "null_field")); + var null_field = CecilApiImporter.CreateField (type.Fields.First (f => f.Name == "null_field"), options); Assert.AreEqual (false, null_field.NotNull); - var null_method = CecilApiImporter.CreateMethod (gen, type.Methods.First (f => f.Name == "NullableReturnMethod")); + var null_method = CecilApiImporter.CreateMethod (gen, type.Methods.First (f => f.Name == "NullableReturnMethod"), options); Assert.AreEqual (false, null_method.ReturnNotNull); Assert.AreEqual (true, null_method.Parameters.First (f => f.Name == "notnull").NotNull); Assert.AreEqual (false, null_method.Parameters.First (f => f.Name == "nullable").NotNull); - var not_null_method = CecilApiImporter.CreateMethod (gen, type.Methods.First (f => f.Name == "NotNullReturnMethod")); + var not_null_method = CecilApiImporter.CreateMethod (gen, type.Methods.First (f => f.Name == "NotNullReturnMethod"), options); Assert.AreEqual (true, not_null_method.ReturnNotNull); Assert.AreEqual (true, not_null_method.Parameters.First (f => f.Name == "notnull").NotNull); Assert.AreEqual (false, not_null_method.Parameters.First (f => f.Name == "nullable").NotNull); - var ctor = CecilApiImporter.CreateCtor (gen, type.Methods.First (f => f.Name == ".ctor")); + var ctor = CecilApiImporter.CreateCtor (gen, type.Methods.First (f => f.Name == ".ctor"), options); Assert.AreEqual (true, ctor.Parameters.First (f => f.Name == "notnull").NotNull); Assert.AreEqual (false, ctor.Parameters.First (f => f.Name == "nullable").NotNull); } diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs index 927b4e24e..f7dcd14f4 100644 --- a/tools/generator/CodeGenerator.cs +++ b/tools/generator/CodeGenerator.cs @@ -113,7 +113,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve // Resolve types using Java.Interop.Tools.JavaTypeSystem if (is_classparse && !options.UseLegacyJavaResolver) { var output_xml = api_xml_adjuster_output ?? Path.Combine (Path.GetDirectoryName (filename), Path.GetFileName (filename) + ".adjusted"); - JavaTypeResolutionFixups.Fixup (filename, output_xml, resolver, references.Distinct ().ToArray (), resolverCache); + JavaTypeResolutionFixups.Fixup (filename, output_xml, resolver, references.Distinct ().ToArray (), resolverCache, options); if (only_xml_adjuster) return; diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs index ae9fc3fbf..377ec97ee 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs @@ -31,19 +31,19 @@ public static ClassGen CreateClass (TypeDefinition t, CodeGenerationOptions opt) var implements_charsequence = t.Interfaces.Any (it => it.InterfaceType.FullName == "Java.Lang.CharSequence"); foreach (var m in t.Methods) { - if (m.IsPrivate || m.IsAssembly || GetRegisterAttribute (m.CustomAttributes) == null) + if (m.IsPrivate || m.IsAssembly || GetRegisterAttribute (m.CustomAttributes, opt) == null) continue; if (implements_charsequence && t.Methods.Any (mm => mm.Name == m.Name + "Formatted")) continue; if (m.IsConstructor) - klass.Ctors.Add (CreateCtor (klass, m)); + klass.Ctors.Add (CreateCtor (klass, m, opt)); else - klass.AddMethod (CreateMethod (klass, m)); + klass.AddMethod (CreateMethod (klass, m, opt)); } foreach (var f in t.Fields) - if (!f.IsPrivate && GetRegisterAttribute (f.CustomAttributes) == null) - klass.AddField (CreateField (f)); + if (!f.IsPrivate && GetRegisterAttribute (f.CustomAttributes, opt) == null) + klass.AddField (CreateField (f, opt)); }; if (klass.IsShallow) @@ -61,9 +61,9 @@ public static ClassGen CreateClass (TypeDefinition t, CodeGenerationOptions opt) return klass; } - public static Ctor CreateCtor (GenBase declaringType, MethodDefinition m) + public static Ctor CreateCtor (GenBase declaringType, MethodDefinition m, CodeGenerationOptions opt) { - var reg_attr = GetRegisterAttribute (m.CustomAttributes); + var reg_attr = GetRegisterAttribute (m.CustomAttributes, opt); var ctor = new Ctor (declaringType) { AssemblyName = m.DeclaringType.Module.Assembly.FullName, @@ -88,10 +88,10 @@ public static Ctor CreateCtor (GenBase declaringType, MethodDefinition m) return ctor; } - public static Field CreateField (FieldDefinition f) + public static Field CreateField (FieldDefinition f, CodeGenerationOptions opt) { var obs_attr = GetObsoleteAttribute (f.CustomAttributes); - var reg_attr = GetRegisterAttribute (f.CustomAttributes); + var reg_attr = GetRegisterAttribute (f.CustomAttributes, opt); var field = new Field { DeprecatedComment = GetObsoleteComment (obs_attr), @@ -117,7 +117,7 @@ public static Field CreateField (FieldDefinition f) public static GenBaseSupport CreateGenBaseSupport (TypeDefinition t, CodeGenerationOptions opt) { var obs_attr = GetObsoleteAttribute (t.CustomAttributes); - var reg_attr = GetRegisterAttribute (t.CustomAttributes); + var reg_attr = GetRegisterAttribute (t.CustomAttributes, opt); var jn = reg_attr != null ? ((string) reg_attr.ConstructorArguments [0].Value).Replace ('/', '.') : t.FullNameCorrected (); var idx = jn.LastIndexOf ('.'); @@ -164,10 +164,10 @@ public static InterfaceGen CreateInterface (TypeDefinition t, CodeGenerationOpti Action populate = () => { foreach (var m in t.Methods) { - if (m.IsPrivate || m.IsAssembly || GetRegisterAttribute (m.CustomAttributes) == null) + if (m.IsPrivate || m.IsAssembly || GetRegisterAttribute (m.CustomAttributes, opt) == null) continue; - iface.AddMethod (CreateMethod (iface, m)); + iface.AddMethod (CreateMethod (iface, m, opt)); } }; @@ -181,9 +181,9 @@ public static InterfaceGen CreateInterface (TypeDefinition t, CodeGenerationOpti return iface; } - public static Method CreateMethod (GenBase declaringType, MethodDefinition m) + public static Method CreateMethod (GenBase declaringType, MethodDefinition m, CodeGenerationOptions opt) { - var reg_attr = GetRegisterAttribute (m.CustomAttributes); + var reg_attr = GetRegisterAttribute (m.CustomAttributes, opt); var method = new Method (declaringType) { AssemblyName = m.DeclaringType.Module.Assembly.FullName, @@ -249,11 +249,17 @@ static CustomAttribute GetObsoleteAttribute (Collection<CustomAttribute> attribu static string GetObsoleteComment (CustomAttribute attribute) => attribute?.ConstructorArguments.Any () == true ? (string) attribute.ConstructorArguments [0].Value : null; - static CustomAttribute GetRegisterAttribute (Collection<CustomAttribute> attributes) => + static CustomAttribute GetRegisterAttribute (Collection<CustomAttribute> attributes, CodeGenerationOptions opt) => attributes.FirstOrDefault (a => { var attrType = a.AttributeType.FullNameCorrected (); - return attrType == "Android.Runtime.RegisterAttribute" || - attrType == "Java.Interop.JniTypeSignatureAttribute"; + + if (attrType == "Android.Runtime.RegisterAttribute") + return true; + + if (opt.CodeGenerationTarget == Xamarin.Android.Binder.CodeGenerationTarget.JavaInterop1 && attrType == "Java.Interop.JniTypeSignatureAttribute") + return true; + + return false; }); static bool IsDefaultInterfaceMethod (GenBase declaringType, MethodDefinition method) diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs index 71b0c2b0b..c2bc4a5dd 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs @@ -4,6 +4,7 @@ using Java.Interop.Tools.Cecil; using Java.Interop.Tools.Generator; using Java.Interop.Tools.JavaTypeSystem; +using Xamarin.Android.Binder; namespace generator { @@ -14,17 +15,21 @@ public static class JavaTypeResolutionFixups // This fixup ensures all referenced Java types can be resolved, and // removes types and members that rely on unresolvable Java types. - public static void Fixup (string xmlFile, string outputXmlFile, DirectoryAssemblyResolver resolver, string [] references, TypeDefinitionCache cache) + public static void Fixup (string xmlFile, string outputXmlFile, DirectoryAssemblyResolver resolver, string [] references, TypeDefinitionCache cache, CodeGeneratorOptions opt) { // Parse api.xml var type_collection = JavaXmlApiImporter.Parse (xmlFile); + var options = new ApiImporterOptions (); + + if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) + options.SupportedRegisterAttributes.Add ("Java.Interop.JniTypeSignatureAttribute"); // Add in reference types from assemblies foreach (var reference in references.Distinct ()) { Report.Verbose (0, "Resolving assembly for Java type resolution: '{0}'.", reference); var assembly = resolver.Load (reference); - ManagedApiImporter.Parse (assembly, type_collection, cache); + ManagedApiImporter.Parse (assembly, type_collection, cache, options); } // Run the type resolution pass From 5db0525895e55febd0c6cdb321d98aeb41bbd853 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst <jonathan.pobst@microsoft.com> Date: Tue, 15 Oct 2024 09:57:31 -1000 Subject: [PATCH 2/3] Address review feedback. --- .../Adapters/ApiImporterOptions.cs | 2 +- .../Adapters/ManagedApiImporter.cs | 2 +- .../JavaTypeResolutionFixups.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs index 7778f3527..4c5160788 100644 --- a/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs +++ b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ApiImporterOptions.cs @@ -5,5 +5,5 @@ namespace Java.Interop.Tools.JavaTypeSystem; public class ApiImporterOptions { - public Collection<string> SupportedRegisterAttributes { get; } = ["Android.Runtime.RegisterAttribute"]; + public Collection<string> SupportedTypeMapAttributes { get; } = ["Android.Runtime.RegisterAttribute"]; } diff --git a/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs index 41e57b56a..908485d58 100644 --- a/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs +++ b/src/Java.Interop.Tools.JavaTypeSystem/Adapters/ManagedApiImporter.cs @@ -333,7 +333,7 @@ static string GetBaseTypeJni (TypeDefinition type, ApiImporterOptions options) attributes.FirstOrDefault (a => { var attrType = a.AttributeType.FullNameCorrected (); - return options.SupportedRegisterAttributes.Contains (attrType); + return options.SupportedTypeMapAttributes.Contains (attrType); }); static string? GetRegisteredJavaTypeName (TypeDefinition type, ApiImporterOptions options) diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs index c2bc4a5dd..dc3ec63fb 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs @@ -22,7 +22,7 @@ public static void Fixup (string xmlFile, string outputXmlFile, DirectoryAssembl var options = new ApiImporterOptions (); if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) - options.SupportedRegisterAttributes.Add ("Java.Interop.JniTypeSignatureAttribute"); + options.SupportedTypeMapAttributes.Add ("Java.Interop.JniTypeSignatureAttribute"); // Add in reference types from assemblies foreach (var reference in references.Distinct ()) { From 964543ee454047a4d93790e477cfd51610bd6cef Mon Sep 17 00:00:00 2001 From: Jonathan Pryor <jonpryor@vt.edu> Date: Thu, 17 Oct 2024 15:45:10 -0400 Subject: [PATCH 3/3] Make the label match the contents The dotnet/java-interop#1266 summary says: > Only use `[JniTypeSignatureAttribute]` for JavaInterop1 *Actually* do so: for XAJavaInterop1, don't allow `[JniTypeSignatureAttribute]`. For JavaInterop1, don't allow [Register]. Eventually we'll want XAJavaInterop1 to import JniTypeSignatureAttribute (maybe?), but not now. --- .../CecilApiImporter.cs | 7 ++++--- .../JavaTypeResolutionFixups.cs | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs index 377ec97ee..ffcc4cdf9 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs @@ -253,10 +253,11 @@ static CustomAttribute GetRegisterAttribute (Collection<CustomAttribute> attribu attributes.FirstOrDefault (a => { var attrType = a.AttributeType.FullNameCorrected (); - if (attrType == "Android.Runtime.RegisterAttribute") - return true; + if (opt.CodeGenerationTarget == Xamarin.Android.Binder.CodeGenerationTarget.JavaInterop1) { + return attrType == "Java.Interop.JniTypeSignatureAttribute"; + } - if (opt.CodeGenerationTarget == Xamarin.Android.Binder.CodeGenerationTarget.JavaInterop1 && attrType == "Java.Interop.JniTypeSignatureAttribute") + if (attrType == "Android.Runtime.RegisterAttribute") return true; return false; diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs index dc3ec63fb..bf8301457 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/JavaTypeResolutionFixups.cs @@ -21,8 +21,10 @@ public static void Fixup (string xmlFile, string outputXmlFile, DirectoryAssembl var type_collection = JavaXmlApiImporter.Parse (xmlFile); var options = new ApiImporterOptions (); - if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) + if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) { + options.SupportedTypeMapAttributes.Clear (); options.SupportedTypeMapAttributes.Add ("Java.Interop.JniTypeSignatureAttribute"); + } // Add in reference types from assemblies foreach (var reference in references.Distinct ()) {