Skip to content

Commit 2bdf2bc

Browse files
authored
[Java.Base] Bind package java.util.concurrent (#1274)
Context: 0aec86a Commit 0aec86a mentioned: > * Use of `JNIEnv.GetJniName()` > > string __id = "(L" + global::Android.Runtime.JNIEnv.GetJniName (GetType ().DeclaringType) + ";)V"; > > Impacts: NestedTypes.cs This issue also impacts [`java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject`][0]. Update `Java.Base` to bind the `java.util.concurrent` package, which will cause `AbstractQueuedSynchronizer` to be bound, which in turn forces us to update `generator` to not emit `JNIEnv.GetJniName()`. Instead of using `JNIEnv.GetJniName(GetType().DeclaringType)`, use: JniEnvironment.Runtime.TypeManager.GetTypeSignature (GetType ().DeclaringType).SimpleReference Update NestedTypes.cs to enable `TryJavaInterop1 => true`. Update `Java.Base.csproj` to ignore C# warning [CS0109][1], as [`CompletableFuture.handle()`][2] is emitted with a `new` which is not required: Java.Util.Concurrent.CompletableFuture.cs(629,76): warning CS0109: The member 'CompletableFuture.Handle(IBiFunction?)' does not hide an accessible member. The new keyword is not required. Add a test to `tests/Java.Base-Tests` which tests nested type support. Update `JavaNativeTypeManager.cs` so that `IsNonStaticInnerClass()` supports JavaInterop1-style attributes, not just XAJavaInterop1. Aside: I updated my local JDK to JDK-17 (from JDK-11), which caused many changes to `src/Java.Base-ref.cs`, particularly parameter names. TODO? Update `Java.Interop.Tools.JavaCallableWrappers` so that non-static inner classes don't have a prefix of their declaring type. This would result in `example/MyQueuedSynchronizer$MyConditionObject` instead of `example/MyQueuedSynchronizer$MyQueuedSynchronizer_MyConditionObject`. [0]: https://developer.android.com/reference/java/util/concurrent/locks/AbstractQueuedSynchronizer.ConditionObject [1]: https://learn.microsoft.com/dotnet/csharp/misc/cs0109 [2]: https://developer.android.com/reference/java/util/concurrent/CompletableFuture#handle(java.util.function.BiFunction%3C?%20super%20T,java.lang.Throwable,?%20extends%20U%3E)
1 parent 87fdb8e commit 2bdf2bc

File tree

10 files changed

+3072
-35
lines changed

10 files changed

+3072
-35
lines changed

src/Java.Base-ref.cs

Lines changed: 2934 additions & 30 deletions
Large diffs are not rendered by default.

src/Java.Base/Java.Base.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>$(DotNetTargetFramework)</TargetFramework>
55
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
66
<Nullable>enable</Nullable>
7-
<NoWarn>$(NoWarn);8764;0114</NoWarn>
7+
<NoWarn>$(NoWarn);8764;0109;0114</NoWarn>
88
</PropertyGroup>
99

1010
<Import Project="..\..\TargetFrameworkDependentValues.props" />

src/Java.Base/Transforms/Metadata.xml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
not(
55
starts-with(@name, 'java.lang')
66
or starts-with(@name, 'java.io')
7+
or starts-with(@name, 'java.util.concurrent')
78
or starts-with(@name, 'java.util.function')
89
)]" />
910

