From 8f16c4a514eae7cba55293a65ae98aa511330ef3 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Mon, 12 Oct 2026 11:16:29 +0200 Subject: [PATCH 1/2] [Java.Interop] Retire obsolete Java wrapper scaffolding Remove the legacy JCW emitter and standalone tool whose output still references retired registration and activation APIs. Preserve the shared naming utilities and current trimmable registration pipeline. Remove unused abstract/deferred constructor bridges and bootstrap artifacts, wire the retained runtime JAR/header producer, and document intentional tooling compatibility removals. Validate output/native table agreement, SDK/API gates, host coverage, and both runtime suites. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../instructions/java-interop.instructions.md | 2 +- .../skills/tests/references/test-catalog.md | 4 +- .../guides/internals/JavaJNI_Interop.md | 30 + Microsoft.Android.slnx | 1 - .../installers/create-installers.targets | 8 - build-tools/scripts/Jar.targets | 6 +- external/Java.Interop/Directory.Build.targets | 2 +- external/Java.Interop/Java.Interop.slnx | 1 - .../Resources.Designer.cs | 45 -- .../Java.Interop.Localization/Resources.resx | 25 - .../Diagnostic.cs | 6 - .../Extensions/XmlExtensions.cs | 41 - .../CecilImporter.cs | 573 -------------- .../XmlExporter.cs | 193 ----- .../XmlImporter.cs | 237 ------ .../CallableWrapperApplicationConstructor.cs | 26 - .../CallableWrapperConstructor.cs | 61 -- .../CallableWrapperField.cs | 46 -- .../CallableWrapperMethod.cs | 97 --- .../CallableWrapperType.cs | 301 ------- .../CallableWrapperTypeAnnotation.cs | 33 - .../CallableWrapperReaderOptions.cs | 9 - .../CallableWrapperWriterOptions.cs | 19 - .../JavaCallableMethodClassifier.cs | 9 - .../JavaPeerStyle.cs | 6 - .../JavaCallableWrapperGeneratorTests.cs | 742 ------------------ .../XmlImporterTests.cs | 144 ---- external/Java.Interop/tools/jcw-gen/App.cs | 104 --- .../Java.Interop/tools/jcw-gen/jcw-gen.csproj | 31 - .../Java.Interop/tools/jcw-gen/jcw-gen.slnf | 13 - .../GenerateTrimmableTypeMapTests.cs | 82 ++ .../Generator/JcwJavaSourceGenerator.cs | 22 +- .../Generator/ManifestGenerator.cs | 2 +- .../Generator/ModelBuilder.cs | 6 +- .../Scanner/JavaPeerScanner.cs | 15 +- .../TrimmableTypeMapTypes.cs | 2 +- src/Mono.Android/Mono.Android.slnf | 1 - .../Resources/ApplicationRegistration.java | 11 - .../MonoRuntimeProvider.Bundled.java | 2 - .../Tasks/CopyResourceTests.cs | 6 +- .../TrimmableTypeMapBuildTests.cs | 33 +- .../Xamarin.Android.Common.targets | 5 - src/java-runtime/java-runtime.targets | 47 +- .../java/mono/android/DebugRuntime.java | 8 - .../java/mono/android/MonoPackageManager.java | 172 ---- .../android/MonoPackageManager_Resources.java | 3 - .../java/mono/android/Runtime.java | 6 - .../XamarinAndroidEnvironmentVariables.java | 9 - .../mono/android/clr/MonoPackageManager.java | 11 - .../mono/android/debug-net6/BuildConfig.java | 6 - .../java/mono/android/debug/BuildConfig.java | 6 - .../android/release-net6/BuildConfig.java | 6 - .../mono/android/release/BuildConfig.java | 6 - 53 files changed, 179 insertions(+), 3103 deletions(-) delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Extensions/XmlExtensions.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlExporter.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlImporter.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperApplicationConstructor.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperConstructor.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperField.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperMethod.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperType.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperTypeAnnotation.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperReaderOptions.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperWriterOptions.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableMethodClassifier.cs delete mode 100644 external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaPeerStyle.cs delete mode 100644 external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGeneratorTests.cs delete mode 100644 external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/XmlImporterTests.cs delete mode 100644 external/Java.Interop/tools/jcw-gen/App.cs delete mode 100644 external/Java.Interop/tools/jcw-gen/jcw-gen.csproj delete mode 100644 external/Java.Interop/tools/jcw-gen/jcw-gen.slnf delete mode 100644 src/Xamarin.Android.Build.Tasks/Resources/ApplicationRegistration.java delete mode 100644 src/java-runtime/java/mono/android/DebugRuntime.java delete mode 100644 src/java-runtime/java/mono/android/MonoPackageManager.java delete mode 100644 src/java-runtime/java/mono/android/app/XamarinAndroidEnvironmentVariables.java delete mode 100644 src/java-runtime/java/mono/android/debug-net6/BuildConfig.java delete mode 100644 src/java-runtime/java/mono/android/debug/BuildConfig.java delete mode 100644 src/java-runtime/java/mono/android/release-net6/BuildConfig.java delete mode 100644 src/java-runtime/java/mono/android/release/BuildConfig.java diff --git a/.github/instructions/java-interop.instructions.md b/.github/instructions/java-interop.instructions.md index d3203d115b5..0dca712ffd9 100644 --- a/.github/instructions/java-interop.instructions.md +++ b/.github/instructions/java-interop.instructions.md @@ -42,7 +42,7 @@ Additional context for code under `external/Java.Interop/`. This complements the - **`generator/`** — primary tool for generating C# bindings from Java API descriptions. - **`class-parse/`** — parses Java `.class` files and generates API descriptions. - **`java-source-utils/`** — utilities for processing Java source code. -- **`jcw-gen/`** — generates Java Callable Wrapper classes. +- Application Java Callable Wrappers are generated by `src/Microsoft.Android.Sdk.TrimmableTypeMap/`. - **`param-name-importer/`** — imports parameter names from Java source. ### Supporting libraries diff --git a/.github/skills/tests/references/test-catalog.md b/.github/skills/tests/references/test-catalog.md index 239483aa051..53d08000701 100644 --- a/.github/skills/tests/references/test-catalog.md +++ b/.github/skills/tests/references/test-catalog.md @@ -27,7 +27,7 @@ These tests can be run immediately with `dotnet test` on the `.csproj`, even if | **java source** | `external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/Java.Interop.Tools.JavaSource-Tests.csproj -v minimal` | | **maven** | `external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/Java.Interop.Tools.Maven-Tests.csproj -v minimal` | | **api xml adjuster** | `external/Java.Interop/tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests/` | `dotnet test external/Java.Interop/tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests.csproj -v minimal` | -| **java callable wrappers** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -v minimal` | +| **Java peer naming/scanning** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -v minimal` | | **java type system** | `external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/Java.Interop.Tools.JavaTypeSystem-Tests.csproj -v minimal` | | **expressions** | `external/Java.Interop/tests/Java.Interop.Tools.Expressions-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Expressions-Tests/Java.Interop.Tools.Expressions-Tests.csproj -v minimal` ⚠️ Requires `javac` | | **generator tools** | `external/Java.Interop/tests/Java.Interop.Tools.Generator-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Generator-Tests/Java.Interop.Tools.Generator-Tests.csproj -v minimal` | @@ -198,7 +198,7 @@ cause, or stack-trace extraction fails, while borrowed references remain valid. | Test Area | Assembly / Project | Notes | |-----------|--------------------|-------| | **generator** | `external/Java.Interop/tests/generator-Tests/` | Binding generator tests | -| **java callable wrappers** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | JCW generation | +| **Java peer naming/scanning** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | Naming, scanning, and type-name mapping; current JCW generation is covered by the trimmable type map suites | | **java type system** | `external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/` | Java type system tooling | | **java source** | `external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/` | Java source generation | | **maven** | `external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/` | Maven integration | diff --git a/Documentation/guides/internals/JavaJNI_Interop.md b/Documentation/guides/internals/JavaJNI_Interop.md index 6863195103e..7abbc92ec34 100644 --- a/Documentation/guides/internals/JavaJNI_Interop.md +++ b/Documentation/guides/internals/JavaJNI_Interop.md @@ -82,6 +82,27 @@ The main outputs are: The app build also generates needed **platform JCWs** from framework inputs alongside user JCWs: for example, the [build tests](../../../src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs) check for `typemap/java/android/app/ActivityTracker.java` and its `Runtime.registerNatives` call. The [reference pack](../../../build-tools/create-packs/Microsoft.Android.Ref.proj) no longer ships prebuilt `mono.android.jar` or `mono.android.dex`. The handwritten Java runtime support instead comes from `java_runtime_trimmable.jar`, selected by [`_CollectRuntimeJarFilenames`](../../../src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets); this is not a jar of pre-generated platform JCWs. `ApplicationRegistration.java` is generated separately during the app build. +The .NET 12 cleanup retires the standalone `jcw-gen` tool and the legacy public +JCW emitter in `Java.Interop.Tools.JavaCallableWrappers`: its `CallableWrapper*` +model/writers, reader/writer options, `JavaPeerStyle`, method classifier, and +Cecil/XML import/export adapters. That emitter produced `__md_methods`, +`Runtime.register`, and `TypeManager.Activate` references whose runtime +implementations had already been removed. The assembly's shared naming, +scanning, hashing, and type-name mapping utilities remain available, as does +the supported XAJavaInterop1 **C# binding** generator. Application JCWs are +generated exclusively by the trimmable pipeline. + +The SDK likewise ships only `java_runtime_trimmable.jar` and its DEX companion. +The unused `java_runtime`, `java_runtime_fastdev`, `java_runtime_clr`, and +`java_runtime_fastdev_clr` artifact pairs, Java `DebugRuntime`/`BuildConfig` +classes, and old environment placeholder are retired. `Runtime.init`, +`createNewContext`, `createNewContextWithData`, `switchToContext`, +`destroyContexts`, `MonoPackageManager.setContext`, and `getDependencies` +are no longer supplied. These are intentional tooling/bootstrap compatibility +removals; custom build tools and Java sources must use the retained runtime +artifact and current startup path. `Runtime.initInternal`, `registerNatives`, +GC peers, and `ApplicationRegistration.Context` remain live. + Each per-assembly TypeMap contains assembly-level mapping attributes: a key such as `my/app/MainActivity`, a proxy type, and, for a trimmable mapping, the managed target type. The root references the per-assembly maps via `TypeMapAssemblyTargetAttribute`. The emitter writes **IL and metadata**, not `.cs` files; the C# in the sections below is an explanatory translation of emitted code, not a file that a developer should edit. See [`TypeMapAssemblyGenerator`](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyGenerator.cs), [`TypeMapAssemblyEmitter.EmitTypeMapAttribute`](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.cs), and the [build-pipeline guide](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/README.md). For the example Activity, think of a mapping like this **conceptual C#**: @@ -122,6 +143,15 @@ When JNI returns an object or Java passes one into managed code, [`TrimmableType The generated Java `onCreate` calls its native `n_OnCreate_Landroid_os_Bundle_`; constructors similarly declare generated `nctor_*` native callbacks, and instantiate/activate the managed peer when appropriate. The class's static block calls `mono.android.Runtime.registerNatives (MainActivity.class)` when the class is first initialized. This is **per Java class**. Application and instrumentation JCWs instead use a guarded `__md_registerNatives()` helper called from their generated wrappers: registration in their static initializer can be too early in startup. The declaration of `registerNatives(Class)` in [`mono.android.Runtime`](../../../src/java-runtime/java/mono/android/Runtime.java) is handwritten Java; individual JCWs and their registration calls are generated. +Abstract JCWs retain their Java constructors and `super(...)` calls for +subclasses, but do not declare or call native constructor bridges. Deferred +Application/Instrumentation hierarchies also omit those bridges and their +unused managed UCO constructor registrations; managed `CreateInstance` +activation remains available. A deferred class with no non-constructor +callbacks needs no lazy registration helper or flag. Callback-bearing +deferred classes still use the helper, and nonempty native registration, +concrete constructor guards, GC hooks, and startup registration remain intact. + There is no concatenated `__md_methods` string and no `Runtime.register("managed.Type, Assembly", ...)` registration in this path. The old JNI native-symbol mangling rules (`Java_package_Class_method...`) matter for symbol-lookup-based JNI code, but generated app JCW callbacks here are associated with their Java declarations through [`RegisterNatives`](https://docs.oracle.com/en/java/javase/17/docs/specs/jni/functions.html#registernatives): the Java method **name** and **signature** must match; no `Java_...` export is required for each method. ### Runtime startup and registration handshake diff --git a/Microsoft.Android.slnx b/Microsoft.Android.slnx index 1cdff0691f1..c2207a3e643 100644 --- a/Microsoft.Android.slnx +++ b/Microsoft.Android.slnx @@ -72,7 +72,6 @@ - diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets index 3c86cddd768..257d1654ee4 100644 --- a/build-tools/installers/create-installers.targets +++ b/build-tools/installers/create-installers.targets @@ -58,16 +58,8 @@ <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)NuGet.Versioning.dll" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)r8.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)bundletool.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_trimmable.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime.dex" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev.dex" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_trimmable.dex" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.dex" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.dex" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)manifestmerger.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)proguard-android-optimize.txt" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)proguard-android.txt" /> diff --git a/build-tools/scripts/Jar.targets b/build-tools/scripts/Jar.targets index 26953d7344e..eff4dbac267 100644 --- a/build-tools/scripts/Jar.targets +++ b/build-tools/scripts/Jar.targets @@ -9,14 +9,14 @@ - <_RuntimeJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java_runtime.jar - <_RuntimeJar_System Condition=" '$(_XamarinAndroidMSBuildDirectory)' != '' ">$(_XamarinAndroidMSBuildDirectory)\java_runtime.jar + <_RuntimeJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java_runtime_trimmable.jar + <_RuntimeJar_System Condition=" '$(_XamarinAndroidMSBuildDirectory)' != '' ">$(_XamarinAndroidMSBuildDirectory)\java_runtime_trimmable.jar <_JavaRuntimeJarPath Condition=" Exists($(_RuntimeJar_InTree)) ">$(_RuntimeJar_InTree) <_JavaRuntimeJarPath Condition=" '$(_JavaRuntimeJarPath)' == '' and Exists($(_RuntimeJar_System)) ">$(_RuntimeJar_System) - diff --git a/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs b/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs index 1dbc8440e70..1285bfe8133 100644 --- a/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs +++ b/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs @@ -447,42 +447,6 @@ public static string Generator_BG8C03 { } } - /// - /// Looks up a localized string similar to Cannot generate Java wrapper for type '{0}'. Only 'class' types are supported.. - /// - public static string JavaCallableWrappers_XA4200 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4200", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot determine JNI name for type '{0}'.. - /// - public static string JavaCallableWrappers_XA4201 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4201", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The 'Name' property must be a fully qualified type like 'com.example.MyClass' and no package was found for '{0}'.. - /// - public static string JavaCallableWrappers_XA4203 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4203", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to resolve interface type '{0}'. Are you missing an assembly reference?. - /// - public static string JavaCallableWrappers_XA4204 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4204", resourceCulture); - } - } - /// /// Looks up a localized string similar to [ExportField] can only be used on methods with 0 parameters.. /// @@ -519,15 +483,6 @@ public static string JavaCallableWrappers_XA4208 { } } - /// - /// Looks up a localized string similar to Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin.. - /// - public static string JavaCallableWrappers_XA4217 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4217", resourceCulture); - } - } - /// /// Looks up a localized string similar to Unable to preload reference '{0}'.. /// diff --git a/external/Java.Interop/src/Java.Interop.Localization/Resources.resx b/external/Java.Interop/src/Java.Interop.Localization/Resources.resx index 18a5041ecad..29fa2c0e46a 100644 --- a/external/Java.Interop/src/Java.Interop.Localization/Resources.resx +++ b/external/Java.Interop/src/Java.Interop.Localization/Resources.resx @@ -316,27 +316,6 @@ The following terms should not be translated: Metadata.xml, path. JNI signature override '{0}' is invalid or does not match the parameter count for member '{1}'. {0} - JNI method signature. {1} - .NET member. - - Cannot generate Java wrapper for type '{0}'. Only 'class' types are supported. - {0} - Java type. -The following terms should not be translated: -class. - - - Cannot determine JNI name for type '{0}'. - {0} - Java type. -The following terms should not be translated: JNI. - - - The 'Name' property must be a fully qualified type like 'com.example.MyClass' and no package was found for '{0}'. - {0} - Java type. -The following terms should not be translated: -Name, com.example.MyClass. - - - Unable to resolve interface type '{0}'. Are you missing an assembly reference? - {0} - Java interface. - [ExportField] can only be used on methods with 0 parameters. The following terms should not be translated: [ExportField]. @@ -353,10 +332,6 @@ Name, com.example.MyClass. [ExportField] cannot be used on a method returning 'void'. The following terms should not be translated: [ExportField], void. - - Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin. - {0} - Kotlin method name. - Unable to preload reference '{0}'. {0} - assembly path diff --git a/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs b/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs index a260ba98f42..0f5efbb563c 100644 --- a/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs +++ b/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs @@ -91,10 +91,6 @@ namespace Java.Interop.Tools.Diagnostics { // XA4110 The registrar cannot marshal the out parameter of type `{0}` in signature for method `{1}`. // XA4111 The registrar cannot build a signature for type `{0}' in method `{1}`. // XA42xx ACW generation - // XA4200 Can only generate ACW's for `claas` types. - // XA4201 Unable to determine JNI name for type {0}. - // XA4203 The specified type name must be fully qualified. - // XA4204 Unable to resolve interface type '{0}'. Are you missing an assembly reference? // XA4205 [ExportField] can only be used on methods with 0 parameters. // XA4206 [Export] cannot be used on a generic type. // XA4207 [ExportField] cannot be used on a generic type. @@ -103,7 +99,6 @@ namespace Java.Interop.Tools.Diagnostics { // XA4210 "You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute." // XA4211 AndroidManifest.xml //uses-sdk/@android:targetSdkVersion '{0}' is less than $(TargetFrameworkVersion) '{1}'. Using API-{1} for ACW compilation. // XA4212 Type `{0}` implements `Android.Runtime.IJavaObject` but does not inherit `Java.Lang.Object` or `Java.Lang.Throwable`. This is not supported. - // XA4217 Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin." // XA5xxx GCC and toolchain // XA32xx .apk generation // XA4300 Unsupported $(AndroidSupportedAbis) value '{0}'; ignoring. @@ -195,4 +190,3 @@ public static Action CreateConsoleLogger () } } } - diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Extensions/XmlExtensions.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Extensions/XmlExtensions.cs deleted file mode 100644 index b70f24aae8e..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Extensions/XmlExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Xml; -using System.Xml.Linq; - -namespace Java.Interop.Tools.JavaCallableWrappers.Extensions; - -static class XmlExtensions -{ - public static T GetAttributeOrDefault (this XElement xml, string name, T defaultValue) - { - var value = xml.Attribute (name)?.Value; - - if (string.IsNullOrWhiteSpace (value)) - return defaultValue; - - return (T) Convert.ChangeType (value, typeof (T)); - } - - public static string GetRequiredAttribute (this XElement xml, string name) - { - var value = xml.Attribute (name)?.Value; - - if (string.IsNullOrWhiteSpace (value)) - throw new InvalidOperationException ($"Missing required attribute '{name}' within element `{xml.ToString()}`."); - - return value!; // NRT - Guarded by IsNullOrWhiteSpace check above - } - - public static void WriteAttributeStringIfNotNull (this XmlWriter xml, string name, string? value) - { - if (value is not null) - xml.WriteAttributeString (name, value); - } - - public static void WriteAttributeStringIfNotFalse (this XmlWriter xml, string name, bool value) - { - // If value is false, don't write the attribute, we'll default to false on import - if (value) - xml.WriteAttributeString (name, value.ToString ()); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs deleted file mode 100644 index 75b14dd618e..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs +++ /dev/null @@ -1,573 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Android.Runtime; -using Java.Interop.Tools.Cecil; -using Java.Interop.Tools.Diagnostics; -using Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; -using Java.Interop.Tools.JavaCallableWrappers.Utilities; -using Java.Interop.Tools.TypeNameMappings; -using Mono.Cecil; - -namespace Java.Interop.Tools.JavaCallableWrappers.Adapters; - -public class CecilImporter -{ - // 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); - - static CallableWrapperType CreateType (TypeDefinition type, IMetadataResolver resolver, CallableWrapperReaderOptions? options = null, string? outerType = null) - { - if (type.IsEnum || type.IsInterface || type.IsValueType) - Diagnostic.Error (4200, CecilExtensions.LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4200, type.FullName); - - var jniName = JavaNativeTypeManager.ToJniName (type, resolver); - - if (jniName is null) - Diagnostic.Error (4201, CecilExtensions.LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4201, type.FullName); - - if (outerType != null && !string.IsNullOrEmpty (outerType)) { - jniName = jniName.Substring (outerType.Length + 1); - ExtractJavaNames (outerType, out var p, out outerType); - } - - ExtractJavaNames (jniName, out var package, out var name); - - 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))) - Diagnostic.Error (4203, CecilExtensions.LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4203, jniName); - - var cwt = new CallableWrapperType (name, package, type.GetPartialAssemblyQualifiedName (resolver)) { - IsApplication = JavaNativeTypeManager.IsApplication (type, resolver), - IsInstrumentation = JavaNativeTypeManager.IsInstrumentation (type, resolver), - IsAbstract = type.IsAbstract, - ApplicationJavaClass = options.DefaultApplicationJavaClass, - GenerateOnCreateOverrides = options.DefaultGenerateOnCreateOverrides, - MonoRuntimeInitialization = options.DefaultMonoRuntimeInitialization, - }; - - // Type annotations - cwt.Annotations.AddRange (CreateAnnotations (type, resolver)); - - // Extends - cwt.ExtendsType = GetJavaTypeName (type.BaseType, resolver); - - // Implemented interfaces - var interfaces = type.Interfaces - .Select (iface => resolver.Resolve (iface.InterfaceType)) - .Where (iface => iface is not null && CecilExtensions.GetTypeRegistrationAttributes (iface).Any ()) - .ToList (); - var addedInterfaces = new HashSet (); - foreach (var iface in interfaces) { - if (interfaces.Any (other => iface.FullName != other.FullName && iface.IsAssignableFrom (other, resolver))) - continue; - - var javaTypeName = GetJavaTypeName (iface, resolver); - if (addedInterfaces.Add (javaTypeName)) - cwt.ImplementedInterfaces.Add (javaTypeName); - } - - // Application constructor - if (CreateApplicationConstructor (cwt.Name, type, resolver) is CallableWrapperApplicationConstructor app_ctor) - cwt.ApplicationConstructor = app_ctor; - - // Methods - foreach (var minfo in type.Methods.Where (m => !m.IsConstructor)) { - var baseRegisteredMethod = CecilExtensions.GetBaseRegisteredMethod (minfo, resolver); - - if (baseRegisteredMethod is not null) - AddMethod (cwt, type, baseRegisteredMethod, minfo, options.MethodClassifier, resolver); - else if (minfo.AnyCustomAttributes ("Java.Interop.JavaCallableAttribute")) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } else if (minfo.AnyCustomAttributes ("Java.Interop.JavaCallableConstructorAttribute")) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } else if (minfo.AnyCustomAttributes (typeof (ExportFieldAttribute))) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } else if (minfo.AnyCustomAttributes (typeof (ExportAttribute))) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } - } - - // Methods from interfaces - foreach (InterfaceImplementation ifaceInfo in type.Interfaces) { - var typeReference = ifaceInfo.InterfaceType; - var typeDefinition = resolver.Resolve (typeReference); - - if (typeDefinition is null) { - Diagnostic.Error (4204, - CecilExtensions.LookupSource (type), - Localization.Resources.JavaCallableWrappers_XA4204, - typeReference.FullName); - continue; - } - - if (!CecilExtensions.GetTypeRegistrationAttributes (typeDefinition).Any ()) - continue; - - foreach (MethodDefinition imethod in typeDefinition.Methods) { - if (imethod.IsStatic) - continue; - - AddMethod (cwt, type, imethod, imethod, options.MethodClassifier, resolver); - } - } - - // Constructors - var ctorTypes = new List () { - type, - }; - - foreach (var bt in type.GetBaseTypes (resolver)) { - ctorTypes.Add (bt); - var rattr = CecilExtensions.GetTypeRegistrationAttributes (bt).FirstOrDefault (); - - if (rattr != null && rattr.DoNotGenerateAcw) - break; - } - - ctorTypes.Reverse (); - - var curCtors = new List (); - - foreach (var minfo in type.Methods) { - if (minfo.IsConstructor && minfo.AnyCustomAttributes (typeof (ExportAttribute))) { - if (minfo.IsStatic) { - // Diagnostic.Warning (log, "ExportAttribute does not work on static constructor"); - } else { - if (CreateConstructor (cwt, minfo, ctorTypes [0], type, outerType, null, curCtors, false, true, resolver) is CallableWrapperConstructor c) - cwt.Constructors.Add (c); - - cwt.HasExport = true; - } - } - } - - AddConstructors (cwt, ctorTypes [0], type, outerType, null, curCtors, true, resolver); - - for (var i = 1; i < ctorTypes.Count; ++i) { - var baseCtors = curCtors; - curCtors = new List (); - AddConstructors (cwt, ctorTypes [i], type, outerType, baseCtors, curCtors, false, resolver); - } - - AddNestedTypes (cwt, type, resolver, options); - - return cwt; - } - - static CallableWrapperField CreateField (MethodDefinition method, string fieldName, IMetadataResolver resolver) - { - var visibility = GetJavaAccess (method.Attributes & MethodAttributes.MemberAccessMask); - var type_name = JavaNativeTypeManager.ReturnTypeFromSignature (JavaNativeTypeManager.GetJniSignature (method, resolver))?.Type - ?? throw new ArgumentException ($"Could not get JNI signature for method `{method.Name}`", nameof (method)); - - var field = new CallableWrapperField (fieldName, type_name, visibility, method.Name) { - IsStatic = method.IsStatic, - }; - - field.Annotations.AddRange (CreateAnnotations (method, resolver)); - - return field; - } - - // Constructor with [Register] attribute - static CallableWrapperConstructor CreateConstructor (MethodDefinition methodDefinition, CallableWrapperType type, RegisterAttribute register, string? managedParameters, string? outerType, IMetadataResolver cache, bool shouldBeDynamicallyRegistered = true) - { - var method = CreateConstructor (methodDefinition.Name, type, register.Signature, register.Connector, managedParameters, outerType, null); - - method.Annotations.AddRange (CreateAnnotations (methodDefinition, cache)); - method.IsDynamicallyRegistered = shouldBeDynamicallyRegistered; - - return method; - } - - // Constructor with [Export] attribute - static CallableWrapperConstructor CreateConstructor (MethodDefinition methodDefinition, CallableWrapperType type, ExportAttribute export, string? managedParameters, IMetadataResolver resolver) - { - var method = CreateConstructor (methodDefinition.Name, type, JavaNativeTypeManager.GetJniSignature (methodDefinition, resolver), "__export__", null, null, export.SuperArgumentsString); - - method.IsExport = true; - method.IsStatic = methodDefinition.IsStatic; - method.JavaAccess = GetJavaAccess (methodDefinition.Attributes & MethodAttributes.MemberAccessMask); - method.ThrownTypeNames = export.ThrownNames; - method.JavaNameOverride = export.Name; - method.ManagedParameters = managedParameters; - method.Annotations.AddRange (CreateAnnotations (methodDefinition, resolver)); - - return method; - } - - // Common constructor creation code - static CallableWrapperConstructor CreateConstructor (string name, CallableWrapperType type, string? signature, string? connector, string? managedParameters, string? outerType, string? superCall) - { - signature = signature ?? throw new ArgumentNullException ("`connector` cannot be null.", nameof (connector)); - var method_name = "n_" + name + ":" + signature + ":" + connector; - - var method = new CallableWrapperConstructor (type, name, method_name, signature); - - PopulateMethod (method, signature, managedParameters, outerType, superCall); - - method.Name = type.Name; - - return method; - } - - // Method with a [Register] attribute - static CallableWrapperMethod CreateMethod (MethodDefinition methodDefinition, CallableWrapperType declaringType, RegisterAttribute register, string? managedParameters, string? outerType, IMetadataResolver resolver, bool shouldBeDynamicallyRegistered = true) - { - var method = CreateMethod (register.Name, declaringType, register.Signature, register.Connector, managedParameters, outerType, null); - - method.Annotations.AddRange (CreateAnnotations (methodDefinition, resolver)); - method.IsDynamicallyRegistered = shouldBeDynamicallyRegistered; - - return method; - } - - // Method with an [Export] attribute - static CallableWrapperMethod CreateMethod (MethodDefinition methodDefinition, CallableWrapperType declaringType, ExportAttribute export, string? managedParameters, IMetadataResolver resolver) - { - var method = CreateMethod (methodDefinition.Name, declaringType, JavaNativeTypeManager.GetJniSignature (methodDefinition, resolver), "__export__", null, null, export.SuperArgumentsString); - - method.IsExport = true; - method.IsStatic = methodDefinition.IsStatic; - method.JavaAccess = GetJavaAccess (methodDefinition.Attributes & MethodAttributes.MemberAccessMask); - method.ThrownTypeNames = export.ThrownNames; - method.JavaNameOverride = export.Name; - method.ManagedParameters = managedParameters; - method.Annotations.AddRange (CreateAnnotations (methodDefinition, resolver)); - - return method; - } - - // Method with an [ExportField] attribute - static CallableWrapperMethod CreateMethod (MethodDefinition methodDefinition, CallableWrapperType declaringType, IMetadataResolver resolver) - { - var method = CreateMethod (methodDefinition.Name, declaringType, JavaNativeTypeManager.GetJniSignature (methodDefinition, resolver), "__export__", null, null, null); - - if (methodDefinition.HasParameters) - Diagnostic.Error (4205, CecilExtensions.LookupSource (methodDefinition), Localization.Resources.JavaCallableWrappers_XA4205); - if (methodDefinition.ReturnType.MetadataType == MetadataType.Void) - Diagnostic.Error (4208, CecilExtensions.LookupSource (methodDefinition), Localization.Resources.JavaCallableWrappers_XA4208); - - method.IsExport = true; - method.IsStatic = methodDefinition.IsStatic; - method.JavaAccess = GetJavaAccess (methodDefinition.Attributes & MethodAttributes.MemberAccessMask); - - // Annotations are processed within CallableWrapperField, not the initializer method. So we don't generate them here. - - return method; - } - - // Common method creation code - static CallableWrapperMethod CreateMethod (string name, CallableWrapperType declaringType, string? signature, string? connector, string? managedParameters, string? outerType, string? superCall) - { - signature = signature ?? throw new ArgumentNullException ("`connector` cannot be null.", nameof (connector)); - var method_name = "n_" + name + ":" + signature + ":" + connector?.Replace ('/', '+'); - - var method = new CallableWrapperMethod (declaringType, name, method_name, signature); - - PopulateMethod (method, signature, managedParameters, outerType, superCall); - - return method; - } - - // This is done this way to allow sharing between CallableWrapperMethod and CallableWrapperConstructor - static void PopulateMethod (CallableWrapperMethod method, string signature, string? managedParameters, string? outerType, string? superCall) - { - method.ManagedParameters = managedParameters; - - var jnisig = signature; - var closer = jnisig.IndexOf (')'); - var ret = jnisig.Substring (closer + 1); - - method.Retval = JavaNativeTypeManager.Parse (ret)?.Type; - - var jniparms = jnisig.Substring (1, closer - 1); - - if (string.IsNullOrEmpty (jniparms) && string.IsNullOrEmpty (superCall)) - return; - - var parms = new StringBuilder (); - var scall = new StringBuilder (); - var acall = new StringBuilder (); - var first = true; - var i = 0; - - foreach (var jti in JavaNativeTypeManager.FromSignature (jniparms)) { - if (outerType != null) { - acall.Append (outerType).Append (".this"); - outerType = null; - continue; - } - - var parmType = jti.Type; - - if (!first) { - parms.Append (", "); - scall.Append (", "); - acall.Append (", "); - } - - first = false; - parms.Append (parmType).Append (" p").Append (i); - scall.Append ("p").Append (i); - acall.Append ("p").Append (i); - ++i; - } - - method.Params = parms.ToString (); - method.SuperCall = superCall ?? scall.ToString (); - method.ActivateCall = acall.ToString (); - } - - static void AddConstructors (CallableWrapperType declaringType, TypeDefinition type, TypeDefinition rootType, string? outerType, List? baseCtors, List curCtors, bool onlyRegisteredOrExportedCtors, IMetadataResolver cache) - { - foreach (var ctor in type.Methods) - if (ctor.IsConstructor && !ctor.IsStatic && !ctor.AnyCustomAttributes (typeof (ExportAttribute))) - if (CreateConstructor (declaringType, ctor, type, rootType, outerType, baseCtors, curCtors, onlyRegisteredOrExportedCtors, false, cache) is CallableWrapperConstructor c) - declaringType.Constructors.Add (c); - } - - static CallableWrapperConstructor? CreateConstructor (CallableWrapperType declaringType, MethodDefinition ctor, TypeDefinition type, TypeDefinition rootType, string? outerType, List? baseCtors, List curCtors, bool onlyRegisteredOrExportedCtors, bool skipParameterCheck, IMetadataResolver cache) - { - // We create a parameter-less constructor for the application class, so don't use the imported one - if (!ctor.HasParameters && JavaNativeTypeManager.IsApplication (rootType, cache)) - return null; - - var managedParameters = GetManagedParameters (ctor, outerType, type, cache); - - if (!skipParameterCheck && (managedParameters == null || declaringType.Constructors.Any (c => c.ManagedParameters == managedParameters))) - return null; - - // Constructor with [Export] attribute - var eattr = CecilExtensions.GetExportAttributes (ctor, cache).FirstOrDefault (); - - if (eattr != null) { - if (!string.IsNullOrEmpty (eattr.Name)) { - // Diagnostic.Warning (log, "Use of ExportAttribute.Name property is invalid on constructors"); - } - - curCtors.Add (ctor); - return CreateConstructor (ctor, declaringType, eattr, managedParameters, cache); - } - - // Constructor with [Register] attribute - var rattr = CecilExtensions.GetMethodRegistrationAttributes (ctor).FirstOrDefault (); - - if (rattr != null) { - if (declaringType.Constructors.Any (c => c.JniSignature == rattr.Signature)) - return null; - - curCtors.Add (ctor); - return CreateConstructor (ctor, declaringType, rattr, managedParameters, outerType, cache); - } - - if (onlyRegisteredOrExportedCtors) - return null; - - // Constructors without [Export] or [Register] attributes - var jniSignature = JavaNativeTypeManager.GetJniSignature (ctor, cache); - - if (jniSignature is null) - return null; - - if (declaringType.Constructors.Any (c => c.JniSignature == jniSignature)) - return null; - - if (baseCtors is null) - throw new InvalidOperationException ("`baseCtors` should not be null!"); - - if (baseCtors.Any (m => m.Parameters.AreParametersCompatibleWith (ctor.Parameters, cache))) { - curCtors.Add (ctor); - return CreateConstructor (".ctor", declaringType, jniSignature, "", managedParameters, outerType, null); - } - - if (baseCtors.Any (m => !m.HasParameters)) { - curCtors.Add (ctor); - return CreateConstructor (".ctor", declaringType, jniSignature, "", managedParameters, outerType, ""); - } - - return null; - } - - static string GetManagedParameters (MethodDefinition ctor, string? outerType, TypeDefinition type, IMetadataResolver cache) - { - var sb = new StringBuilder (); - - foreach (var pdef in ctor.Parameters) { - if (sb.Length > 0) - sb.Append (':'); - if (outerType != null && sb.Length == 0) - sb.Append (type.DeclaringType.GetPartialAssemblyQualifiedName (cache)); - else - sb.Append (pdef.ParameterType.GetPartialAssemblyQualifiedName (cache)); - } - - return sb.ToString (); - } - - static CallableWrapperApplicationConstructor? CreateApplicationConstructor (string name, TypeDefinition type, IMetadataResolver resolver) - { - if (!JavaNativeTypeManager.IsApplication (type, resolver)) - return null; - - return new CallableWrapperApplicationConstructor (name); - } - - static void AddNestedTypes (CallableWrapperType declaringType, TypeDefinition type, IMetadataResolver cache, CallableWrapperReaderOptions? options) - { - if (!type.HasNestedTypes) - return; - - foreach (var nt in type.NestedTypes) { - if (!nt.HasJavaPeer (cache)) - continue; - if (!JavaNativeTypeManager.IsNonStaticInnerClass (nt, cache)) - continue; - - declaringType.NestedTypes.Add (CreateType (nt, cache, options, JavaNativeTypeManager.ToJniName (type, cache))); - AddNestedTypes (declaringType, nt, cache, options); - } - - declaringType.HasExport |= declaringType.NestedTypes.Any (t => t.HasExport); - } - - static void AddMethod (CallableWrapperType declaringType, TypeDefinition type, MethodDefinition? registeredMethod, MethodDefinition implementedMethod, JavaCallableMethodClassifier? methodClassifier, IMetadataResolver cache) - { - if (registeredMethod != null) - foreach (RegisterAttribute attr in CecilExtensions.GetMethodRegistrationAttributes (registeredMethod)) { - // Check for Kotlin-mangled methods that cannot be overridden - if (attr.Name.Contains ("-impl") || (attr.Name.Length > 7 && attr.Name [attr.Name.Length - 8] == '-')) - Diagnostic.Error (4217, CecilExtensions.LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4217, attr.Name); - - var shouldBeDynamicallyRegistered = methodClassifier?.ShouldBeDynamicallyRegistered (type, registeredMethod, implementedMethod, attr.OriginAttribute) ?? true; - var method = CreateMethod (implementedMethod, declaringType, attr, null, null, cache, shouldBeDynamicallyRegistered); - - if (!registeredMethod.IsConstructor && !declaringType.Methods.Any (m => m.Name == method.Name && m.Params == method.Params)) - declaringType.Methods.Add (method); - } - foreach (ExportAttribute attr in CecilExtensions.GetExportAttributes (implementedMethod, cache)) { - if (type.HasGenericParameters) - Diagnostic.Error (4206, CecilExtensions.LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4206); - - var method = CreateMethod (implementedMethod, declaringType, attr, null, cache); - - if (!string.IsNullOrEmpty (attr.SuperArgumentsString)) { - // Diagnostic.Warning (log, "Use of ExportAttribute.SuperArgumentsString property is invalid on methods"); - } - - if (!implementedMethod.IsConstructor && !declaringType.Methods.Any (m => m.Name == method.Name && m.Params == method.Params)) - declaringType.Methods.Add (method); - } - foreach (ExportFieldAttribute attr in CecilExtensions.GetExportFieldAttributes (implementedMethod)) { - if (type.HasGenericParameters) - Diagnostic.Error (4207, CecilExtensions.LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4207); - - var method = CreateMethod (implementedMethod, declaringType, cache); - - if (!implementedMethod.IsConstructor && !declaringType.Methods.Any (m => m.Name == method.Name && m.Params == method.Params)) { - declaringType.Methods.Add (method); - declaringType.Fields.Add (CreateField (implementedMethod, attr.Name, cache)); - } - } - } - - static void ExtractJavaNames (string jniName, out string package, out string type) - { - var i = jniName.LastIndexOf ('/'); - - if (i < 0) { - type = jniName; - package = string.Empty; - } else { - type = jniName.Substring (i + 1); - package = jniName.Substring (0, i).Replace ('/', '.'); - } - } - - static string GetJavaTypeName (TypeReference r, IMetadataResolver cache) - { - var d = cache.Resolve (r); - var jniName = JavaNativeTypeManager.ToJniName (d, cache); - - if (jniName is null) { - Diagnostic.Error (4201, Localization.Resources.JavaCallableWrappers_XA4201, r.FullName); - throw new InvalidOperationException ("--nrt:jniName-- Should not be reached"); - } - - return jniName.Replace ('/', '.').Replace ('$', '.'); - } - - static IEnumerable CreateAnnotations (ICustomAttributeProvider type, IMetadataResolver resolver) - { - foreach (var ca in type.CustomAttributes) { - var annotation = CreateAnnotation (ca, resolver); - - if (annotation is not null) - yield return annotation; - } - } - - static CallableWrapperTypeAnnotation? CreateAnnotation (CustomAttribute ca, IMetadataResolver resolver) - { - var catype = resolver.Resolve (ca.AttributeType); - var tca = catype.CustomAttributes.FirstOrDefault (a => a.AttributeType.FullName == "Android.Runtime.AnnotationAttribute"); - - if (tca is null) - return null; - - var name_object = tca.ConstructorArguments [0].Value; - - // Should never be hit - if (name_object is not string name) - throw new ArgumentException ($"Expected a string for the first argument of the {nameof (RegisterAttribute)} constructor.", nameof (ca)); - - var annotation = new CallableWrapperTypeAnnotation (name); - - foreach (var p in ca.Properties) { - var pd = catype.Properties.FirstOrDefault (pp => pp.Name == p.Name); - var reg = pd?.CustomAttributes.FirstOrDefault (pdca => pdca.AttributeType.FullName == "Android.Runtime.RegisterAttribute"); - var key = reg != null ? (string) reg.ConstructorArguments [0].Value : p.Name; - var value = ManagedValueToJavaSource (p.Argument.Value); - - annotation.Properties.Add (new KeyValuePair (key, value)); - } - - return annotation; - } - - // FIXME: this is hacky. Is there any existing code for value to source conversion? - static string ManagedValueToJavaSource (object value) - { - if (value is string) - return "\"" + value.ToString ()?.Replace ("\"", "\"\"") + '"'; - else if (value.GetType ().FullName == "Java.Lang.Class") - return value.ToString () + ".class"; - else if (value is bool v) - return v ? "true" : "false"; - else - return value.ToString () ?? ""; - } - - static string GetJavaAccess (MethodAttributes access) - { - return access switch { - MethodAttributes.Public => "public", - MethodAttributes.FamORAssem => "protected", - MethodAttributes.Family => "protected", - _ => "private", - }; - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlExporter.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlExporter.cs deleted file mode 100644 index 748270142f0..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlExporter.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Xml; -using Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; -using Java.Interop.Tools.JavaCallableWrappers.Extensions; - -namespace Java.Interop.Tools.JavaCallableWrappers.Adapters; - -public static class XmlExporter -{ - static XmlWriterSettings settings = new XmlWriterSettings { - Indent = true, - NewLineOnAttributes = false, - OmitXmlDeclaration = true, - }; - - public static void Export (string filename, IEnumerable types) - { - using (var sw = new StreamWriter (filename, false, Encoding.UTF8)) - Export (sw, types); - } - - public static void Export (TextWriter sw, IEnumerable types) - { - using (var xml = XmlWriter.Create (sw, settings)) - Export (xml, types); - } - - public static void Export (XmlWriter xml, IEnumerable types) - { - ExportTypes (xml, types); - } - - static void ExportTypes (XmlWriter xml, IEnumerable types) - { - foreach (var type in types) - ExportType (xml, type); - } - - public static void ExportType (XmlWriter xml, CallableWrapperType type) - { - xml.WriteStartElement ("type"); - xml.WriteAttributeString ("name", type.Name); - xml.WriteAttributeString ("package", type.Package); - xml.WriteAttributeStringIfNotFalse ("is_abstract", type.IsAbstract); - xml.WriteAttributeStringIfNotNull ("application_java_class", type.ApplicationJavaClass); - xml.WriteAttributeStringIfNotFalse ("generate_on_create_overrides", type.GenerateOnCreateOverrides); - xml.WriteAttributeStringIfNotNull ("mono_runtime_initialization", type.MonoRuntimeInitialization); - xml.WriteAttributeStringIfNotNull ("extends_type", type.ExtendsType); - xml.WriteAttributeStringIfNotFalse ("is_application", type.IsApplication); - xml.WriteAttributeStringIfNotFalse ("is_instrumentation", type.IsInstrumentation); - xml.WriteAttributeString ("partial_assembly_qualified_name", type.PartialAssemblyQualifiedName); - xml.WriteAttributeStringIfNotFalse ("has_export", type.HasExport); - - if (type.ApplicationConstructor is not null) - xml.WriteAttributeString ("application_constructor", type.ApplicationConstructor.Name); - - ExportAnnotations (xml, type.Annotations); - ExportImplementedInterfaces (xml, type.ImplementedInterfaces); - ExportConstructors (xml, type.Constructors); - ExportFields (xml, type.Fields); - ExportMethods (xml, type.Methods); - ExportNestedTypes (xml, type.NestedTypes); - - xml.WriteEndElement (); - } - - static void ExportAnnotations (XmlWriter writer, IEnumerable annotations) - { - if (annotations.Count () == 0) - return; - - writer.WriteStartElement ("annotations"); - - foreach (var annotation in annotations) { - writer.WriteStartElement ("annotation"); - writer.WriteAttributeString ("name", annotation.Name); - - foreach (var property in annotation.Properties) { - writer.WriteStartElement ("property"); - writer.WriteAttributeString ("name", property.Key); - writer.WriteAttributeString ("value", property.Value); - writer.WriteEndElement (); - } - - writer.WriteEndElement (); - } - - writer.WriteEndElement (); - } - - static void ExportImplementedInterfaces (XmlWriter writer, List interfaces) - { - if (interfaces.Count == 0) - return; - - writer.WriteStartElement ("implemented_interfaces"); - - foreach (var @interface in interfaces) { - writer.WriteStartElement ("interface"); - writer.WriteAttributeString ("name", @interface); - writer.WriteEndElement (); - } - - writer.WriteEndElement (); - } - - static void ExportConstructors (XmlWriter xml, IEnumerable constructors) - { - if (constructors.Count () == 0) - return; - - xml.WriteStartElement ("constructors"); - - foreach (var constructor in constructors) - ExportMethod (xml, constructor); - - xml.WriteEndElement (); - } - - static void ExportFields (XmlWriter xml, IEnumerable fields) - { - if (fields.Count () == 0) - return; - - xml.WriteStartElement ("fields"); - - foreach (var field in fields) { - xml.WriteStartElement ("field"); - xml.WriteAttributeString ("name", field.FieldName); - xml.WriteAttributeString ("type", field.TypeName); - xml.WriteAttributeString ("visibility", field.Visibility); - xml.WriteAttributeStringIfNotFalse ("is_static", field.IsStatic); - xml.WriteAttributeString ("initializer_name", field.InitializerName); - ExportAnnotations (xml, field.Annotations); - xml.WriteEndElement (); - } - - xml.WriteEndElement (); - } - - static void ExportMethods (XmlWriter xml, IEnumerable methods) - { - if (methods.Count () == 0) - return; - - xml.WriteStartElement ("methods"); - - foreach (var method in methods) - ExportMethod (xml, method); - - xml.WriteEndElement (); - } - - static void ExportMethod (XmlWriter xml, CallableWrapperMethod method) - { - xml.WriteStartElement (method is CallableWrapperConstructor ? "constructor" : "method"); - xml.WriteAttributeString ("name", method.Name); - xml.WriteAttributeString ("method", method.Method); - xml.WriteAttributeString ("jni_signature", method.JniSignature); - xml.WriteAttributeStringIfNotNull ("managed_parameters", method.ManagedParameters); - xml.WriteAttributeStringIfNotNull ("java_name_override", method.JavaNameOverride); - xml.WriteAttributeStringIfNotNull ("params", method.Params); - xml.WriteAttributeStringIfNotNull ("retval", method.Retval); - xml.WriteAttributeStringIfNotNull ("java_access", method.JavaAccess); - xml.WriteAttributeStringIfNotFalse ("is_export", method.IsExport); - xml.WriteAttributeStringIfNotFalse ("is_static", method.IsStatic); - xml.WriteAttributeStringIfNotFalse ("is_dynamically_registered", method.IsDynamicallyRegistered); - xml.WriteAttributeStringIfNotNull ("thrown_type_names", method.ThrownTypeNames != null ? string.Join (", ", method.ThrownTypeNames) : null); - xml.WriteAttributeStringIfNotNull ("super_call", method.SuperCall); - xml.WriteAttributeStringIfNotNull ("activate_call", method.ActivateCall); - - ExportAnnotations (xml, method.Annotations); - - xml.WriteEndElement (); - } - - static void ExportNestedTypes (XmlWriter xml, IEnumerable nestedTypes) - { - if (nestedTypes.Count () == 0) - return; - - xml.WriteStartElement ("nested_types"); - - foreach (var nestedType in nestedTypes) - ExportType (xml, nestedType); - - xml.WriteEndElement (); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlImporter.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlImporter.cs deleted file mode 100644 index 32702c75013..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlImporter.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Xml; -using System.Xml.Linq; -using Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; -using Java.Interop.Tools.JavaCallableWrappers.Extensions; -using Java.Interop.Tools.TypeNameMappings; - -namespace Java.Interop.Tools.JavaCallableWrappers.Adapters; - -public static class XmlImporter -{ - public static List Import (string filename) - { - using (var sr = new StreamReader (filename, Encoding.UTF8)) - return Import (sr); - } - - public static List Import (TextReader sr) - { - using (var xml = XmlReader.Create (sr)) - return Import (xml); - } - - public static List Import (XmlReader xml) - { - var doc = XDocument.Load (xml); - - var types = new List (); - - foreach (var type in doc.Root.Elements ("type")) - types.Add (ImportType (type)); - - return types; - } - - - public static List Import (XElement xml) - { - var types = new List (); - - foreach (var type in xml.Elements ("type")) - types.Add (ImportType (type)); - - return types; - } - - public static CallableWrapperType ImportType (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var package = xml.GetAttributeOrDefault ("package", (string?) ""); - var partial_assembly_qualified_name = xml.GetRequiredAttribute ("partial_assembly_qualified_name"); - - // If package is empty, generate a crc64 package name from the assembly qualified name - if (string.IsNullOrEmpty (package)) - package = GeneratePackageFromAssemblyQualifiedName (partial_assembly_qualified_name); - - var type = new CallableWrapperType (name, package ?? "", partial_assembly_qualified_name) { - ApplicationJavaClass = xml.GetAttributeOrDefault ("application_java_class", (string?) null), - ExtendsType = xml.GetAttributeOrDefault ("extends_type", (string?) null), - GenerateOnCreateOverrides = xml.GetAttributeOrDefault ("generate_on_create_overrides", false), - HasExport = xml.GetAttributeOrDefault ("has_export", false), - IsAbstract = xml.GetAttributeOrDefault ("is_abstract", false), - IsApplication = xml.GetAttributeOrDefault ("is_application", false), - IsInstrumentation = xml.GetAttributeOrDefault ("is_instrumentation", false), - MonoRuntimeInitialization = xml.GetAttributeOrDefault ("mono_runtime_initialization", (string?) null), - }; - - if (xml.GetAttributeOrDefault ("application_constructor", (string?) null) is string applicationConstructor) - type.ApplicationConstructor = new CallableWrapperApplicationConstructor (applicationConstructor); - - ImportAnnotations (type.Annotations, xml.Element ("annotations")); - ImportImplementedInterfaces (type, xml.Element ("implemented_interfaces")); - ImportConstructors (type, xml.Element ("constructors")); - ImportMethods (type, xml.Element ("methods")); - ImportFields (type, xml.Element ("fields")); - - foreach (var nestedType in xml.Elements ("nested_type")) - type.NestedTypes.Add (ImportType (nestedType)); - - return type; - } - - static void ImportAnnotations (List annotations, XElement? xml) - { - foreach (var annotation in xml?.Elements ("annotation") ?? []) { - var a = ImportAnnotation (annotation); - annotations.Add (a); - } - } - - static CallableWrapperTypeAnnotation ImportAnnotation (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var annotation = new CallableWrapperTypeAnnotation (name); - - foreach (var property in xml.Elements ("property")) { - var p = ImportAnnotationProperty (property); - annotation.Properties.Add (p); - } - - return annotation; - } - - static KeyValuePair ImportAnnotationProperty (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var value = xml.GetRequiredAttribute ("value"); - - return new KeyValuePair (name, value); - } - - static void ImportImplementedInterfaces (CallableWrapperType type, XElement? xml) - { - foreach (var iface in xml?.Elements ("interface") ?? []) { - var name = iface.GetRequiredAttribute ("name"); - type.ImplementedInterfaces.Add (name); - } - } - - static void ImportConstructors (CallableWrapperType type, XElement? xml) - { - foreach (var ctor in xml?.Elements ("constructor") ?? []) { - var c = ImportConstructor (type, ctor); - type.Constructors.Add (c); - } - } - - static void ImportMethods (CallableWrapperType type, XElement? xml) - { - foreach (var method in xml?.Elements ("method") ?? []) { - var m = ImportMethod (type, method); - type.Methods.Add (m); - } - } - - static CallableWrapperConstructor ImportConstructor (CallableWrapperType type, XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var method = xml.GetRequiredAttribute ("method"); - var jniSig = xml.GetRequiredAttribute ("jni_signature"); - - var ctor = new CallableWrapperConstructor (type, name, method, jniSig); - FillInMethodDetails (ctor, xml); - - return ctor; - } - - static CallableWrapperMethod ImportMethod (CallableWrapperType type, XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var method = xml.GetRequiredAttribute ("method"); - var jniSig = xml.GetRequiredAttribute ("jni_signature"); - - var m = new CallableWrapperMethod (type, name, method, jniSig); - FillInMethodDetails (m, xml); - - return m; - } - - static void FillInMethodDetails (CallableWrapperMethod method, XElement xml) - { - // Common between constructors and methods - method.ManagedParameters = xml.GetAttributeOrDefault ("managed_parameters", (string?) null); - method.JavaNameOverride = xml.GetAttributeOrDefault ("java_name_override", (string?) null); - method.Params = xml.GetAttributeOrDefault ("params", (string?) null); - method.Retval = xml.GetAttributeOrDefault ("retval", (string?) null); - method.JavaAccess = xml.GetAttributeOrDefault ("java_access", (string?) null); - method.IsExport = xml.GetAttributeOrDefault ("is_export", false); - method.IsStatic = xml.GetAttributeOrDefault ("is_static", false); - method.IsDynamicallyRegistered = xml.GetAttributeOrDefault ("is_dynamically_registered", false); - method.SuperCall = xml.GetAttributeOrDefault ("super_call", (string?) null); - method.ActivateCall = xml.GetAttributeOrDefault ("activate_call", (string?) null); - - if (xml.GetAttributeOrDefault ("thrown_type_names", (string?) null) is string thrownTypeNames) - method.ThrownTypeNames = thrownTypeNames.Split (new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - ImportAnnotations (method.Annotations, xml.Element ("annotations")); - } - - static void ImportFields (CallableWrapperType type, XElement? xml) - { - foreach (var field in xml?.Elements ("field") ?? []) { - var f = ImportField (field); - type.Fields.Add (f); - } - } - - static CallableWrapperField ImportField (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var type = xml.GetRequiredAttribute ("type"); - var visibility = xml.GetRequiredAttribute ("visibility"); - var initializer_name = xml.GetRequiredAttribute ("initializer_name"); - - var field = new CallableWrapperField (name, type, visibility, initializer_name) { - IsStatic = xml.GetAttributeOrDefault ("is_static", false), - }; - - ImportAnnotations (field.Annotations, xml.Element ("annotations")); - - return field; - } - - /// - /// Generates a package name from a partial assembly qualified name. - /// This is used when the package attribute is missing or empty in the XML. - /// - /// The partial assembly qualified name in format "Namespace.TypeName, AssemblyName" - /// A package name based on the current - static string GeneratePackageFromAssemblyQualifiedName (string partialAssemblyQualifiedName) - { - // Format: "Namespace.TypeName, AssemblyName" or "Namespace.TypeName+NestedType, AssemblyName" - var commaIndex = partialAssemblyQualifiedName.IndexOf (','); - if (commaIndex < 0) - return ""; - - var fullTypeName = partialAssemblyQualifiedName.Substring (0, commaIndex).Trim (); - var assemblyName = partialAssemblyQualifiedName.Substring (commaIndex + 1).Trim (); - - // Extract namespace from full type name - // Handle nested types by using '+' as separator - var plusIndex = fullTypeName.IndexOf ('+'); - var typeNameWithoutNested = plusIndex >= 0 ? fullTypeName.Substring (0, plusIndex) : fullTypeName; - - var lastDotIndex = typeNameWithoutNested.LastIndexOf ('.'); - var ns = lastDotIndex >= 0 ? typeNameWithoutNested.Substring (0, lastDotIndex) : ""; - - // If no namespace, return empty (will use default package) - if (string.IsNullOrEmpty (ns)) - return ""; - - return JavaNativeTypeManager.GetPackageName (ns, assemblyName); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperApplicationConstructor.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperApplicationConstructor.cs deleted file mode 100644 index 2d8c40938d2..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperApplicationConstructor.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperApplicationConstructor -{ - public string Name { get; set; } - - public CallableWrapperApplicationConstructor (string name) - { - Name = name; - } - - public void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - sw.Write ("\tpublic "); - sw.Write (Name); - sw.WriteLine (" ()"); - - sw.WriteLine ("\t{"); - sw.WriteLine ("\t\tmono.MonoPackageManager.setContext (this);"); - sw.WriteLine ("\t}"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperConstructor.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperConstructor.cs deleted file mode 100644 index 782f0f9885f..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperConstructor.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperConstructor : CallableWrapperMethod -{ - public CallableWrapperConstructor (CallableWrapperType declaringType, string name, string method, string jniSignature) : base (declaringType, name, method, jniSignature) - { - } - - public override void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - // TODO: we only generate constructors so that Android types w/ no - // default constructor can be subclasses by our generated code. - // - // This does NOT currently allow creating managed types from Java. - sw.WriteLine (); - - foreach (var annotation in Annotations) - annotation.Generate (sw, "", options); - - sw.Write ("\tpublic "); - sw.Write (Name); - - sw.Write (" ("); - sw.Write (Params); - sw.Write (')'); - - sw.WriteLine (ThrowsDeclaration); - - sw.WriteLine ("\t{"); - sw.Write ("\t\tsuper ("); - sw.Write (SuperCall); - sw.WriteLine (");"); - -#if MONODROID_TIMING - sw.WriteLine ("\t\tandroid.util.Log.i(\"MonoDroid-Timing\", \"{0}..ctor({1}): time: \"+java.lang.System.currentTimeMillis());", Name, Params); -#endif - - if (!DeclaringType.CannotRegisterInStaticConstructor) { - - sw.Write ("\t\tif (getClass () == "); - sw.Write (Name); - sw.WriteLine (".class) {"); - - sw.Write ("\t\t\t"); - - sw.Write ("mono.android.TypeManager.Activate (\""); - sw.Write (DeclaringType.PartialAssemblyQualifiedName); - sw.Write ("\", \""); - sw.Write (ManagedParameters); - sw.Write ("\", this, new java.lang.Object[] { "); - sw.Write (ActivateCall); - sw.WriteLine (" });"); - - sw.WriteLine ("\t\t}"); - } - - sw.WriteLine ("\t}"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperField.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperField.cs deleted file mode 100644 index 043dedc9ee1..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperField.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperField -{ - public string FieldName { get; set; } - public string TypeName { get; set; } - public string Visibility { get; set; } - public bool IsStatic { get; set; } - public string InitializerName { get; set; } - public List Annotations { get; } = new List (); - - public CallableWrapperField (string fieldName, string typeName, string visibility, string initializerName) - { - FieldName = fieldName; - TypeName = typeName; - Visibility = visibility; - InitializerName = initializerName; - } - - public void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - foreach (var annotation in Annotations) - annotation.Generate (sw, "", options); - - sw.Write ("\t"); - sw.Write (Visibility); - sw.Write (' '); - - if (IsStatic) - sw.Write ("static "); - - sw.Write (TypeName); - sw.Write (' '); - - sw.Write (FieldName); - sw.Write (" = "); - - sw.Write (InitializerName); - sw.WriteLine (" ();"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperMethod.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperMethod.cs deleted file mode 100644 index 9b9e692d5f1..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperMethod.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperMethod -{ - public string Name { get; set; } - public string Method { get; set; } - public string JniSignature { get; set; } - public string? ManagedParameters { get; set; } - public string? JavaNameOverride { get; set; } - public string? Params { get; set; } - public string? Retval { get; set; } - public string? JavaAccess { get; set; } - public bool IsExport { get; set; } - public bool IsStatic { get; set; } - public bool IsDynamicallyRegistered { get; set; } = true; - public string []? ThrownTypeNames { get; set; } - public string? SuperCall { get; set; } - public string? ActivateCall { get; set; } - public string JavaName => JavaNameOverride ?? Name; - public List Annotations { get; } = new List (); - public CallableWrapperType DeclaringType { get; } - - public string? ThrowsDeclaration => ThrownTypeNames?.Length > 0 ? $" throws {string.Join (", ", ThrownTypeNames)}" : null; - - public CallableWrapperMethod (CallableWrapperType declaringType, string name, string method, string jniSignature) - { - DeclaringType = declaringType; - Name = name; - Method = method; - JniSignature = jniSignature; - } - - public virtual void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - foreach (var annotation in Annotations) - annotation.Generate (sw, "", options); - - sw.Write ("\t"); - - sw.Write (IsExport ? JavaAccess : "public"); - sw.Write (' '); - - if (IsStatic) - sw.Write ("static "); - - sw.Write (Retval); - sw.Write (' '); - - sw.Write (JavaName); - - sw.Write (" ("); - sw.Write (Params); - sw.Write (')'); - - sw.WriteLine (ThrowsDeclaration); - sw.WriteLine ("\t{"); - -#if MONODROID_TIMING - sw.WriteLine ("\t\tandroid.util.Log.i(\"MonoDroid-Timing\", \"{0}.{1}: time: \"+java.lang.System.currentTimeMillis());", Name, Method); -#endif - - sw.Write ("\t\t"); - sw.Write (Retval == "void" ? string.Empty : "return "); - - sw.Write ("n_"); - sw.Write (Name); - - sw.Write (" ("); - sw.Write (ActivateCall); - sw.WriteLine (");"); - - sw.WriteLine ("\t}"); - sw.WriteLine (); - - sw.Write ("\tprivate "); - - if (IsStatic) - sw.Write ("static "); - - sw.Write ("native "); - - sw.Write (Retval); - - sw.Write (" n_"); - sw.Write (Name); - - sw.Write (" ("); - sw.Write (Params); - sw.WriteLine (");"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperType.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperType.cs deleted file mode 100644 index 1de1caaad54..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperType.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperType -{ - public string Name { get; set; } - public string Package { get; set; } - public bool IsAbstract { get; set; } - public string? ApplicationJavaClass { get; set; } - public bool GenerateOnCreateOverrides { get; set; } - /// - /// The Java source code to be included in Instrumentation.onCreate - /// - /// Originally came from MonoRuntimeProvider.java delimited by: - /// // Mono Runtime Initialization {{{ - /// // }}} - /// - public string? MonoRuntimeInitialization { get; set; } - public string? ExtendsType { get; set; } - public CallableWrapperApplicationConstructor? ApplicationConstructor { get; set; } - public bool IsApplication { get; set; } - public bool IsInstrumentation { get; set; } - public string PartialAssemblyQualifiedName { get; set; } - public bool HasExport { get; set; } - - public List Annotations { get; } = new List (); - public List ImplementedInterfaces { get; } = new List (); - public List Constructors { get; } = new List (); - public List Fields { get; } = new List (); - public List Methods { get; } = new List (); - public List NestedTypes { get; } = new List (); - - public bool CannotRegisterInStaticConstructor => IsApplication || IsInstrumentation; - - public CallableWrapperType (string name, string package, string partialAssemblyQualifiedName) - { - Name = name; - Package = package; - PartialAssemblyQualifiedName = partialAssemblyQualifiedName; - } - - // example of java target to generate for a type - // - // package mono.droid; - // - // import android.app.Activity; - // import android.os.Bundle; - // - // public class MonoActivity extends android.app.Activity - // { - // static final String __md_methods; - // static { - // __md_methods = - // "n_OnCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n" + - // ""; - // mono.android.Runtime.register ("Mono.Droid.MonoActivity, AssemblyName", MonoActivity.class, __md_methods); - // } - // - // public void onCreate(android.os.Bundle savedInstanceState) - // { - // n_onCreate (savedInstanceState); - // } - // - // private native void n_onCreate (android.os.Bundle bundle); - // } - public void Generate (TextWriter writer, CallableWrapperWriterOptions options, bool isNested = false) - { - if (!isNested && !string.IsNullOrEmpty (Package)) { - writer.WriteLine ("package " + Package + ";"); - writer.WriteLine (); - } - - GenerateHeader (writer, options); - - if (!isNested) - GenerateInfrastructure (writer, options); - - GenerateBody (writer, options); - - foreach (var nested in NestedTypes) - nested.Generate (writer, options, true); - - GenerateFooter (writer, options); - } - - void GenerateHeader (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - // Type annotations - foreach (var annotation in Annotations) - annotation.Generate (sw, "", options); - - sw.WriteLine ("public " + (IsAbstract ? "abstract " : "") + "class " + Name); - - var extends = ExtendsType; - - // Do this check here rather than the constructor because it can be set after the constructor is called - if (extends == "android.app.Application" && ApplicationJavaClass != null && !string.IsNullOrEmpty (ApplicationJavaClass)) - extends = ApplicationJavaClass; - - sw.WriteLine ("\textends " + extends); - - sw.WriteLine ("\timplements"); - sw.Write ("\t\t"); - - sw.Write ("mono.android.IGCUserPeer"); - - foreach (var iface in ImplementedInterfaces) { - sw.WriteLine (","); - sw.Write ("\t\t"); - sw.Write (iface); - } - - sw.WriteLine (); - sw.WriteLine ("{"); - } - - void GenerateInfrastructure (TextWriter writer, CallableWrapperWriterOptions options) - { - var needCtor = false; - - if (HasDynamicallyRegisteredMethods) { - needCtor = true; - writer.WriteLine ("/** @hide */"); - writer.WriteLine ("\tpublic static final String __md_methods;"); - } - - for (var i = 0; i < NestedTypes.Count; i++) { - if (!NestedTypes [i].HasDynamicallyRegisteredMethods) - continue; - - needCtor = true; - writer.Write ("\tstatic final String __md_"); - writer.Write (i + 1); - writer.WriteLine ("_methods;"); - } - - if (needCtor) { - writer.WriteLine ("\tstatic {"); - - if (HasDynamicallyRegisteredMethods) - GenerateRegisterType (writer, this, "__md_methods", options); - - for (var i = 0; i < NestedTypes.Count; ++i) - GenerateRegisterType (writer, NestedTypes [i], $"__md_{i + 1}_methods", options); - - writer.WriteLine ("\t}"); - } - } - - void GenerateBody (TextWriter sw, CallableWrapperWriterOptions options) - { - foreach (var ctor in Constructors) - ctor.Generate (sw, options); - - ApplicationConstructor?.Generate (sw, options); - - foreach (var field in Fields) - field.Generate (sw, options); - - foreach (var method in Methods) - method.Generate (sw, options); - - if (GenerateOnCreateOverrides && IsApplication && !Methods.Any (m => m.Name == "onCreate")) - WriteApplicationOnCreate (sw, options); - - if (GenerateOnCreateOverrides && IsInstrumentation && !Methods.Any (m => m.Name == "onCreate")) - WriteInstrumentationOnCreate (sw, options); - - sw.WriteLine (); - sw.WriteLine ("\tprivate java.util.ArrayList refList;"); - - sw.WriteLine ("\tpublic void monodroidAddReference (java.lang.Object obj)"); - sw.WriteLine ("\t{"); - sw.WriteLine ("\t\tif (refList == null)"); - sw.WriteLine ("\t\t\trefList = new java.util.ArrayList ();"); - sw.WriteLine ("\t\trefList.add (obj);"); - sw.WriteLine ("\t}"); - sw.WriteLine (); - - sw.WriteLine ("\tpublic void monodroidClearReferences ()"); - sw.WriteLine ("\t{"); - sw.WriteLine ("\t\tif (refList != null)"); - sw.WriteLine ("\t\t\trefList.clear ();"); - sw.WriteLine ("\t}"); - } - - void GenerateFooter (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine ("}"); - } - - void WriteApplicationOnCreate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - sw.WriteLine ("\tpublic void onCreate ()"); - sw.WriteLine ("\t{"); - - sw.Write ("\t\tmono.android.Runtime.register (\""); - sw.Write (PartialAssemblyQualifiedName); - sw.Write ("\", "); - sw.Write (Name); - sw.WriteLine (".class, __md_methods);"); - - sw.WriteLine ("\t\tsuper.onCreate ();"); - sw.WriteLine ("\t}"); - } - - void WriteInstrumentationOnCreate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - sw.WriteLine ("\tpublic void onCreate (android.os.Bundle arguments)"); - sw.WriteLine ("\t{"); - -#if MONODROID_TIMING - sw.WriteLine ("\t\tandroid.util.Log.i(\"MonoDroid-Timing\", \"{0}.onCreate(Bundle): time: \"+java.lang.System.currentTimeMillis());", Name); - sw.WriteLine (); -#endif - - sw.WriteLine ("\t\tandroid.content.Context context = getContext ();"); - sw.WriteLine (); - - if (!string.IsNullOrEmpty (MonoRuntimeInitialization)) { - sw.WriteLine (MonoRuntimeInitialization); - sw.WriteLine (); - } - - sw.Write ("\t\tmono.android.Runtime.register (\""); - sw.Write (PartialAssemblyQualifiedName); - sw.Write ("\", "); - sw.Write (Name); - sw.WriteLine (".class, __md_methods);"); - - sw.WriteLine ("\t\tsuper.onCreate (arguments);"); - sw.WriteLine ("\t}"); - } - - void GenerateRegisterType (TextWriter sw, CallableWrapperType self, string field, CallableWrapperWriterOptions options) - { - if (!self.HasDynamicallyRegisteredMethods) - return; - - sw.Write ("\t\t"); - sw.Write (field); - sw.WriteLine (" = "); - - foreach (var method in self.Methods) { - if (method.IsDynamicallyRegistered) { - sw.Write ("\t\t\t\"", method.Method); - sw.Write (method.Method); - sw.WriteLine ("\\n\" +"); - } - } - - sw.WriteLine ("\t\t\t\"\";"); - - if (CannotRegisterInStaticConstructor) - return; - - sw.Write ("\t\t"); - - sw.Write ("mono.android.Runtime.register (\""); - sw.Write (self.PartialAssemblyQualifiedName); - sw.Write ("\", "); - sw.Write (self.Name); - sw.Write (".class, "); - sw.Write (field); - sw.WriteLine (");"); - } - - // If there are no methods, we need to generate "empty" registration because of backward compatibility - public bool HasDynamicallyRegisteredMethods => Methods.Count == 0 || Methods.Any (sig => sig.IsDynamicallyRegistered); - - /// - /// Returns a destination file path based on the package name of this Java type - /// - public string GetDestinationPath (string outputPath) - { - var dir = Package.Replace ('.', Path.DirectorySeparatorChar); - return Path.Combine (outputPath, dir, Name + ".java"); - } - - public void Generate (string outputPath, CallableWrapperWriterOptions options) - { - using (StreamWriter sw = OpenStream (outputPath)) - Generate (sw, options, false); - } - - StreamWriter OpenStream (string outputPath) - { - var destination = GetDestinationPath (outputPath); - Directory.CreateDirectory (Path.GetDirectoryName (destination)!); - - return new StreamWriter (new FileStream (destination, FileMode.Create, FileAccess.Write)); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperTypeAnnotation.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperTypeAnnotation.cs deleted file mode 100644 index e605eee62e7..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperTypeAnnotation.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperTypeAnnotation -{ - public string Name { get; set; } - public List> Properties { get; } = new (); - - public CallableWrapperTypeAnnotation (string name) - { - Name = name; - } - - public void Generate (TextWriter sw, string indent, CallableWrapperWriterOptions options) - { - sw.Write (indent); - sw.Write ('@'); - sw.Write (Name); - - var properties = string.Join (", ", Properties.Select (p => $"{p.Key} = {p.Value}")); - - if (!string.IsNullOrEmpty (properties)) { - sw.Write (" ("); - sw.Write (properties); - sw.Write (")"); - } - - sw.WriteLine (); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperReaderOptions.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperReaderOptions.cs deleted file mode 100644 index acd5a9633ab..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperReaderOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Java.Interop.Tools.JavaCallableWrappers; - -public class CallableWrapperReaderOptions -{ - public string? DefaultApplicationJavaClass { get; set; } - public bool DefaultGenerateOnCreateOverrides { get; set; } - public string? DefaultMonoRuntimeInitialization { get; set; } - public JavaCallableMethodClassifier? MethodClassifier { get; set; } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperWriterOptions.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperWriterOptions.cs deleted file mode 100644 index 9cbfe5ddc53..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperWriterOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Java.Interop.Tools.JavaCallableWrappers; - -public class CallableWrapperWriterOptions -{ - JavaPeerStyle codeGenerationTarget; - - public JavaPeerStyle CodeGenerationTarget { - get => codeGenerationTarget; - set { - if (value != JavaPeerStyle.XAJavaInterop1) - throw new NotSupportedException ($"The Java callable wrapper code generation target '{value}' is not supported. Use XAJavaInterop1 instead."); - codeGenerationTarget = value; - } - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableMethodClassifier.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableMethodClassifier.cs deleted file mode 100644 index 75e8061d6d4..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableMethodClassifier.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Mono.Cecil; - -namespace Java.Interop.Tools.JavaCallableWrappers -{ - public abstract class JavaCallableMethodClassifier - { - public abstract bool ShouldBeDynamicallyRegistered (TypeDefinition topType, MethodDefinition registeredMethod, MethodDefinition implementedMethod, CustomAttribute? registerAttribute); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaPeerStyle.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaPeerStyle.cs deleted file mode 100644 index 22ea687104e..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaPeerStyle.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Java.Interop.Tools.JavaCallableWrappers -{ - public enum JavaPeerStyle { - XAJavaInterop1, - } -} diff --git a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGeneratorTests.cs b/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGeneratorTests.cs deleted file mode 100644 index 2890314f99f..00000000000 --- a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGeneratorTests.cs +++ /dev/null @@ -1,742 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -using Mono.Cecil; - -using NUnit.Framework; - -using Java.Interop.Tools.Diagnostics; -using Java.Interop.Tools.JavaCallableWrappers; -using Java.Interop.Tools.JavaCallableWrappersTests; -using Java.Interop.Tools.TypeNameMappings; - -using Xamarin.Android.ToolsTests; -using Java.Interop.Tools.JavaCallableWrappers.Adapters; -using Java.Interop.Tools.Cecil; - -namespace Java.Interop.Tools.JavaCallableWrappersTests -{ - [TestFixture] - public class JavaCallableWrapperGeneratorTests - { - [Test] - public void ConstructorExceptions () - { - Action logger = (f, o) => { }; - - // structs aren't supported - var td = SupportDeclarations.GetTypeDefinition (typeof (int)); - var e = Assert.Throws (() => CecilImporter.CreateType (td, new TypeDefinitionCache ())); - Assert.AreEqual (4200, e.Code); - } - - [Test] - public void KotlinInvalidImplRegisterName () - { - Action logger = (f, o) => { }; - - // Contains invalid [Register] name of "foo-impl" - var td = SupportDeclarations.GetTypeDefinition (typeof (KotlinInvalidImplRegisterName)); - var e = Assert.Throws (() => CecilImporter.CreateType (td, new TypeDefinitionCache ())); - Assert.AreEqual (4217, e.Code); - } - - [Test] - public void KotlinInvalidHashRegisterName () - { - Action logger = (f, o) => { }; - - // Contains invalid [Register] name of "foo-f8k2a13" - var td = SupportDeclarations.GetTypeDefinition (typeof (KotlinInvalidHashRegisterName)); - var e = Assert.Throws (() => CecilImporter.CreateType (td, new TypeDefinitionCache ())); - Assert.AreEqual (4217, e.Code); - } - - [Test] - public void GenerateApplication ( - [Values (null, "android.app.Application", "android.support.multidex.MultiDexApplication")] string applicationJavaClass - ) - { - var actual = Generate (typeof (ApplicationName), applicationJavaClass); - var expected = $@"package application; - - -public class Name - extends {applicationJavaClass ?? "android.app.Application"} - implements - mono.android.IGCUserPeer -{{ -/** @hide */ - public static final String __md_methods; - static {{ - __md_methods = - """"; - }} - - public Name () - {{ - mono.MonoPackageManager.setContext (this); - }} - - public void onCreate () - {{ - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ApplicationName, Java.Interop.Tools.JavaCallableWrappers-Tests"", Name.class, __md_methods); - super.onCreate (); - }} - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - {{ - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - }} - - public void monodroidClearReferences () - {{ - if (refList != null) - refList.clear (); - }} -}} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateTypeMentioningNestedInvoker () - { - var actual = Generate (typeof (ApplicationName.ActivityLifecycleCallbacks)); - var expected = """ -package application; - - -public class Name_ActivityLifecycleCallbacks - extends java.lang.Object - implements - mono.android.IGCUserPeer, - java.lang.Object -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - "n_onActivityCreated:(Landroid/app/Activity;Landroid/os/Bundle;)V:GetOnActivityCreated_Landroid_app_Activity_Landroid_os_Bundle_Handler:Android.App.Application+IActivityLifecycleCallbacksInvoker, Mono.Android\n" + - ""; - mono.android.Runtime.register ("Xamarin.Android.ToolsTests.ApplicationName+ActivityLifecycleCallbacks, Java.Interop.Tools.JavaCallableWrappers-Tests", Name_ActivityLifecycleCallbacks.class, __md_methods); - } - - public void onActivityCreated (android.app.Activity p0, android.os.Bundle p1) - { - n_onActivityCreated (p0, p1); - } - - private native void n_onActivityCreated (android.app.Activity p0, android.os.Bundle p1); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} - -"""; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateOnlyMostDerivedInterfaces () - { - var actual = Generate (typeof (OnTabSelectedListener)); - - Assert.That (actual, Does.Contain ("\t\tcom.xamarin.android.OnTabSelectedListener")); - Assert.That (actual, Does.Not.Contain ("\t\tcom.xamarin.android.BaseOnTabSelectedListener")); - } - - static string Generate (Type type, string applicationJavaClass = null, string monoRuntimeInit = null, JavaPeerStyle style = JavaPeerStyle.XAJavaInterop1) - { - var reader_options = new CallableWrapperReaderOptions { - DefaultApplicationJavaClass = applicationJavaClass, - DefaultGenerateOnCreateOverrides = true, - DefaultMonoRuntimeInitialization = monoRuntimeInit, - }; - - var td = SupportDeclarations.GetTypeDefinition (type); - var g = CecilImporter.CreateType (td, new TypeDefinitionCache (), reader_options); - - var o = new StringWriter (); - var dir = Path.GetDirectoryName (typeof (JavaCallableWrapperGeneratorTests).Assembly.Location); - var options = new CallableWrapperWriterOptions { - CodeGenerationTarget = style, - }; - - g.Generate (Path.Combine (dir, "__o"), options); - g.Generate (o, options); - - return o.ToString (); - } - - - [Test] - public void GenerateIndirectApplication ( - [Values (null, "android.app.Application", "android.support.multidex.MultiDexApplication")] string applicationJavaClass - ) - { - var actual = Generate (typeof (IndirectApplication), applicationJavaClass); - var expected = @"package crc64197ae30a36756915; - - -public class IndirectApplication - extends application.Name - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - ""n_onCreate:()V:Application.OnCreate\n"" + - """"; - } - - public IndirectApplication () - { - mono.MonoPackageManager.setContext (this); - } - - public void onCreate () - { - n_onCreate (); - } - - private native void n_onCreate (); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateExportedMembers () - { - var actual = Generate (typeof (ExportsMembers)); - var expected = @"package crc64197ae30a36756915; - - -public class ExportsMembers - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - ""n_GetInstance:()Lcrc64197ae30a36756915/ExportsMembers;:__export__\n"" + - ""n_GetValue:()Ljava/lang/String;:__export__\n"" + - ""n_staticMethodNotMangled:()V:__export__\n"" + - ""n_methodNamesNotMangled:()V:__export__\n"" + - ""n_CompletelyDifferentName:(Ljava/lang/String;I)Ljava/lang/String;:__export__\n"" + - ""n_methodThatThrows:()V:__export__\n"" + - ""n_methodThatThrowsEmptyArray:()V:__export__\n"" + - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExportsMembers, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExportsMembers.class, __md_methods); - } - - public static crc64197ae30a36756915.ExportsMembers STATIC_INSTANCE = GetInstance (); - - public java.lang.String VALUE = GetValue (); - - public static crc64197ae30a36756915.ExportsMembers GetInstance () - { - return n_GetInstance (); - } - - private static native crc64197ae30a36756915.ExportsMembers n_GetInstance (); - - public java.lang.String GetValue () - { - return n_GetValue (); - } - - private native java.lang.String n_GetValue (); - - public static void staticMethodNotMangled () - { - n_staticMethodNotMangled (); - } - - private static native void n_staticMethodNotMangled (); - - public void methodNamesNotMangled () - { - n_methodNamesNotMangled (); - } - - private native void n_methodNamesNotMangled (); - - public java.lang.String attributeOverridesNames (java.lang.String p0, int p1) - { - return n_CompletelyDifferentName (p0, p1); - } - - private native java.lang.String n_CompletelyDifferentName (java.lang.String p0, int p1); - - public void methodThatThrows () throws java.lang.Throwable - { - n_methodThatThrows (); - } - - private native void n_methodThatThrows (); - - public void methodThatThrowsEmptyArray () - { - n_methodThatThrowsEmptyArray (); - } - - private native void n_methodThatThrowsEmptyArray (); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateInnerClass () - { - var actual = Generate (typeof (ExampleOuterClass)); - var expected = @"package crc64197ae30a36756915; - - -public class ExampleOuterClass - extends register.NonStaticOuterClass - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static final String __md_1_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleOuterClass, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleOuterClass.class, __md_methods); - __md_1_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleOuterClass+ExampleInnerClass, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleOuterClass_ExampleInnerClass.class, __md_1_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } - -public class ExampleOuterClass_ExampleInnerClass - extends register.NonStaticOuterClass.NonStaticInnerClass - implements - mono.android.IGCUserPeer -{ - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateNestedClass_DefaultName () - { - var actual = Generate (typeof (RegisterName.DefaultNestedName)); - var expected = @"package register; - - -public class Name_DefaultNestedName - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.RegisterName+DefaultNestedName, Java.Interop.Tools.JavaCallableWrappers-Tests"", Name_DefaultNestedName.class, __md_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateNestedClass_OverrideName () - { - var actual = Generate (typeof (RegisterName.OverrideNestedName)); - var expected = @"package register; - - -public class Name$Override - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.RegisterName+OverrideNestedName, Java.Interop.Tools.JavaCallableWrappers-Tests"", Name$Override.class, __md_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateConstructors () - { - var actual = Generate (typeof (ExportsConstructors)); - var expected = @"package register; - - -public class ExportsConstructors - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExportsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExportsConstructors.class, __md_methods); - } - - public ExportsConstructors () - { - super (); - if (getClass () == ExportsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", """", this, new java.lang.Object[] { }); - } - } - - public ExportsConstructors (int p0) - { - super (p0); - if (getClass () == ExportsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.Int32, System.Private.CoreLib"", this, new java.lang.Object[] { p0 }); - } - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateConstructors_WithThrows () - { - var actual = Generate (typeof (ExportsThrowsConstructors)); - var expected = @"package register; - - -public class ExportsThrowsConstructors - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExportsThrowsConstructors.class, __md_methods); - } - - public ExportsThrowsConstructors () throws java.lang.Throwable - { - super (); - if (getClass () == ExportsThrowsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", """", this, new java.lang.Object[] { }); - } - } - - public ExportsThrowsConstructors (int p0) throws java.lang.Throwable - { - super (p0); - if (getClass () == ExportsThrowsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.Int32, System.Private.CoreLib"", this, new java.lang.Object[] { p0 }); - } - } - - public ExportsThrowsConstructors (java.lang.String p0) - { - super (p0); - if (getClass () == ExportsThrowsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.String, System.Private.CoreLib"", this, new java.lang.Object[] { p0 }); - } - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateActivity () - { - var actual = Generate (typeof (ExampleActivity)); - var expected = @"package my; - - -public class ExampleActivity - extends android.app.Activity - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleActivity, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleActivity.class, __md_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateInstrumentation () - { - var init = "mono.MonoPackageManager.LoadApplication (context, context.getApplicationInfo (), new String[]{context.getApplicationInfo ().sourceDir});"; - var actual = Generate (typeof (ExampleInstrumentation), monoRuntimeInit: init); - var expected = $@"package my; - - -public class ExampleInstrumentation - extends android.app.Instrumentation - implements - mono.android.IGCUserPeer -{{ -/** @hide */ - public static final String __md_methods; - static {{ - __md_methods = - """"; - }} - - public void onCreate (android.os.Bundle arguments) - {{ - android.content.Context context = getContext (); - -{init} - - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleInstrumentation, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleInstrumentation.class, __md_methods); - super.onCreate (arguments); - }} - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - {{ - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - }} - - public void monodroidClearReferences () - {{ - if (refList != null) - refList.clear (); - }} -}} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateJavaInteropExample () - { - var actual = Generate (typeof (JavaInteropExample)); - var expected = @"package register; - - -public class JavaInteropExample - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - ""n_Example:()V:__export__\n"" + - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.JavaInteropExample, Java.Interop.Tools.JavaCallableWrappers-Tests"", JavaInteropExample.class, __md_methods); - } - - public JavaInteropExample (int p0, int p1) - { - super (); - if (getClass () == JavaInteropExample.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.JavaInteropExample, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.Int32, System.Private.CoreLib:System.Int32, System.Private.CoreLib"", this, new java.lang.Object[] { p0, p1 }); - } - } - - public void example () - { - n_Example (); - } - - private native void n_Example (); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [TestCase (-1)] - [TestCase (1)] - public void UndefinedCodeGenerationTargetIsRejected (int target) - { - Assert.Throws (() => - new CallableWrapperWriterOptions { CodeGenerationTarget = (JavaPeerStyle) target }); - } - } -} diff --git a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/XmlImporterTests.cs b/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/XmlImporterTests.cs deleted file mode 100644 index 6486045ae7b..00000000000 --- a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/XmlImporterTests.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System.IO; -using System.Xml.Linq; -using Java.Interop.Tools.JavaCallableWrappers.Adapters; -using Java.Interop.Tools.TypeNameMappings; -using NUnit.Framework; - -namespace Java.Interop.Tools.JavaCallableWrappersTests -{ - [TestFixture] - public class XmlImporterTests - { - PackageNamingPolicy existingValue; - - [SetUp] - public void SetUp () - { - existingValue = JavaNativeTypeManager.PackageNamingPolicy; - JavaNativeTypeManager.PackageNamingPolicy = PackageNamingPolicy.LowercaseCrc64; - } - - [TearDown] - public void TearDown () - { - JavaNativeTypeManager.PackageNamingPolicy = existingValue; - } - - [Test] - public void ImportType_EmptyPackage_GeneratesCrc64Package () - { - // Simulate the case where [Register("CustomView")] is used without a package prefix - // The XML has an empty package attribute, and we expect XmlImporter to generate a crc64 package - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // The generated package should be "crc64" + crc64hash of "MyApp.Views:MyApp.Android" - Assert.AreEqual ("crc64b8e52a012da2d805", type.Package); - Assert.AreEqual ("CustomView", type.Name); - } - - [Test] - public void ImportType_EmptyPackage_NestedType_GeneratesCrc64Package () - { - // Simulate the case with a nested type - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // The generated package should be based on "MyApp.Views:MyApp.Android" (ignoring nested type part) - Assert.AreEqual ("crc64b8e52a012da2d805", type.Package); - Assert.AreEqual ("InnerView", type.Name); - } - - [Test] - public void ImportType_MissingPackageAttribute_GeneratesCrc64Package () - { - // Simulate the case where the package attribute is completely missing - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // The generated package should be "crc64" + crc64hash of "MyApp.Views:MyApp.Android" - Assert.AreEqual ("crc64b8e52a012da2d805", type.Package); - } - - [Test] - public void ImportType_WithPackage_UsesProvidedPackage () - { - // Ensure that when a package is provided, it is used directly - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - Assert.AreEqual ("my.custom.package", type.Package); - } - - [Test] - public void ImportType_NoNamespace_ReturnsEmptyPackage () - { - // When there's no namespace in the type name, we can't generate a package - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // Without a namespace, we can't generate a crc64 package, so it should remain empty - Assert.AreEqual ("", type.Package); - } - - [Test] - public void ImportType_XamarinAndroidToolsTests_MatchesExpectedCrc64 () - { - // This test verifies the crc64 generation matches what JavaNativeTypeManager would generate - // Based on the test data in JavaCallableWrapperGeneratorTests, namespace "Xamarin.Android.ToolsTests" - // with assembly "Java.Interop.Tools.JavaCallableWrappers-Tests" should produce crc64197ae30a36756915 - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // This should match the expected crc64 from JavaCallableWrapperGeneratorTests - Assert.AreEqual ("crc64197ae30a36756915", type.Package); - } - } -} diff --git a/external/Java.Interop/tools/jcw-gen/App.cs b/external/Java.Interop/tools/jcw-gen/App.cs deleted file mode 100644 index 0eb606902fb..00000000000 --- a/external/Java.Interop/tools/jcw-gen/App.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Diagnostics; -using System.Linq; -using System.IO; -using System.Threading.Tasks; - -using Java.Interop.Tools.Cecil; -using Java.Interop.Tools.Diagnostics; -using Java.Interop.Tools.JavaCallableWrappers; -using Mono.Cecil; -using Mono.Options; -using Java.Interop.Tools.JavaCallableWrappers.Adapters; - -namespace Java.Interop.Tools -{ - class App - { - public static int Main (string [] args) - { - var resolver = new DirectoryAssemblyResolver (logger: Diagnostic.CreateConsoleLogger (), loadDebugSymbols: false); - - bool help = false; - string outputPath = null; - int verbosity = 0; - var style = JavaPeerStyle.XAJavaInterop1; - - var options = new OptionSet { - "Usage: jcw-gen.exe OPTIONS* ASSEMBLY+ [@RESPONSE-FILES]", - "", - "Generates Java Callable Wrappers from specified assemblies.", - "", - "Copyright 2016 Xamarin Inc.", - "", - "Options:", - { "L=", - "{DIRECTORY} to resolve assemblies from.", - v => resolver.SearchDirectories.Add (v) }, - { "o=", - "{DIRECTORY} to write Java source code to.", - v => outputPath = v }, - { "codegen-target=", - "STYLE of Java Callable Wrappers to generate", - (JavaPeerStyle? v) => style = v.HasValue ? v.Value : style }, - { "v:", - "Logging verbosity.", - (int? v) => verbosity = v.HasValue ? v.Value : verbosity + 1 }, - { "h|help|?", - "Show this message and exit", - v => help = v != null }, - new ResponseFileSource (), - }; - var cache = new TypeDefinitionCache (); - var scanner = new JavaTypeScanner (Diagnostic.CreateConsoleLogger (), cache); - try { - var assemblies = options.Parse (args); - if (assemblies.Count == 0 || outputPath == null || help) { - int r = 0; - if (assemblies.Count == 0) { - Console.Error.WriteLine ("jcw-gen: No assemblies specified."); - r = 1; - } - else if (outputPath == null) { - Console.Error.WriteLine ("jcw-gen: No output directory specified. Use `jcw-gen -o PATH`."); - r = 1; - } - options.WriteOptionDescriptions (Console.Out); - return r; - } - foreach (var assembly in assemblies) { - resolver.SearchDirectories.Add (Path.GetDirectoryName (assembly)); - resolver.Load (assembly); - } - var types = scanner.GetJavaTypes (assemblies, resolver) - .Where (td => !JavaTypeScanner.ShouldSkipJavaCallableWrapperGeneration (td, cache)); - foreach (var type in types) { - GenerateJavaCallableWrapper (type, outputPath, cache, style); - } - return 0; - } - catch (Exception e) { - Console.Error.Write ("jcw-gen: {0}", verbosity > 0 ? e.ToString () : e.Message); - return 1; - } - finally { - resolver.Dispose (); - } - } - - static void GenerateJavaCallableWrapper (TypeDefinition type, string outputPath, TypeDefinitionCache cache, JavaPeerStyle style) - { - if (type.IsInterface) { - return; - } - - var t = CecilImporter.CreateType (type, cache); - - var options = new CallableWrapperWriterOptions { - CodeGenerationTarget = style, - }; - - t.Generate (outputPath, options); - } - } -} diff --git a/external/Java.Interop/tools/jcw-gen/jcw-gen.csproj b/external/Java.Interop/tools/jcw-gen/jcw-gen.csproj deleted file mode 100644 index f99367616b8..00000000000 --- a/external/Java.Interop/tools/jcw-gen/jcw-gen.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - $(DotNetTargetFramework) - Exe - - - - - - $(UtilityOutputFullPath) - - - - - - - - - - - - - - - - - - - - diff --git a/external/Java.Interop/tools/jcw-gen/jcw-gen.slnf b/external/Java.Interop/tools/jcw-gen/jcw-gen.slnf deleted file mode 100644 index 26d4de23d53..00000000000 --- a/external/Java.Interop/tools/jcw-gen/jcw-gen.slnf +++ /dev/null @@ -1,13 +0,0 @@ -{ - "solution": { - "path": "..\\..\\Java.Interop.slnx", - "projects": [ - "src\\Java.Interop.Localization\\Java.Interop.Localization.csproj", - "src\\Java.Interop.Tools.Cecil\\Java.Interop.Tools.Cecil.csproj", - "src\\Java.Interop.Tools.Diagnostics\\Java.Interop.Tools.Diagnostics.csproj", - "src\\Java.Interop.Tools.JavaCallableWrappers\\Java.Interop.Tools.JavaCallableWrappers.csproj", - "tests\\Java.Interop.Tools.JavaCallableWrappers-Tests\\Java.Interop.Tools.JavaCallableWrappers-Tests.csproj", - "tools\\jcw-gen\\jcw-gen.csproj" - ] - } -} \ No newline at end of file diff --git a/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs index 283dc2cf301..16f3043ebf0 100644 --- a/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs +++ b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Android.Sdk.TrimmableTypeMap; using Microsoft.Android.Tasks; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -12,6 +13,87 @@ namespace Xamarin.Android.Build.Tests { [Parallelizable (ParallelScope.Children)] public class GenerateTrimmableTypeMapTests : BaseTest { + [TestCase (false, false, false)] + [TestCase (false, false, true)] + [TestCase (false, true, false)] + [TestCase (false, true, true)] + [TestCase (true, false, false)] + [TestCase (true, false, true)] + [TestCase (true, true, false)] + [TestCase (true, true, true)] + public void ConstructorCallbacksMatchJavaCallSites (bool isAbstract, bool deferred, bool hasCallback) + { + var constructor = new MarshalMethodInfo { + JniName = ".ctor", + JniSignature = "()V", + NativeCallbackName = "n_ctor", + ManagedMethodName = ".ctor", + IsConstructor = true, + }; + var callback = new MarshalMethodInfo { + JniName = "onCallback", + JniSignature = "()V", + NativeCallbackName = "n_onCallback", + ManagedMethodName = "OnCallback", + Connector = "GetOnCallbackHandler", + }; + var peer = new JavaPeerInfo { + JavaName = "example/Peer", + CompatJniName = "example/Peer", + ManagedTypeName = "Example.Peer", + ManagedTypeNamespace = "Example", + ManagedTypeShortName = "Peer", + AssemblyName = "Example", + BaseJavaName = "java/lang/Object", + IsAbstract = isAbstract, + CannotRegisterInStaticConstructor = deferred, + ActivationCtor = new ActivationCtorInfo { + DeclaringTypeName = "Example.Peer", + DeclaringAssemblyName = "Example", + DeclaringType = new TypeRefData { ManagedTypeName = "Example.Peer", AssemblyName = "Example" }, + Style = ActivationCtorStyle.XamarinAndroid, + }, + JavaConstructors = [new JavaConstructorInfo { JniSignature = "()V", ConstructorIndex = 0 }], + MarshalMethods = hasCallback ? [constructor, callback] : [constructor], + }; + using var writer = new StringWriter (); + new JcwJavaSourceGenerator ().Generate (peer, writer); + var java = writer.ToString (); + StringAssert.Contains ("public Peer ()", java); + StringAssert.Contains ("super ();", java); + StringAssert.Contains ("mono.android.IGCUserPeer", java); + StringAssert.Contains ("private java.util.ArrayList refList;", java); + StringAssert.DoesNotContain ("__md_methods", java); + + bool hasNativeConstructor = !isAbstract && !deferred; + Assert.AreEqual (hasNativeConstructor, java.Contains ("if (getClass () == Peer.class) nctor_0 ();", StringComparison.Ordinal)); + Assert.AreEqual (hasNativeConstructor, java.Contains ("private native void nctor_0 ();", StringComparison.Ordinal)); + Assert.AreEqual (deferred && hasCallback, java.Contains ("private static boolean __md_natives_registered;", StringComparison.Ordinal)); + Assert.AreEqual (deferred && hasCallback, java.Contains ("private static synchronized void __md_registerNatives ()", StringComparison.Ordinal)); + Assert.AreEqual (deferred && hasCallback, java.Contains ("__md_registerNatives ();", StringComparison.Ordinal)); + Assert.AreEqual (hasCallback, java.Contains ("public native void n_onCallback ();", StringComparison.Ordinal)); + + var generator = new TypeMapAssemblyGenerator (new Version (11, 0)); + var model = generator.CreateModel ([peer], "_Example.TypeMap"); + var proxy = model.ProxyTypes.Single (); + Assert.AreEqual (hasNativeConstructor ? 1 : 0, proxy.UcoConstructors.Count); + string [] expectedRegistrations = hasNativeConstructor + ? (hasCallback ? ["nctor_0", "n_onCallback"] : ["nctor_0"]) + : (hasCallback ? ["n_onCallback"] : []); + CollectionAssert.AreEquivalent (expectedRegistrations, + proxy.NativeRegistrations.Select (registration => registration.JniMethodName)); + Assert.IsNotNull (proxy.ActivationCtor, "Managed peer creation must retain its activation constructor."); + + using var stream = new MemoryStream (); + generator.Generate (model, stream, useSharedTypemapUniverse: false); + stream.Position = 0; + using var assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly (stream); + var emittedProxy = assembly.MainModule.Types.Single (type => type.Name == proxy.TypeName); + Assert.AreEqual (hasNativeConstructor, emittedProxy.Methods.Any (method => method.Name == "nctor_0_uco")); + Assert.IsTrue (emittedProxy.Methods.Any (method => method.Name == "CreateInstance")); + TestContext.Out.WriteLine ($"abstract={isAbstract}, deferred={deferred}, callback={hasCallback}: Java nctor={hasNativeConstructor}, native registrations=[{string.Join (", ", proxy.NativeRegistrations.Select (registration => registration.JniMethodName))}]"); + } + [Test] public void Execute_EmptyAssemblyList_Succeeds () { diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs index 7f592364f3b..a1f1e7c4e73 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; namespace Microsoft.Android.Sdk.TrimmableTypeMap; @@ -143,6 +144,9 @@ static void WriteStaticInitializer (JavaPeerInfo type, TextWriter writer) // emit a lazy one-time __md_registerNatives() helper and call it at the top of // each generated native-method wrapper. if (type.CannotRegisterInStaticConstructor) { + if (!type.MarshalMethods.Any (method => !method.IsConstructor)) { + return; + } writer.Write ($$""" private static boolean __md_natives_registered; private static synchronized void __md_registerNatives () @@ -186,7 +190,7 @@ static void WriteConstructors (JavaPeerInfo type, TextWriter writer) """); - if (!type.CannotRegisterInStaticConstructor) { + if (!type.IsAbstract && !type.CannotRegisterInStaticConstructor) { writer.Write ($$""" if (getClass () == {{simpleClassName}}.class) nctor_{{ctor.ConstructorIndex}} ({{args}}); @@ -201,14 +205,16 @@ static void WriteConstructors (JavaPeerInfo type, TextWriter writer) } // Write native constructor declarations - foreach (var ctor in type.JavaConstructors) { - var nativeCtorParams = JniSignatureHelper.ParseParameters (ctor.JniSignature); - string parameters = FormatParameterList (nativeCtorParams); - writer.WriteLine ($"\tprivate native void nctor_{ctor.ConstructorIndex} ({parameters});"); - } + if (!type.IsAbstract && !type.CannotRegisterInStaticConstructor) { + foreach (var ctor in type.JavaConstructors) { + var nativeCtorParams = JniSignatureHelper.ParseParameters (ctor.JniSignature); + string parameters = FormatParameterList (nativeCtorParams); + writer.WriteLine ($"\tprivate native void nctor_{ctor.ConstructorIndex} ({parameters});"); + } - if (type.JavaConstructors.Count > 0) { - writer.WriteLine (); + if (type.JavaConstructors.Count > 0) { + writer.WriteLine (); + } } } diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs index 1e3809a0fb5..b1be581c13f 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs @@ -40,7 +40,7 @@ class ManifestGenerator /// /// Generates the application manifest from an optional pre-loaded template. - /// Returns the list of additional content provider names (for ApplicationRegistration.java). + /// Returns the list of additional runtime provider class names to generate. /// public (XDocument Document, IList ProviderNames) Generate ( XDocument? manifestTemplate, diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs index 3c048736ab2..a69560ea61e 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs @@ -374,10 +374,8 @@ static void BuildUcoConstructors (JavaPeerInfo peer, JavaPeerProxyData proxy) return; } - // Abstract types are never directly instantiated from Java — the ACW - // constructor's getClass() guard prevents activation. Skip generating - // UCO constructor wrappers for them. - if (peer.IsAbstract) { + // Abstract and deferred JCWs do not call native constructor callbacks. + if (peer.IsAbstract || peer.CannotRegisterInStaticConstructor) { return; } diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs index 428b3e989e4..28818971620 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs @@ -839,8 +839,7 @@ static void SkipArrayShape (ref BlobReader reader) // Pass 4: detect interface method implementations. // When a type implements a Java interface (e.g., IOnClickListener), the - // implementing method may not have [Register]. The legacy pipeline adds - // these via the interface loop in CecilImporter.cs lines 100-120. + // implementing method may not have [Register]. if (registeredMethodKeys is not null) { CollectInterfaceMethodImplementations (typeDef, index, methods, registeredMethodKeys); } @@ -1083,7 +1082,7 @@ void CollectBasePropertyOverrides (TypeDefinition typeDef, AssemblyIndex index, /// /// Detects methods from implemented Java interfaces that aren't directly [Register]'d - /// on the implementing type. Mirrors the legacy CecilImporter interface loop (lines 100-120): + /// on the implementing type: /// for each implemented interface with [Register], adds its registered methods to the type. /// void CollectInterfaceMethodImplementations (TypeDefinition typeDef, AssemblyIndex index, @@ -1174,7 +1173,6 @@ void CollectInterfaceMethodImplementations (TypeDefinition typeDef, AssemblyInde /// /// Detects Java constructors by chaining from base registered ctors. - /// Mirrors the legacy CecilImporter behavior: /// 1. Walk the base type hierarchy collecting registered ctors (stopping at DoNotGenerateAcw) /// 2. Add all base registered ctors as seed constructors (legacy adds them to the wrapper directly) /// 3. For each ctor on this type without [Register], accept it if a base registered ctor @@ -1200,8 +1198,6 @@ void CollectBaseConstructorChain (TypeDefinition typeDef, AssemblyIndex index, } // Add all base registered ctors as seed constructors. - // Legacy CecilImporter processes base types first (ctorTypes is reversed) and adds - // their registered ctors directly to the wrapper's Constructors list. bool hasParameterlessBaseCtor = false; foreach (var baseCtor in baseRegisteredCtors) { var signature = baseCtor.RegisterInfo.Signature; @@ -1253,7 +1249,6 @@ void CollectBaseConstructorChain (TypeDefinition typeDef, AssemblyIndex index, // and compute its JNI signature from the managed parameter types. // The generated Java ctor calls super() (the parameterless base ctor), // then delegates to nctor_N(...) which handles the args on the managed side. - // This matches legacy CecilImporter behavior (CecilImporter.cs:394-397). if (hasParameterlessBaseCtor) { var sig = methodDef.DecodeSignature (index.TypeRefSignatureProvider, index); var jniSignature = BuildJniCtorSignature (sig); @@ -1477,7 +1472,7 @@ static string GetEnumUnderlyingPrimitiveDescriptor (TypeDefinition typeDef, Asse /// /// Walks the base type hierarchy collecting constructors that have [Register] attributes. - /// Stops after the first base type with DoNotGenerateAcw=true (matching legacy CecilImporter). + /// Stops after the first base type with DoNotGenerateAcw=true. /// Returns them ordered from nearest base to furthest ancestor. /// List CollectBaseRegisteredCtors (TypeDefinition typeDef, AssemblyIndex index) @@ -1501,7 +1496,7 @@ List CollectBaseRegisteredCtors (TypeDefinition typeDef, AssemblyI } // Stop after the first MCW base type — its registered ctors are collected above, - // but we don't need to walk further up (matching legacy CecilImporter behavior). + // but we don't need to walk further up. if (baseIndex.RegisterInfoByType.TryGetValue (baseHandle, out var baseRegInfo) && baseRegInfo.DoNotGenerateAcw) { break; } @@ -2208,7 +2203,7 @@ string BuildJniSignatureFromManaged (MethodSignature sig, IReadOnly /// /// Parses an [ExportField] attribute as a marshal method registration. /// [ExportField] methods use the managed method name as the JNI name and have - /// a connector of "__export__" (matching legacy CecilImporter behavior). + /// a connector of "__export__". /// (RegisterInfo registerInfo, ExportInfo exportInfo) ParseExportFieldAsMethod (CustomAttribute ca, MethodDefinition methodDef, AssemblyIndex index) { diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs index 481056740b7..438e7189d6b 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs @@ -40,7 +40,7 @@ public record GeneratedJavaSource (string RelativePath, string Content); /// /// The in-memory result of manifest generation: the application document and -/// any additional content provider class names for ApplicationRegistration.java. +/// any additional runtime provider class names to generate. /// public record GeneratedManifest (XDocument Document, string[] AdditionalProviderSources); diff --git a/src/Mono.Android/Mono.Android.slnf b/src/Mono.Android/Mono.Android.slnf index dc1ead421c5..8b4dc80b3c1 100644 --- a/src/Mono.Android/Mono.Android.slnf +++ b/src/Mono.Android/Mono.Android.slnf @@ -7,7 +7,6 @@ "build-tools\\jnienv-gen\\jnienv-gen.csproj", "external\\Java.Interop\\src\\Java.Interop.NamingCustomAttributes\\Java.Interop.NamingCustomAttributes.shproj", "external\\Java.Interop\\tools\\generator\\generator.csproj", - "external\\Java.Interop\\tools\\jcw-gen\\jcw-gen.csproj", "src\\Mono.Android\\Mono.Android.csproj", "src\\java-runtime\\java-runtime.csproj" ] diff --git a/src/Xamarin.Android.Build.Tasks/Resources/ApplicationRegistration.java b/src/Xamarin.Android.Build.Tasks/Resources/ApplicationRegistration.java deleted file mode 100644 index f53b64bec97..00000000000 --- a/src/Xamarin.Android.Build.Tasks/Resources/ApplicationRegistration.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.dot.android; - -public class ApplicationRegistration { - - public static android.content.Context Context; - - public static void registerApplications () - { - // REGISTER_APPLICATION_AND_INSTRUMENTATION_CLASSES_HERE - } -} diff --git a/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java b/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java index 5660876e513..c761f292a9b 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java +++ b/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java @@ -1,7 +1,5 @@ package mono; -//NOTE: we can't use import, see Generator.GetMonoInitSource - public class MonoRuntimeProvider extends android.content.ContentProvider { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs index 22e25c62f30..feb3bd584c7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs @@ -48,10 +48,10 @@ public void FilesThatAreExpected (string resourceName) Assert.AreNotEqual (0, new FileInfo (tempFile).Length, "file should be non-empty!"); } - [Test] - public void FileThatDoesNotExist () + [TestCase ("thisdoesnotexist")] + [TestCase ("ApplicationRegistration.java")] + public void FileThatDoesNotExist (string resourceName) { - var resourceName = "thisdoesnotexist"; var task = new CopyResource { BuildEngine = engine, ResourceName = resourceName, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs index 9b6dfff193f..0e71fb289af 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Security; using System.Security.Cryptography; @@ -2665,19 +2666,45 @@ public void TrimmableTypeMap_RuntimeArtifacts_ArePackagedInSdk () { var toolsDir = TestEnvironment.AndroidMSBuildDirectory; + foreach (var file in new [] { + "java_runtime_trimmable.jar", + "java_runtime_trimmable.dex", + }) { + FileAssert.Exists (Path.Combine (toolsDir, file), $"{file} should exist in the SDK pack."); + } + foreach (var file in new [] { "java_runtime.jar", "java_runtime.dex", "java_runtime_fastdev.jar", "java_runtime_fastdev.dex", - "java_runtime_trimmable.jar", - "java_runtime_trimmable.dex", "java_runtime_clr.jar", "java_runtime_clr.dex", "java_runtime_fastdev_clr.jar", "java_runtime_fastdev_clr.dex", }) { - FileAssert.Exists (Path.Combine (toolsDir, file), $"{file} should exist in the SDK pack."); + FileAssert.DoesNotExist (Path.Combine (toolsDir, file), $"{file} should not exist in the SDK pack."); + } + + using var runtimeJar = ZipFile.OpenRead (Path.Combine (toolsDir, "java_runtime_trimmable.jar")); + foreach (var entry in new [] { + "mono/android/Runtime.class", + "mono/android/IGCUserPeer.class", + "mono/android/GCUserPeer.class", + "mono/MonoPackageManager.class", + "mono/NativeLibraryHelper.class", + }) { + Assert.IsNotNull (runtimeJar.GetEntry (entry), $"{entry} must remain in the runtime JAR."); + } + foreach (var entry in new [] { + "mono/android/DebugRuntime.class", + "mono/android/BuildConfig.class", + "mono/android/app/XamarinAndroidEnvironmentVariables.class", + "mono/MonoPackageManager_Resources.class", + "net/dot/android/ApplicationRegistration.class", + "classes.dex", + }) { + Assert.IsNull (runtimeJar.GetEntry (entry), $"{entry} must not be packaged in the runtime JAR."); } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 13bdcbd28cc..0fa46c55ee0 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -171,11 +171,6 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. True - False - True - False diff --git a/src/java-runtime/java-runtime.targets b/src/java-runtime/java-runtime.targets index 116a4921b63..c872b59917f 100644 --- a/src/java-runtime/java-runtime.targets +++ b/src/java-runtime/java-runtime.targets @@ -2,57 +2,24 @@ - <_RuntimeOutput Include="$(OutputPath)java_runtime.jar"> - $(OutputPath)java_runtime.jar - $(OutputPath)java_runtime.dex - $(IntermediateOutputPath)release - $(IntermediateOutputPath)release.txt - java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java - <_RuntimeOutput Include="$(OutputPath)java_runtime_trimmable.jar"> $(OutputPath)java_runtime_trimmable.jar $(OutputPath)java_runtime_trimmable.dex $(IntermediateOutputPath)release-trimmable $(IntermediateOutputPath)release-trimmable.txt - java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\MonoPackageManager.java - - <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev.jar"> - $(OutputPath)java_runtime_fastdev.jar - $(OutputPath)java_runtime_fastdev.dex - $(IntermediateOutputPath)fastdev - $(IntermediateOutputPath)fastdev.txt - java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java - - - <_RuntimeOutput Include="$(OutputPath)java_runtime_clr.jar"> - $(OutputPath)java_runtime_clr.jar - $(OutputPath)java_runtime_clr.dex - $(IntermediateOutputPath)release-clr - $(IntermediateOutputPath)release-clr.txt - java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\MonoPackageManager.java - - <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev_clr.jar"> - $(OutputPath)java_runtime_fastdev_clr.jar - $(OutputPath)java_runtime_fastdev_clr.dex - $(IntermediateOutputPath)fastdev-clr - $(IntermediateOutputPath)fastdev-clr.txt - java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\MonoPackageManager.java + - - <_RuntimeSource Include="@(AllRuntimeSource)" /> - <_RuntimeSource Remove="%(_RuntimeOutput.RemoveItems)" /> - <_RuntimeSource Include="%(_RuntimeOutput.AddItems)" Condition=" '%(_RuntimeOutput.AddItems)' != '' " /> - - diff --git a/src/java-runtime/java/mono/android/DebugRuntime.java b/src/java-runtime/java/mono/android/DebugRuntime.java deleted file mode 100644 index 8d42e45e263..00000000000 --- a/src/java-runtime/java/mono/android/DebugRuntime.java +++ /dev/null @@ -1,8 +0,0 @@ -package mono.android; - -public class DebugRuntime { - private DebugRuntime () - {} - - public static native void init (String[] apks, String runtimeLibDir, String[] appDirs, boolean haveSplitApks); -} diff --git a/src/java-runtime/java/mono/android/MonoPackageManager.java b/src/java-runtime/java/mono/android/MonoPackageManager.java deleted file mode 100644 index afbee894eb0..00000000000 --- a/src/java-runtime/java/mono/android/MonoPackageManager.java +++ /dev/null @@ -1,172 +0,0 @@ -package mono; - -import java.io.*; -import java.lang.String; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.util.Calendar; -import java.util.Locale; -import java.util.HashSet; -import java.util.zip.*; -import java.util.Arrays; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.res.AssetManager; -import android.os.Build; -import android.util.Log; -import mono.android.Runtime; -import mono.android.DebugRuntime; -import mono.android.BuildConfig; -import net.dot.android.ApplicationRegistration; - -public class MonoPackageManager { - - static Object lock = new Object (); - static boolean initialized; - - public static void LoadApplication (Context context) - { - synchronized (lock) { - android.content.pm.ApplicationInfo runtimePackage = context.getApplicationInfo (); - String[] apks = null; - String[] splitApks = runtimePackage.splitSourceDirs; - if (splitApks != null && splitApks.length > 0) { - apks = new String[splitApks.length + 1]; - apks [0] = runtimePackage.sourceDir; - System.arraycopy (splitApks, 0, apks, 1, splitApks.length); - } else { - apks = new String[] { runtimePackage.sourceDir }; - } - - if (context instanceof android.app.Application) { - ApplicationRegistration.Context = context; - } - if (!initialized) { - Locale locale = Locale.getDefault (); - String language = locale.getLanguage () + "-" + locale.getCountry (); - String filesDir = context.getFilesDir ().getAbsolutePath (); - String cacheDir = context.getCacheDir ().getAbsolutePath (); - String dataDir = getNativeLibraryPath (context); - ClassLoader loader = context.getClassLoader (); - String runtimeDir = getNativeLibraryPath (runtimePackage); - int localDateTimeOffset; - - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - localDateTimeOffset = OffsetDateTime.now().getOffset().getTotalSeconds(); - } - else { - localDateTimeOffset = (Calendar.getInstance ().get (Calendar.ZONE_OFFSET) + Calendar.getInstance ().get (Calendar.DST_OFFSET)) / 1000; - } - - // - // Should the order change here, src/mono/native/runtime-base/shared-constants.hh and - // src/native/clr/include/constants.hh must be updated accordingly - // - String[] appDirs = new String[] {filesDir, cacheDir, dataDir}; - boolean haveSplitApks = runtimePackage.splitSourceDirs != null && runtimePackage.splitSourceDirs.length > 0; - - // - // Preload DSOs libmonodroid.so depends on so that the dynamic - // linker can resolve them when loading monodroid. This is not - // needed in the latest Android versions but is required in at least - // API 16 and since there's no inherent negative effect of doing it, - // we can do it unconditionally. - // - // Additionally, we need to load all the DSOs which depend on libmonosgen-2.0. The reason is that on - // some 64-bit devices running Android 5.{0,1} the dynamic linker fails to find `libmonosgen-2.0.so` - // even though it is in the same directory as the DSO depending on it *and* libmonosgen-2.0 is already - // in memory. This was seen on some devices (Huawei P8) and the x86_64 Android emulator. See the - // following issues: - // - // https://github.com/dotnet/android/issues/4772 - // https://github.com/dotnet/android/issues/4852 - // - // We could limit the preloading to only 64-bit 5.x Android versions but it appears to be more effort - // than necessary as preloading won't hurt performance (much - some libraries might not be needed - // immediately during startup) and there might be other Android builds out there with similar problems. - // - // We need to use our own `BuildConfig` class to detect debug builds here because, - // it seems, ApplicationInfo.flags information is not reliable - in the debug builds - // (with `android:debuggable=true` present on the `` element in the - // manifest) using shared runtime, the `runtimePackage.flags` field does NOT have - // the FLAGS_DEBUGGABLE (0x00000002) set and thus we'd revert to the `else` clause - // below, leading to an error locating the Mono runtime - // - if (BuildConfig.Debug) { - NativeLibraryHelper.loadLibrary ("xamarin-debug-app-helper", runtimePackage, apks); - DebugRuntime.init (apks, runtimeDir, appDirs, haveSplitApks); - } else { - NativeLibraryHelper.loadLibrary ("monosgen-2.0", runtimePackage, apks); - } - NativeLibraryHelper.loadLibrary ("xamarin-app", runtimePackage, apks); - - if (!BuildConfig.DotNetRuntime) { - // .net5+ APKs don't contain `libmono-native.so` - NativeLibraryHelper.loadLibrary ("mono-native", runtimePackage, apks); - } - - NativeLibraryHelper.loadLibrary ("monodroid", runtimePackage, apks); - - Runtime.initInternal ( - language, - apks, - runtimeDir, - appDirs, - localDateTimeOffset, - loader, - MonoPackageManager_Resources.Assemblies, - isEmulator (), - haveSplitApks - ); - - ApplicationRegistration.registerApplications (); - - initialized = true; - } - } - } - - // We need to detect the emulator in order to determine the maximum gref count. - // The official Android emulator requires a much lower maximum than actual - // devices. Hopefully other emulators don't need the treatment. If they do, we - // can add their detection here. We should perform the absolute minimum of - // checking in order to save time. - static boolean isEmulator() - { - String val = Build.HARDWARE; - - // This detects the official Android emulator - if (val.contains ("ranchu") || val.contains ("goldfish")) - return true; - - return false; - } - - public static void setContext (Context context) - { - // Ignore; vestigial - } - - static String getNativeLibraryPath (Context context) - { - return getNativeLibraryPath (context.getApplicationInfo ()); - } - - static String getNativeLibraryPath (ApplicationInfo ainfo) - { - if (android.os.Build.VERSION.SDK_INT >= 9) - return ainfo.nativeLibraryDir; - return ainfo.dataDir + "/lib"; - } - - public static String[] getAssemblies () - { - return MonoPackageManager_Resources.Assemblies; - } - - public static String[] getDependencies () - { - return MonoPackageManager_Resources.Dependencies; - } -} diff --git a/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java b/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java index 82f350bfa6c..a081446fea2 100644 --- a/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java +++ b/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java @@ -7,7 +7,4 @@ public class MonoPackageManager_Resources { public static String[] Assemblies = new String[]{ }; - public static String[] Dependencies = new String[]{ - }; } - diff --git a/src/java-runtime/java/mono/android/Runtime.java b/src/java-runtime/java/mono/android/Runtime.java index 385904a1ec3..9e067334dad 100644 --- a/src/java-runtime/java/mono/android/Runtime.java +++ b/src/java-runtime/java/mono/android/Runtime.java @@ -7,13 +7,11 @@ public class Runtime { static java.lang.Class java_lang_Class = java.lang.Class.class;; static java.lang.Class java_lang_System = java.lang.System.class; static java.lang.Class mono_android_IGCUserPeer = mono.android.IGCUserPeer.class; - static java.lang.Class mono_android_GCUserPeer = mono.android.GCUserPeer.class; static { Thread.setDefaultUncaughtExceptionHandler (new XamarinUncaughtExceptionHandler (Thread.getDefaultUncaughtExceptionHandler ())); } - public static native void init (String lang, String[] runtimeApks, String runtimeDataDir, String[] appDirs, ClassLoader loader, String[] externalStorageDirs, String[] assemblies, String packageName, int apiLevel, String[] environmentVariables); public static native void initInternal ( String lang, String[] runtimeApks, @@ -26,10 +24,6 @@ public static native void initInternal ( boolean haveSplitApks ); public static native void registerNatives (java.lang.Class nativeClass); - public static native int createNewContext (String[] runtimeApks, String[] assemblies, ClassLoader loader); - public static native int createNewContextWithData (String[] runtimeApks, String[] assemblies, byte[][] assembliesBytes, String[] assembliesPaths, ClassLoader loader, boolean forcePreloadAssemblies); - public static native void switchToContext (int contextID); - public static native void destroyContexts (int[] contextIDs); public static native void propagateUncaughtException (Thread javaThread, Throwable javaException); } diff --git a/src/java-runtime/java/mono/android/app/XamarinAndroidEnvironmentVariables.java b/src/java-runtime/java/mono/android/app/XamarinAndroidEnvironmentVariables.java deleted file mode 100644 index 00d41fcdd6d..00000000000 --- a/src/java-runtime/java/mono/android/app/XamarinAndroidEnvironmentVariables.java +++ /dev/null @@ -1,9 +0,0 @@ -package mono.android.app; - -public class XamarinAndroidEnvironmentVariables -{ - // Variables are specified the in "name", "value" pairs - public static final String[] Variables = new String[] { -//@ENVVARS@ - }; -} diff --git a/src/java-runtime/java/mono/android/clr/MonoPackageManager.java b/src/java-runtime/java/mono/android/clr/MonoPackageManager.java index 0f59ebd590c..5ed5b7b43b7 100644 --- a/src/java-runtime/java/mono/android/clr/MonoPackageManager.java +++ b/src/java-runtime/java/mono/android/clr/MonoPackageManager.java @@ -16,8 +16,6 @@ import android.os.Build; import android.util.Log; import mono.android.Runtime; -import mono.android.DebugRuntime; -import mono.android.BuildConfig; import net.dot.android.ApplicationRegistration; public class MonoPackageManager { @@ -100,11 +98,6 @@ static boolean isEmulator() return false; } - public static void setContext (Context context) - { - // Ignore; vestigial - } - static String getNativeLibraryPath (Context context) { return getNativeLibraryPath (context.getApplicationInfo ()); @@ -120,8 +113,4 @@ public static String[] getAssemblies () return MonoPackageManager_Resources.Assemblies; } - public static String[] getDependencies () - { - return MonoPackageManager_Resources.Dependencies; - } } diff --git a/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java b/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java deleted file mode 100644 index e05ba068714..00000000000 --- a/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = true; - public static boolean DotNetRuntime = true; -} diff --git a/src/java-runtime/java/mono/android/debug/BuildConfig.java b/src/java-runtime/java/mono/android/debug/BuildConfig.java deleted file mode 100644 index 575b166ca60..00000000000 --- a/src/java-runtime/java/mono/android/debug/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = true; - public static boolean DotNetRuntime = false; -} diff --git a/src/java-runtime/java/mono/android/release-net6/BuildConfig.java b/src/java-runtime/java/mono/android/release-net6/BuildConfig.java deleted file mode 100644 index 498a947ff8c..00000000000 --- a/src/java-runtime/java/mono/android/release-net6/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = false; - public static boolean DotNetRuntime = true; -} diff --git a/src/java-runtime/java/mono/android/release/BuildConfig.java b/src/java-runtime/java/mono/android/release/BuildConfig.java deleted file mode 100644 index 4070a147bb1..00000000000 --- a/src/java-runtime/java/mono/android/release/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = false; - public static boolean DotNetRuntime = false; -} From 7b60efd96de8fd85e49a9038f2a03902a3324ca7 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Mon, 12 Oct 2026 16:26:59 +0200 Subject: [PATCH 2/2] [build] Clean up retired Java runtime artifacts Remove exact retired JAR/DEX paths before Build and Clean even when retained runtime generation is up to date. Cover repeated seeded upgrades, retained output timestamps, unrelated files and deletion error propagation. Remove the obsolete Kotlin XA4217 catalog entry while retaining the active architecture diagnostic. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- Documentation/docs-mobile/messages/index.md | 1 - .../JavaRuntimeTargetsTests.cs | 86 +++++++++++++++++++ src/java-runtime/java-runtime.targets | 8 ++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/JavaRuntimeTargetsTests.cs diff --git a/Documentation/docs-mobile/messages/index.md b/Documentation/docs-mobile/messages/index.md index c48000686b7..44d4513d0ae 100644 --- a/Documentation/docs-mobile/messages/index.md +++ b/Documentation/docs-mobile/messages/index.md @@ -193,7 +193,6 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla + [XA4214](xa4214.md): The managed type \`Library1.Class1\` exists in multiple assemblies: Library1, Library2. Please refactor the managed type names in these assemblies so that they are not identical. + [XA4215](xa4215.md): The Java type \`com.contoso.library1.Class1\` is generated by more than one managed type. Please change the \[Register\] attribute so that the same Java type is not emitted. + [XA4216](xa4216.md): The deployment target '19' is not supported (the minimum is '24'). Please increase the $(SupportedOSPlatformVersion) property value in your project file. -+ XA4217: Cannot override Kotlin-generated method '{method}' because it is not a valid Java method name. This method can only be overridden from Kotlin. + [XA4217](xa4217.md): Architecture '{arch}' has Java types which have no counterparts in template architecture '{templateArch}': {types} + [XA4218](xa4218.md): Unable to find //manifest/application/uses-library at path: {path} + XA4219: Cannot find binding generator for language {language} or {defaultLanguage}. diff --git a/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/JavaRuntimeTargetsTests.cs b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/JavaRuntimeTargetsTests.cs new file mode 100644 index 00000000000..1887171251e --- /dev/null +++ b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/JavaRuntimeTargetsTests.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; +using System.Linq; +using System.Xml.Linq; + +using NUnit.Framework; + +namespace Xamarin.Android.Build.Tests; + +[TestFixture] +public class JavaRuntimeTargetsTests : BaseTest +{ + [TestCase ("Build")] + [TestCase ("Clean")] + public void RetiredArtifactsAreRemovedWithoutRegeneratingRetainedOutputs (string target) + { + string directory = Path.Combine (Root, "temp", TestName); + string output = Path.Combine (directory, "output"); + Directory.CreateDirectory (output); + string targets = Path.Combine (NativeAotBootstrapTestTools.FindRepositoryRoot (), "src", "java-runtime", "java-runtime.targets"); + string project = Path.Combine (directory, "runtime.proj"); + new XDocument ( + new XElement ("Project", + new XElement ("PropertyGroup", + new XElement ("OutputPath", output + Path.DirectorySeparatorChar), + new XElement ("IntermediateOutputPath", Path.Combine (directory, "obj") + Path.DirectorySeparatorChar), + new XElement ("JavaCPath", "unexpected-javac-invocation"), + new XElement ("JavaPath", "unexpected-d8-invocation")), + new XElement ("Import", new XAttribute ("Project", targets)), + new XElement ("Target", new XAttribute ("Name", "Build")), + new XElement ("Target", new XAttribute ("Name", "Clean")))) + .Save (project); + + string [] retired = [ + "java_runtime.jar", "java_runtime.dex", + "java_runtime_fastdev.jar", "java_runtime_fastdev.dex", + "java_runtime_clr.jar", "java_runtime_clr.dex", + "java_runtime_fastdev_clr.jar", "java_runtime_fastdev_clr.dex", + ]; + string [] retained = ["java_runtime_trimmable.jar", "java_runtime_trimmable.dex", "mono_android_Runtime.h", "custom-runtime.jar"]; + DateTime timestamp = new [] { File.GetLastWriteTimeUtc (project), File.GetLastWriteTimeUtc (targets) }.Max ().AddSeconds (2); + foreach (string name in retained) { + string file = Path.Combine (output, name); + File.WriteAllText (file, name); + File.SetLastWriteTimeUtc (file, timestamp); + } + + string dotnet = Environment.GetEnvironmentVariable ("DOTNET_HOST_PATH") ?? "dotnet"; + for (int run = 0; run < 2; run++) { + foreach (string name in retired) { + File.WriteAllText (Path.Combine (output, name), "stale"); + } + var result = NativeAotBootstrapTestTools.Run (dotnet, "msbuild", project, "-t:" + target, "-v:normal", "-nr:false"); + Assert.AreEqual (0, result.ExitCode, result.Output + result.Error); + foreach (string name in retired) { + FileAssert.DoesNotExist (Path.Combine (output, name), $"{target} must remove retired artifact {name} on every run."); + } + foreach (string name in retained) { + string file = Path.Combine (output, name); + if (target == "Clean" && name == "java_runtime_trimmable.jar") { + FileAssert.DoesNotExist (file, "Clean still removes the retained JAR through its existing cleanup target."); + continue; + } + FileAssert.Exists (file, $"{target} must not remove {name} as a retired artifact."); + Assert.AreEqual (name, File.ReadAllText (file)); + Assert.AreEqual (timestamp, File.GetLastWriteTimeUtc (file), "Cleanup must not rewrite retained or unrelated outputs."); + } + if (target == "Build") { + StringAssert.Contains ("Skipping target \"_BuildJavaRuntimeJar\"", result.Output); + StringAssert.Contains ("Skipping target \"_GenerateRuntimeDex16\"", result.Output); + } + } + + if (target == "Build" && !OperatingSystem.IsWindows ()) { + File.WriteAllText (Path.Combine (output, retired [0]), "cannot delete"); + var permissions = File.GetUnixFileMode (output); + try { + File.SetUnixFileMode (output, permissions & ~(UnixFileMode.UserWrite | UnixFileMode.GroupWrite | UnixFileMode.OtherWrite)); + var result = NativeAotBootstrapTestTools.Run (dotnet, "msbuild", project, "-t:Build", "-v:normal", "-nr:false"); + Assert.AreNotEqual (0, result.ExitCode, "A failed retired-artifact deletion must fail the build.\n" + result.Output + result.Error); + } finally { + File.SetUnixFileMode (output, permissions); + } + } + } +} diff --git a/src/java-runtime/java-runtime.targets b/src/java-runtime/java-runtime.targets index c872b59917f..62e22a52159 100644 --- a/src/java-runtime/java-runtime.targets +++ b/src/java-runtime/java-runtime.targets @@ -10,6 +10,14 @@ + + + <_RetiredJavaRuntimeName Include="java_runtime;java_runtime_fastdev;java_runtime_clr;java_runtime_fastdev_clr" /> + <_RetiredJavaRuntimeArtifact Include="@(_RetiredJavaRuntimeName->'$(OutputPath)%(Identity).jar');@(_RetiredJavaRuntimeName->'$(OutputPath)%(Identity).dex')" /> + + + +