Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,964 changes: 2,934 additions & 30 deletions src/Java.Base-ref.cs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Java.Base/Java.Base.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>$(DotNetTargetFramework)</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);8764;0114</NoWarn>
<NoWarn>$(NoWarn);8764;0109;0114</NoWarn>
</PropertyGroup>

<Import Project="..\..\TargetFrameworkDependentValues.props" />
Expand Down
33 changes: 33 additions & 0 deletions src/Java.Base/Transforms/Metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
not(
starts-with(@name, 'java.lang')
or starts-with(@name, 'java.io')
or starts-with(@name, 'java.util.concurrent')
or starts-with(@name, 'java.util.function')
)]" />

Expand Down Expand Up @@ -87,4 +88,36 @@
name="managedOverride">reabstract</attr>
<attr path="/api/package[@name='java.lang.reflect']/interface[@name='AnnotatedType']/method[@name='getDeclaredAnnotations' and count(parameter)=0]"
name="explicitInterface">IAnnotatedElement</attr>

<attr path="/api/package[@name='java.util.concurrent']/interface[@name='RunnableFuture']/method[@name='run' and count(parameter)=0]"
name="managedOverride">reabstract</attr>
<attr path="/api/package[@name='java.util.concurrent']/interface[@name='RunnableFuture']/method[@name='run' and count(parameter)=0]"
name="explicitInterface">global::Java.Lang.IRunnable</attr>
<attr path="/api/package[@name='java.util.concurrent']/class[@name='CompletableFuture']/method[@name='applyToEither'
or @name='applyToEitherAsync'
or @name='acceptEither'
or @name='acceptEitherAsync'
or @name='exceptionally'
or @name='handle'
or @name='handleAsync'
or @name='runAfterBoth'
or @name='runAfterBothAsync'
or @name='runAfterEither'
or @name='runAfterEitherAsync'
or @name='thenAccept'
or @name='thenAcceptAsync'
or @name='thenAcceptBoth'
or @name='thenAcceptBothAsync'
or @name='thenApply'
or @name='thenApplyAsync'
or @name='thenCombine'
or @name='thenCombineAsync'
or @name='thenCompose'
or @name='thenComposeAsync'
or @name='thenRun'
or @name='thenRunAsync'
or @name='whenComplete'
or @name='whenCompleteAsync'
]"
name="managedReturn">Java.Util.Concurrent.ICompletionStage</attr>
</metadata>
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ internal static bool IsNonStaticInnerClass (TypeDefinition? type, IMetadataResol
foreach (var baseType in type.GetBaseTypes (cache)) {
if (baseType == null)
continue;
if (!baseType.AnyCustomAttributes (typeof (RegisterAttribute)))
if (!HasTypeRegistrationAttribute (baseType))
continue;

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

return false;
}

static bool HasTypeRegistrationAttribute (TypeDefinition type)
{
if (!type.HasCustomAttributes)
return false;
return type.AnyCustomAttributes (typeof (RegisterAttribute)) ||
type.AnyCustomAttributes ("Java.Interop.JniTypeSignatureAttribute");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to cause any issues for XAJavaInterop1? Do we need to find a way to ensure that this is only used for JavaInterop1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to cause any issues for XAJavaInterop1?

No. JavaNativeTypeManager allows obtaining the Java Callable Wrapper type name from a System.Type or Mono.Cecil.TypeDefinition instance. jcw-gen already uses [JniTypeSignature], as does JavaNativeTypeManager:

var attr = type.CustomAttributes.FirstOrDefault (a =>
resolver.Resolve (a.AttributeType)
.FullName == "Java.Interop.JniTypeSignatureAttribute");

The change here is for IsNonStaticInnerClass(), which didn't yet check for [JniTypeSignature].

Do we need to find a way to ensure that this is only used for JavaInterop1?

No.

}
#endif // HAVE_CECIL

static string ToCrc64 (string value)
Expand Down
2 changes: 2 additions & 0 deletions tests/Java.Base-Tests/Java.Base/JavaVMFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ static partial void CreateJavaVM ()
["example/MyIntConsumer"] = typeof (MyIntConsumer),
["example/MyRunnable"] = typeof (MyRunnable),
[JavaInvoker.JniTypeName] = typeof (JavaInvoker),
[MyQueuedSynchronizer.JniTypeName] = typeof (MyQueuedSynchronizer),
["example/MyQueuedSynchronizer$MyQueuedSynchronizer_MyConditionObject"] = typeof (MyQueuedSynchronizer.MyConditionObject),
}
);
JniRuntime.SetCurrent (c);
Expand Down
36 changes: 36 additions & 0 deletions tests/Java.Base-Tests/Java.Base/NestedTypeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;

using Java.Interop;

using NUnit.Framework;

