Skip to content

Commit 06b9c48

Browse files
committed
[generator] Use + for nested types, not /
Context: dotnet/android#9747 Context: https://discord.com/channels/732297728826277939/732297837953679412/1336353039031734352 Context: https://discord.com/channels/732297728826277939/732297837953679412/1336358257769316372 The `[Register]` attribute provides "connector method" names, and for interface methods this will also include the name of the type which declares the method, which itself may be in a nested type: namespace Android.App { public partial class Application { public partial interface IActivityLifecycleCallbacks : IJavaObject, IJavaPeerable { [Register ( name: "onActivityCreated", signature: "(Landroid/app/Activity;Landroid/os/Bundle;)V", connector: "GetOnActivityCreated_Landroid_app_Activity_Landroid_os_Bundle_Handler:Android.App.Application/IActivityLifecycleCallbacksInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")] void OnActivityCreated (Android.App.Activity activity, Android.OS.Bundle? savedInstanceState); // … } } } This output has been largely unchanged for *years*, but there is a problem with it: the `connector` parameter contains a nested type, and uses `/` to separate the "outer" type from the "inner" type. This works on MonoVM. This *fails* on NativeAOT and CoreCLR: Could not resolve type 'Android.App.Application/IActivityLifecycleCallbacksInvoker' in assembly 'Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065'. The `/` needs to be a `+` in order for `Type.GetType()` to find it: [Register ( name: "onActivityCreated", signature: "(Landroid/app/Activity;Landroid/os/Bundle;)V", connector: "GetOnActivityCreated_Landroid_app_Activity_Landroid_os_Bundle_Handler:Android.App.Application+IActivityLifecycleCallbacksInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")] void OnActivityCreated (Android.App.Activity activity, Android.OS.Bundle? savedInstanceState); Update `generator` so that `+` is used within the `connector` parameter. However, to maintain compatibility with existing binding assemblies, update `Java.Interop.Tools.JavaCallableWrappers` so that it replaces `/` with `+` on import, so that the resulting Java Callable Wrappers contain `+` and not `/`: // Java Callable Wrapper /* partial */ class MauiApplication_ActivityLifecycleCallbacks { 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, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null\n" + // … ""; mono.android.Runtime.register ("Microsoft.Maui.MauiApplication+ActivityLifecycleCallbacks, Microsoft.Maui", MauiApplication_ActivityLifecycleCallbacks.class, __md_methods); } }
1 parent dd3c1d0 commit 06b9c48

File tree

9 files changed

+12
-12
lines changed

9 files changed

+12
-12
lines changed