@@ -87,4 +88,36 @@
8788
name="managedOverride">reabstract</attr>
8889
<attr path="/api/package[@name='java.lang.reflect']/interface[@name='AnnotatedType']/method[@name='getDeclaredAnnotations' and count(parameter)=0]"
8990
name="explicitInterface">IAnnotatedElement</attr>
91+
92+
<attr path="/api/package[@name='java.util.concurrent']/interface[@name='RunnableFuture']/method[@name='run' and count(parameter)=0]"
93+
name="managedOverride">reabstract</attr>
94+
<attr path="/api/package[@name='java.util.concurrent']/interface[@name='RunnableFuture']/method[@name='run' and count(parameter)=0]"
95+
name="explicitInterface">global::Java.Lang.IRunnable</attr>
96+
<attr path="/api/package[@name='java.util.concurrent']/class[@name='CompletableFuture']/method[@name='applyToEither'
97+
or @name='applyToEitherAsync'
98+
or @name='acceptEither'
99+
or @name='acceptEitherAsync'
100+
or @name='exceptionally'
101+
or @name='handle'
102+
or @name='handleAsync'
103+
or @name='runAfterBoth'
104+
or @name='runAfterBothAsync'
105+
or @name='runAfterEither'
106+
or @name='runAfterEitherAsync'
107+
or @name='thenAccept'
108+
or @name='thenAcceptAsync'
109+
or @name='thenAcceptBoth'
110+
or @name='thenAcceptBothAsync'
111+
or @name='thenApply'
112+
or @name='thenApplyAsync'
113+
or @name='thenCombine'
114+
or @name='thenCombineAsync'
115+
or @name='thenCompose'
116+
or @name='thenComposeAsync'
117+
or @name='thenRun'
118+
or @name='thenRunAsync'
119+
or @name='whenComplete'
120+
or @name='whenCompleteAsync'
121+
]"
122+
name="managedReturn">Java.Util.Concurrent.ICompletionStage</attr>
90123
</metadata>

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ internal static bool IsNonStaticInnerClass (TypeDefinition? type, IMetadataResol
737737
foreach (var baseType in type.GetBaseTypes (cache)) {
738738
if (baseType == null)
739739
continue;
740-
if (!baseType.AnyCustomAttributes (typeof (RegisterAttribute)))
740+
if (!HasTypeRegistrationAttribute (baseType))
741741
continue;
742742

743743
foreach (var method in baseType.Methods) {
@@ -753,6 +753,14 @@ internal static bool IsNonStaticInnerClass (TypeDefinition? type, IMetadataResol
753753

754754
return false;
755755
}
756+
757+
static bool HasTypeRegistrationAttribute (TypeDefinition type)
758+
{
759+
if (!type.HasCustomAttributes)
760+
return false;
761+
return type.AnyCustomAttributes (typeof (RegisterAttribute)) ||
762+
type.AnyCustomAttributes ("Java.Interop.JniTypeSignatureAttribute");
763+
}
756764
#endif // HAVE_CECIL
757765

758766
static string ToCrc64 (string value)

tests/Java.Base-Tests/Java.Base/JavaVMFixture.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ static partial void CreateJavaVM ()
2020
["example/MyIntConsumer"] = typeof (MyIntConsumer),
2121
["example/MyRunnable"] = typeof (MyRunnable),
2222
[JavaInvoker.JniTypeName] = typeof (JavaInvoker),
23+
[MyQueuedSynchronizer.JniTypeName] = typeof (MyQueuedSynchronizer),
24+
["example/MyQueuedSynchronizer$MyQueuedSynchronizer_MyConditionObject"] = typeof (MyQueuedSynchronizer.MyConditionObject),
2325
}
2426
);
2527
JniRuntime.SetCurrent (c);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
3+
using Java.Interop;
4+
5+
using NUnit.Framework;
6+
7+
namespace Java.BaseTests {
8+
9+
[TestFixture]
10+
public class NestedTypeTests : JavaVMFixture {
11+
12+
[Test]
13+
public void Create_AbstractQueuedSynchronizer_ConditionObject ()
14+
{
15+
using var outer = new MyQueuedSynchronizer ();
16+
using var inner = new MyQueuedSynchronizer.MyConditionObject (outer);
17+
}
18+
}
19+
20+
[JniTypeSignature (JniTypeName)]
21+
class MyQueuedSynchronizer : Java.Util.Concurrent.Locks.AbstractQueuedSynchronizer {
22+
internal const string JniTypeName = "example/MyQueuedSynchronizer";
23+
24+
public MyQueuedSynchronizer ()
25+
{
26+
}
27+
28+
public class MyConditionObject : Java.Util.Concurrent.Locks.AbstractQueuedSynchronizer.ConditionObject {
29+
30+
public MyConditionObject (MyQueuedSynchronizer outer)
31+
: base (outer)
32+
{
33+
}
34+
}
35+
}
36+
}

tests/generator-Tests/Integration-Tests/NestedTypes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace generatortests
66
[TestFixture]
77
public class NestedTypes : BaseGeneratorTest
88
{
9-
protected override bool TryJavaInterop1 => false;
9+
protected override bool TryJavaInterop1 => true;
1010

1111
[Test]
1212
public void GeneratedOK ()

tests/generator-Tests/expected.ji/NestedTypes/Java.Lang.Object.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
#nullable restore
111
using System;
212
using System.Collections.Generic;
313
using Java.Interop;

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

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
#nullable restore
111
using System;
212
using System.Collections.Generic;
313
using Java.Interop;
@@ -14,10 +24,39 @@ public abstract partial class Action : global::Java.Lang.Object {
1424
[global::Java.Interop.JniTypeSignature ("xamarin/test/NotificationCompatBase$Action$Factory", GenerateJavaPeer=false)]
1525
public partial interface IFactory : IJavaPeerable {
1626
// 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']]"
27+
[global::Java.Interop.JniMethodSignature ("build", "(I)Lxamarin/test/NotificationCompatBase$Action;")]
1728
global::Xamarin.Test.NotificationCompatBase.Action Build (int p0);
1829

1930
}
2031

32+
[global::Java.Interop.JniTypeSignature ("xamarin/test/NotificationCompatBase$Action$Factory", GenerateJavaPeer=false)]
33+
internal partial class IFactoryInvoker : global::Java.Lang.Object, IFactory {
34+
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
35+
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
36+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
37+
get { return _members_xamarin_test_NotificationCompatBase_Action_Factory; }
38+
}
39+
40+
static readonly JniPeerMembers _members_xamarin_test_NotificationCompatBase_Action_Factory = new JniPeerMembers ("xamarin/test/NotificationCompatBase$Action$Factory", typeof (IFactoryInvoker));
41+
42+
public IFactoryInvoker (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
43+
{
44+
}
45+
46+
public unsafe global::Xamarin.Test.NotificationCompatBase.Action Build (int p0)
47+
{
48+
const string __id = "build.(I)Lxamarin/test/NotificationCompatBase$Action;";
49+
try {
50+
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
51+
__args [0] = new JniArgumentValue (p0);
52+
var __rm = _members_xamarin_test_NotificationCompatBase_Action_Factory.InstanceMethods.InvokeAbstractObjectMethod (__id, this, __args);
53+
return global::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<global::Xamarin.Test.NotificationCompatBase.Action> (ref __rm, JniObjectReferenceOptions.CopyAndDispose);
54+
} finally {
55+
}
56+
}
57+
58+
}
59+
2160
static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/NotificationCompatBase$Action", typeof (Action));
2261

2362
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
@@ -64,9 +103,10 @@ protected InstanceInner (ref JniObjectReference reference, JniObjectReferenceOpt
64103
}
65104

66105
// Metadata.xml XPath constructor reference: path="/api/package[@name='xamarin.test']/class[@name='NotificationCompatBase.InstanceInner']/constructor[@name='NotificationCompatBase.InstanceInner' and count(parameter)=1 and parameter[1][@type='xamarin.test.NotificationCompatBase']]"
106+
[global::Java.Interop.JniConstructorSignature ("(Lxamarin/test/NotificationCompatBase;)V")]
67107
public unsafe InstanceInner (global::Xamarin.Test.NotificationCompatBase __self) : base (ref *InvalidJniObjectReference, JniObjectReferenceOptions.None)
68108
{
69-
string __id = "(L" + global::Android.Runtime.JNIEnv.GetJniName (GetType ().DeclaringType) + ";)V";
109+
string __id = "(L" + global::Java.Interop.JniEnvironment.Runtime.TypeManager.GetTypeSignature (GetType ().DeclaringType).SimpleReference + ";)V";
70110

71111
if (PeerReference.IsValid)
72112
return;

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,11 @@ public string GetJniNestedDerivedSignature (CodeGenerationOptions opt)
210210
StringBuilder sb = new StringBuilder ();
211211
foreach (Parameter p in items) {
212212
if (p.Name == "__self") {
213-
sb.AppendFormat ("L\" + global::Android.Runtime.JNIEnv.GetJniName (GetType ().DeclaringType{0}) + \";", opt.NullForgivingOperator);
213+
if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) {
214+
sb.AppendFormat ("L\" + global::Java.Interop.JniEnvironment.Runtime.TypeManager.GetTypeSignature (GetType ().DeclaringType{0}).SimpleReference + \";", opt.NullForgivingOperator);
215+
} else {
216+
sb.AppendFormat ("L\" + global::Android.Runtime.JNIEnv.GetJniName (GetType ().DeclaringType{0}) + \";", opt.NullForgivingOperator);
217+
}
214218
continue;
215219
}
216220
sb.Append (p.JniType);

0 commit comments

Comments
 (0)