namespace Java.BaseTests {

[TestFixture]
public class NestedTypeTests : JavaVMFixture {

[Test]
public void Create_AbstractQueuedSynchronizer_ConditionObject ()
{
using var outer = new MyQueuedSynchronizer ();
using var inner = new MyQueuedSynchronizer.MyConditionObject (outer);
}
}

[JniTypeSignature (JniTypeName)]
class MyQueuedSynchronizer : Java.Util.Concurrent.Locks.AbstractQueuedSynchronizer {
internal const string JniTypeName = "example/MyQueuedSynchronizer";

public MyQueuedSynchronizer ()
{
}

public class MyConditionObject : Java.Util.Concurrent.Locks.AbstractQueuedSynchronizer.ConditionObject {

public MyConditionObject (MyQueuedSynchronizer outer)
: base (outer)
{
}
}
}
}
2 changes: 1 addition & 1 deletion tests/generator-Tests/Integration-Tests/NestedTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace generatortests
[TestFixture]
public class NestedTypes : BaseGeneratorTest
{
protected override bool TryJavaInterop1 => false;
protected override bool TryJavaInterop1 => true;

[Test]
public void GeneratedOK ()
Expand Down
10 changes: 10 additions & 0 deletions tests/generator-Tests/expected.ji/NestedTypes/Java.Lang.Object.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

#nullable restore
using System;
using System.Collections.Generic;
using Java.Interop;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

#nullable restore
using System;
using System.Collections.Generic;
using Java.Interop;
Expand All @@ -14,10 +24,39 @@ public abstract partial class Action : global::Java.Lang.Object {
[global::Java.Interop.JniTypeSignature ("xamarin/test/NotificationCompatBase$Action$Factory", GenerateJavaPeer=false)]
public partial interface IFactory : IJavaPeerable {
// 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']]"
[global::Java.Interop.JniMethodSignature ("build", "(I)Lxamarin/test/NotificationCompatBase$Action;")]
global::Xamarin.Test.NotificationCompatBase.Action Build (int p0);

}

[global::Java.Interop.JniTypeSignature ("xamarin/test/NotificationCompatBase$Action$Factory", GenerateJavaPeer=false)]
internal partial class IFactoryInvoker : global::Java.Lang.Object, IFactory {
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
get { return _members_xamarin_test_NotificationCompatBase_Action_Factory; }
}

static readonly JniPeerMembers _members_xamarin_test_NotificationCompatBase_Action_Factory = new JniPeerMembers ("xamarin/test/NotificationCompatBase$Action$Factory", typeof (IFactoryInvoker));

public IFactoryInvoker (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
{
}

public unsafe global::Xamarin.Test.NotificationCompatBase.Action Build (int p0)
{
const string __id = "build.(I)Lxamarin/test/NotificationCompatBase$Action;";
try {
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
__args [0] = new JniArgumentValue (p0);
var __rm = _members_xamarin_test_NotificationCompatBase_Action_Factory.InstanceMethods.InvokeAbstractObjectMethod (__id, this, __args);
return global::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<global::Xamarin.Test.NotificationCompatBase.Action> (ref __rm, JniObjectReferenceOptions.CopyAndDispose);
} finally {
}
}

}

static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/NotificationCompatBase$Action", typeof (Action));

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

// 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']]"
[global::Java.Interop.JniConstructorSignature ("(Lxamarin/test/NotificationCompatBase;)V")]
public unsafe InstanceInner (global::Xamarin.Test.NotificationCompatBase __self) : base (ref *InvalidJniObjectReference, JniObjectReferenceOptions.None)
{
string __id = "(L" + global::Android.Runtime.JNIEnv.GetJniName (GetType ().DeclaringType) + ";)V";
string __id = "(L" + global::Java.Interop.JniEnvironment.Runtime.TypeManager.GetTypeSignature (GetType ().DeclaringType).SimpleReference + ";)V";

if (PeerReference.IsValid)
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,11 @@ public string GetJniNestedDerivedSignature (CodeGenerationOptions opt)
StringBuilder sb = new StringBuilder ();
foreach (Parameter p in items) {
if (p.Name == "__self") {
sb.AppendFormat ("L\" + global::Android.Runtime.JNIEnv.GetJniName (GetType ().DeclaringType{0}) + \";", opt.NullForgivingOperator);
if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) {
sb.AppendFormat ("L\" + global::Java.Interop.JniEnvironment.Runtime.TypeManager.GetTypeSignature (GetType ().DeclaringType{0}).SimpleReference + \";", opt.NullForgivingOperator);
} else {
sb.AppendFormat ("L\" + global::Android.Runtime.JNIEnv.GetJniName (GetType ().DeclaringType{0}) + \";", opt.NullForgivingOperator);
}
continue;
}
sb.Append (p.JniType);
Expand Down