src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ static CallableWrapperMethod CreateMethod (MethodDefinition methodDefinition, Ca
269269
static CallableWrapperMethod CreateMethod (string name, CallableWrapperType declaringType, string? signature, string? connector, string? managedParameters, string? outerType, string? superCall)
270270
{
271271
signature = signature ?? throw new ArgumentNullException ("`connector` cannot be null.", nameof (connector));
272-
var method_name = "n_" + name + ":" + signature + ":" + connector;
272+
var method_name = "n_" + name + ":" + signature + ":" + connector?.Replace ('/', '+');
273273

274274
var method = new CallableWrapperMethod (declaringType, name, method_name, signature);
275275

src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ static string ToCliTypePart (string part)
150150
for (int i = 0; i < parts.Length; ++i) {
151151
parts [i] = ToPascalCase (parts [i], 1);
152152
}
153-
return string.Join ("/", parts);
153+
return string.Join ("+", parts);
154154
}
155155

156156
static string ToPascalCase (string value, int minLength)

tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteNestedInterfaceTypes.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ public partial interface IParent : IJavaObject, IJavaPeerable {
88
}
99

1010
// Metadata.xml XPath interface reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent.Child']"
11-
[Register ("com/xamarin/android/Parent$Child", "", "Com.Xamarin.Android.IParent/IChildInvoker")]
11+
[Register ("com/xamarin/android/Parent$Child", "", "Com.Xamarin.Android.IParent+IChildInvoker")]
1212
public partial interface IChild : IJavaObject, IJavaPeerable {
1313
int Bar {
1414
// Metadata.xml XPath method reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent.Child']/method[@name='getBar' and count(parameter)=0]"
15-
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParent/IChildInvoker, MyAssembly")]
15+
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParent+IChildInvoker, MyAssembly")]
1616
get;
1717
}
1818

tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteNestedInterfaceTypes.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public partial interface IParent : IJavaObject, IJavaPeerable {
1212
public partial interface IChild : IJavaObject, IJavaPeerable {
1313
int Bar {
1414
// Metadata.xml XPath method reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent.Child']/method[@name='getBar' and count(parameter)=0]"
15-
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParent/IChildInvoker, MyAssembly")]
15+
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParent+IChildInvoker, MyAssembly")]
1616
get;
1717
}
1818

tests/generator-Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ public void GenerateProperNestedInterfaceSignatures ()
461461

462462
var generated = writer.ToString ();
463463

464-
Assert.True (generated.Contains ("GetOnActivityDestroyed_IHandler:Com.Xamarin.Android.Application/IActivityLifecycleInterface, MyAssembly"));
464+
Assert.True (generated.Contains ("GetOnActivityDestroyed_IHandler:Com.Xamarin.Android.Application+IActivityLifecycleInterface, MyAssembly"));
465465
Assert.False (generated.Contains ("GetOnActivityDestroyed_IHandler:Com.Xamarin.Android.Application.IActivityLifecycleInterface, MyAssembly"));
466466
}
467467

tests/generator-Tests/expected.xaji/AccessModifiers/Xamarin.Test.PublicClass.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public partial class PublicClass : global::Java.Lang.Object {
2222
[Register ("xamarin/test/PublicClass$ProtectedInterface", "", "Xamarin.Test.PublicClass/IProtectedInterfaceInvoker")]
2323
protected internal partial interface IProtectedInterface : IJavaObject, IJavaPeerable {
2424
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='PublicClass.ProtectedInterface']/method[@name='foo' and count(parameter)=0]"
25-
[Register ("foo", "()V", "GetFooHandler:Xamarin.Test.PublicClass/IProtectedInterfaceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
25+
[Register ("foo", "()V", "GetFooHandler:Xamarin.Test.PublicClass+IProtectedInterfaceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
2626
void Foo ();
2727

2828
}

tests/generator-Tests/expected.xaji/Core_Jar2Xml/Android.Views.View.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public partial class View : global::Java.Lang.Object {
2222
[Register ("android/view/View$OnClickListener", "", "Android.Views.View/IOnClickListenerInvoker")]
2323
public partial interface IOnClickListener : IJavaObject, IJavaPeerable {
2424
// Metadata.xml XPath method reference: path="/api/package[@name='android.view']/interface[@name='View.OnClickListener']/method[@name='onClick' and count(parameter)=1 and parameter[1][@type='android.view.View']]"
25-
[Register ("onClick", "(Landroid/view/View;)V", "GetOnClick_Landroid_view_View_Handler:Android.Views.View/IOnClickListenerInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
25+
[Register ("onClick", "(Landroid/view/View;)V", "GetOnClick_Landroid_view_View_Handler:Android.Views.View+IOnClickListenerInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
2626
void OnClick (global::Android.Views.View v);
2727

2828
}

tests/generator-Tests/expected.xaji/NestedTypes/Xamarin.Test.NotificationCompatBase.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public abstract partial class Action : global::Java.Lang.Object {
2525
[Register ("xamarin/test/NotificationCompatBase$Action$Factory", "", "Xamarin.Test.NotificationCompatBase/Action/IFactoryInvoker")]
2626
public partial interface IFactory : IJavaObject, IJavaPeerable {
2727
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='NotificationCompatBase.Action.Factory']/method[@name='build' and count(parameter)=1 and parameter[1][@type='int']]"
28-
[Register ("build", "(I)Lxamarin/test/NotificationCompatBase$Action;", "GetBuild_IHandler:Xamarin.Test.NotificationCompatBase/Action/IFactoryInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
28+
[Register ("build", "(I)Lxamarin/test/NotificationCompatBase$Action;", "GetBuild_IHandler:Xamarin.Test.NotificationCompatBase+Action+IFactoryInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
2929
global::Xamarin.Test.NotificationCompatBase.Action Build (int p0);
3030

3131
}

tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,10 @@ IEnumerable<GenBase> Ancestors ()
181181
public string AnnotatedVisibility => support.AnnotatedVisibility;
182182

183183
// not: not currently assembly qualified, but it uses needed
184-
// Type.GetType() conventions such as '/' for nested types.
184+
// Type.GetType() conventions such as '+' for nested types.
185185
public string AssemblyQualifiedName => string.IsNullOrWhiteSpace (Namespace)
186-
? $"{FullName.Replace ('.', '/')}"
187-
: $"{Namespace}." + $"{FullName.Substring (Namespace.Length + 1).Replace ('.', '/')}";
186+
? $"{FullName.Replace ('.', '+')}"
187+
: $"{Namespace}." + $"{FullName.Substring (Namespace.Length + 1).Replace ('.', '+')}";
188188

189189
public int ApiAvailableSince { get; set; }
190190

0 commit comments

Comments
 (0)