Skip to content

Commit 9f7a4be

Browse files
committed
[Java.Base, generator] Bind all of package java.lang
Context: bc5bcf4 Bind all classes and interfaces in the `java.lang` package. Alter Java array binding, so that instead of `IList<T>`, we get "direct" Java arrays, e.g. namespace Java.Lang { partial class Character { // Previous/Xamarin.Android-like public static int CodePointAt (IList<char>? a, int index); // New/Desktop public static int CodePointAt (JavaCharArray? a, int index); } } Rationale: it *allows* for more efficient JVM :: .NET array copying, by making copies explicit (to the dev), not implicit. We can add an implicit conversion from e.g. `IEnumerable<char>` to `JavaCharArray` in the future, if deemed useful. This also impacts method return types, properties, and fields. `java.lang.String` is no longer bound as `System.String`. This might be a mistake/reconsidered, but the current rationale is that bindings should "more directly" mirror the underlying Java API. We can provide method overloads or implicit conversions to make C# integration "nicer", e.g. we have an implicit conversion from `System.String` to `Java.Lang.String` for now. Rename `.toString()` to `.ToJavaString()` -- which returns `Java.Lang.String` (see previous paragraph) -- and provide `Java.Lang.Object.ToString()` and `Java.Lang.Throwable.ToString()` overrides which call `.ToJavaString()`. Bind the `java.lang.module` package in the namespace `Java.Lang.Modules`. This is to avoid a type/namespace conflict with `java.lang.Module`, bound as `Java.Lang.Module`. Continue updating `generator` to remove "Android-isms". Update `Java.Base.csproj` to ignore [warning CS0108][0]: Java.Lang.Reflect.IAnnotatedArrayType.cs(15,45): warning CS0108: 'IAnnotatedArrayType.AnnotatedOwnerType' hides inherited member 'IAnnotatedType.AnnotatedOwnerType'. Use the new keyword if hiding was intended. The problem here is that we have: public partial interface IAnnotatedType { // Contains default interface method virtual unsafe IAnnotatedType? AnnotatedOwnerType => …; } public partial interface IAnnotatedArrayType : IAnnotatedType { // Contains *no* method body; re-abstracted IAnnotatedType? AnnotatedOwnerType {get;} } I'm not sure how to properly represent this. `managedOverride` metadata (5a0e37e) doesn't seem useful to "re-abstract" a default interface member. Update `Java.Base.targets` to use `generator --global`. This is so that `java.lang.System` can be bound as `Java.Lang.System` without causing various C# compilation errors due to type lookup. (Compare to Xamarin.Android's `Java.Lang.JavaSystem`, which got a `Java*` prefix to avoid these compilation errors.) Update `JavaInteropCodeGeneratorTests.CreateOptions()` so that C# features such as default interface methods and nested interface types are enabled within the unit tests. Also add an explicit entry for `java.lang.String` so that unit tests which assume that `java.lang.String` exists will pass, as the "normal" Xamarin.Android- style `java.lang.String` :: `string` binding is currently skipped. Update `tests/generator-Tests/**/*.xml` so that `java.lang.String` is present within the `api.xml` when they also use `java.lang.String` as a type "elsewhere" (method parameter/return type, field type). This is to reduce reliance on the builtin bindings, which JavaInterop1 bindings try to minimize. TODO: * When `generator --codegen-target=JavaInterop1` is used, all the language features should also be enabled by default. * Certain Java Annotation-related types aren't bound in JavaInterop1, vs. XAJavaInterop1. Revisit this. * "Revisit" use of `JNIEnv.ToLocalJniHandle()` in Xamarin.Android bindings, and it's outright removal in JavaInterop1 bindings. @jonpryor *thinks* the `JNIENv.ToLocalJniHandle(v)` was introduced "in case" `v` would be collected by the GC "during" a JNI call. Use of `GC.KeepAlive()` (1f21f38, da73d6a), would be a better solution, but also requires auditing `generator` output. * Bind the rest of `java.base.jmod` (bc5bcf4). [0]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0108
1 parent 05bfece commit 9f7a4be

File tree

112 files changed

+1186
-352
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+1186
-352
lines changed

src/Java.Base/Java.Base.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
<TargetFrameworks>net6.0</TargetFrameworks>
55
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
66
<Nullable>enable</Nullable>
7-
<NoWarn>$(NoWarn);8764</NoWarn>
7+
<!-- TODO: CS0108 is due to e.g. interfaces re-abstracting default interface methods -->
8+
<NoWarn>$(NoWarn);8764;CS0108</NoWarn>
89
<Version>$(JICoreLibVersion)</Version>
910
</PropertyGroup>
1011

src/Java.Base/Java.Base.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<MakeDir Directories="$(IntermediateOutputPath)mcw" />
4545
<PropertyGroup>
4646
<Generator>"$(GeneratorPath)"</Generator>
47-
<_GenFlags>--public</_GenFlags>
47+
<_GenFlags>--public --global</_GenFlags>
4848
<_Out>-o "$(IntermediateOutputPath)mcw"</_Out>
4949
<_Codegen>--codegen-target=JavaInterop1</_Codegen>
5050
<_Fixup>--fixup=Transforms/Metadata.xml</_Fixup>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace Java.Lang {
2+
3+
public static partial class ICharSequenceExtensions {
4+
5+
public static ICharSequence[]? ToCharSequenceArray (this string?[]? values)
6+
{
7+
if (values == null) {
8+
return null;
9+
}
10+
var array = new ICharSequence [values.Length];
11+
for (int i = 0; i < values.Length; ++i) {
12+
if (values [i] == null) {
13+
continue;
14+
}
15+
array [i] = new Java.Lang.String (values [i]);
16+
}
17+
return array;
18+
}
19+
}
20+
}

src/Java.Base/Java.Lang/Object.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,11 @@ public Object (ref JniObjectReference reference, JniObjectReferenceOptions optio
1010
: base (ref reference, options)
1111
{
1212
}
13+
14+
public override string? ToString ()
15+
{
16+
var s = ToJavaString ();
17+
return JniEnvironment.Strings.ToString (s?.PeerReference ?? default);
18+
}
1319
}
1420
}

src/Java.Base/Java.Lang/String.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using Java.Interop;
5+
6+
namespace Java.Lang {
7+
public partial class String : IEnumerable, IEnumerable<char> {
8+
9+
public unsafe String (string? value)
10+
: base (ref *InvalidJniObjectReference, JniObjectReferenceOptions.None)
11+
{
12+
const string __id = "(Ljava/lang/String;)V";
13+
14+
if (PeerReference.IsValid)
15+
return;
16+
17+
var lref = JniEnvironment.Strings.NewString (value);
18+
19+
try {
20+
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
21+
__args [0] = new JniArgumentValue (lref);
22+
var __r = _members.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), __args);
23+
Construct (ref __r, JniObjectReferenceOptions.CopyAndDispose);
24+
_members.InstanceMethods.FinishCreateInstance (__id, this, __args);
25+
} finally {
26+
JniObjectReference.Dispose (ref lref);
27+
global::System.GC.KeepAlive (value);
28+
}
29+
}
30+
31+
public static explicit operator string? (Java.Lang.String? value)
32+
{
33+
if (value == null) {
34+
return null;
35+
}
36+
return JniEnvironment.Strings.ToString (value.PeerReference);
37+
}
38+
39+
public static implicit operator Java.Lang.String? (string? value)
40+
{
41+
if (value == null) {
42+
return null;
43+
}
44+
return new Java.Lang.String (value);
45+
}
46+
}
47+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
namespace Java.Lang {
6+
partial class StringBuffer : IEnumerable, IEnumerable<char> {
7+
}
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
namespace Java.Lang {
6+
partial class StringBuilder : IEnumerable, IEnumerable<char> {
7+
}
8+
}

src/Java.Base/Java.Lang/Throwable.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,11 @@ public Throwable (ref JniObjectReference reference, JniObjectReferenceOptions op
1010
: base (ref reference, options)
1111
{
1212
}
13+
14+
public override string? ToString ()
15+
{
16+
var s = ToJavaString ();
17+
return JniEnvironment.Strings.ToString (s?.PeerReference ?? default);
18+
}
1319
}
1420
}

src/Java.Base/Transforms/Metadata.xml

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,27 @@
22
<!-- For now, just bind java.lang.* -->
33
<remove-node path="//api/package[not(starts-with(@name, 'java.lang'))]" />
44

5-
<!-- For now, just bind Class, Object, Throwable -->
6-
<remove-node path="//api/package/interface" />
7-
<remove-node path="//api/package/class[not(@name = 'Object'
8-
or @name = 'BootstrapMethodError'
9-
or @name = 'Class'
10-
or @name = 'Math'
11-
or @name = 'Number'
12-
or @name = 'Throwable'
13-
)]"
14-
/>
5+
<!-- Type / Namespace conflicts -->
6+
<ns-replace source="java.lang.module" replacement="Java.Lang.Modules" />
157

16-
<attr path="/api/package[@name='java.lang']/class[@name='Object']/method[@name='finalize']" name="managedName">JavaFinalize</attr>
8+
<!-- Bind `Object.finalize()` as `Object.JavaFinalize()` -->
9+
<attr path="/api/package[@name='java.lang']//method[@name='finalize' and count(parameter)=0]" name="managedName">JavaFinalize</attr>
10+
<!-- warning CS0672: Member 'Enum.JavaFinalize()' overrides obsolete member 'Object.JavaFinalize()'. Add the Obsolete attribute to 'Enum.JavaFinalize()'. -->
11+
<attr path="/api/package[@name='java.lang']/class[@name='Enum']/method[@name='finalize' and count(parameter)=0]" name="deprecated">deprecated</attr>
12+
13+
<!-- Bind `Object.toString()` as `Object.ToJavaString()`-->
14+
<attr path="//method[@name='toString' and count(parameter)=0]" name="managedName">ToJavaString</attr>
15+
<attr path="/api/package[@name='java.lang']/class[@name='Object']/method[@name='toString']" name="managedOverride">virtual</attr>
16+
<attr path="/api/package[@name='java.lang']/class[@name='Throwable']/method[@name='toString']" name="managedOverride">virtual</attr>
17+
18+
<!-- AbstractStringBuilder is package-private; fixity fix -->
19+
<remove-node path="//api/package[@name='java.lang']/class[@name='AbstractStringBuilder']" />
20+
21+
<attr path="/api/package[@name='java.lang']/class[@name='StringBuilder']" name="extends">java.lang.Object</attr>
22+
<remove-node path="//api/package[@name='java.lang']/class[@name='StringBuilder']/method[@jni-return='Ljava/lang/AbstractStringBuilder;']" />
23+
<remove-node path="//api/package[@name='java.lang']/class[@name='StringBuilder']/method[@jni-return='Ljava/lang/Appendable;']" />
24+
25+
<attr path="/api/package[@name='java.lang']/class[@name='StringBuffer']" name="extends">java.lang.Object</attr>
26+
<remove-node path="//api/package[@name='java.lang']/class[@name='StringBuffer']/method[@jni-return='Ljava/lang/AbstractStringBuilder;']" />
27+
<remove-node path="//api/package[@name='java.lang']/class[@name='StringBuffer']/method[@jni-return='Ljava/lang/Appendable;']" />
1728
</metadata>

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ namespace generatortests
66
[TestFixture]
77
public class Arrays : BaseGeneratorTest
88
{
9-
protected override bool TryJavaInterop1 => false;
10-
119
[Test]
1210
public void GeneratedOK ()
1311
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public static Assembly Compile (Xamarin.Android.Binder.CodeGeneratorOptions opti
7171
var references = referencePaths.Select (p => MetadataReference.CreateFromFile (p)).ToArray ();
7272

7373
string testCommandLine =
74-
$"csc \"-out:{Path.GetFileName (assemblyFileName)}\" " +
74+
$"csc -noconfig -nostdlib \"-out:{Path.GetFileName (assemblyFileName)}\" " +
7575
$"-unsafe -t:library " +
7676
string.Join (" ", preprocessorSymbols.Select (p => $"\"-define:{p}\"")) + " " +
7777
string.Join (" ", referencePaths.Select (p => $"\"-r:{p}\"")) + " " +

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

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,21 @@ public partial class MyClass {
2424
}
2525

2626
// Metadata.xml XPath constructor reference: path="/api/package[@name='java.code']/class[@name='MyClass']/constructor[@name='MyClass' and count(parameter)=1 and parameter[1][@type='java.lang.String']]"
27-
unsafe MyClass (string p0) : base (ref *InvalidJniObjectReference, JniObjectReferenceOptions.None)
27+
unsafe MyClass (Java.Lang.String? p0) : base (ref *InvalidJniObjectReference, JniObjectReferenceOptions.None)
2828
{
2929
const string __id = "(Ljava/lang/String;)V";
3030

3131
if (PeerReference.IsValid)
3232
return;
3333

34-
var native_p0 = global::Java.Interop.JniEnvironment.Strings.NewString (p0);
3534
try {
3635
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
37-
__args [0] = new JniArgumentValue (native_p0);
36+
__args [0] = new JniArgumentValue (p0);
3837
var __r = _members.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), __args);
3938
Construct (ref __r, JniObjectReferenceOptions.CopyAndDispose);
4039
_members.InstanceMethods.FinishCreateInstance (__id, this, __args);
4140
} finally {
42-
global::Java.Interop.JniObjectReference.Dispose (ref native_p0);
41+
global::System.GC.KeepAlive (p0);
4342
}
4443
}
4544

@@ -65,26 +64,24 @@ public partial class MyClass {
6564
}
6665
}
6766

68-
public virtual unsafe string Key {
67+
public virtual unsafe Java.Lang.String? Key {
6968
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/class[@name='MyClass']/method[@name='get_Key' and count(parameter)=0]"
7069
get {
7170
const string __id = "get_Key.()Ljava/lang/String;";
7271
try {
7372
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, null);
74-
return global::Java.Interop.JniEnvironment.Strings.ToString (ref __rm, JniObjectReferenceOptions.CopyAndDispose);
73+
return __rm;
7574
} finally {
7675
}
7776
}
7877
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/class[@name='MyClass']/method[@name='set_Key' and count(parameter)=1 and parameter[1][@type='java.lang.String']]"
7978
set {
8079
const string __id = "set_Key.(Ljava/lang/String;)V";
81-
var native_value = global::Java.Interop.JniEnvironment.Strings.NewString (value);
8280
try {
8381
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
84-
__args [0] = new JniArgumentValue (native_value);
82+
__args [0] = new JniArgumentValue (value);
8583
_members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args);
8684
} finally {
87-
global::Java.Interop.JniObjectReference.Dispose (ref native_value);
8885
}
8986
}
9087
}
@@ -120,27 +117,26 @@ public partial class MyClass {
120117
}
121118

122119
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/class[@name='MyClass']/method[@name='GetCountForKey' and count(parameter)=1 and parameter[1][@type='java.lang.String']]"
123-
public virtual unsafe int GetCountForKey (string key)
120+
public virtual unsafe int GetCountForKey (Java.Lang.String? key)
124121
{
125122
const string __id = "GetCountForKey.(Ljava/lang/String;)I";
126-
var native_key = global::Java.Interop.JniEnvironment.Strings.NewString (key);
127123
try {
128124
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
129-
__args [0] = new JniArgumentValue (native_key);
125+
__args [0] = new JniArgumentValue (key);
130126
var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, __args);
131127
return __rm;
132128
} finally {
133-
global::Java.Interop.JniObjectReference.Dispose (ref native_key);
129+
global::System.GC.KeepAlive (key);
134130
}
135131
}
136132

137133
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/class[@name='MyClass']/method[@name='Key' and count(parameter)=0]"
138-
public virtual unsafe string Key ()
134+
public virtual unsafe Java.Lang.String? Key ()
139135
{
140136
const string __id = "Key.()Ljava/lang/String;";
141137
try {
142138
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, null);
143-
return global::Java.Interop.JniEnvironment.Strings.ToString (ref __rm, JniObjectReferenceOptions.CopyAndDispose);
139+
return __rm;
144140
} finally {
145141
}
146142
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ internal sealed partial class AnimatorListenerImplementor : global::Java.Lang.Ob
5757
}
5858

5959
#pragma warning disable 0649
60-
public EventHandler<AnimationEndEventArgs> OnAnimationEndHandler;
60+
public EventHandler<AnimationEndEventArgs>? OnAnimationEndHandler;
6161
#pragma warning restore 0649
6262

6363
public bool OnAnimationEnd (int param1)
@@ -71,7 +71,7 @@ internal sealed partial class AnimatorListenerImplementor : global::Java.Lang.Ob
7171
}
7272

7373
#pragma warning disable 0649
74-
public EventHandler<AnimationEndEventArgs> OnAnimationEndHandler;
74+
public EventHandler<AnimationEndEventArgs>? OnAnimationEndHandler;
7575
#pragma warning restore 0649
7676

7777
public bool OnAnimationEnd (int param1, int param2)
Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,8 @@
1-
[Register ("java/code/IMyInterface", DoNotGenerateAcw=true)]
2-
public abstract class MyInterface : Java.Lang.Object {
3-
internal MyInterface ()
4-
{
5-
}
6-
7-
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='StaticMethod' and count(parameter)=0]"
8-
public static unsafe void StaticMethod ()
9-
{
10-
const string __id = "StaticMethod.()V";
11-
try {
12-
_members.StaticMethods.InvokeVoidMethod (__id, null);
13-
} finally {
14-
}
15-
}
16-
17-
static readonly JniPeerMembers _members = new JniPeerMembers ("java/code/IMyInterface", typeof (MyInterface));
18-
19-
}
20-
21-
[Register ("java/code/IMyInterface", DoNotGenerateAcw=true)]
22-
[global::System.Obsolete ("Use the 'MyInterface' type. This type will be removed in a future release.", error: true)]
23-
public abstract class MyInterfaceConsts : MyInterface {
24-
private MyInterfaceConsts ()
25-
{
26-
}
27-
28-
}
29-
301
// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']"
312
[global::Java.Interop.JniTypeSignature ("java/code/IMyInterface", GenerateJavaPeer=false)]
323
public partial interface IMyInterface : IJavaPeerable {
4+
private static readonly JniPeerMembers _members = new JniPeerMembers ("java/code/IMyInterface", typeof (IMyInterface), isInterface: true);
5+
336
int Count {
347
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Count' and count(parameter)=0]"
358
get;
@@ -38,7 +11,7 @@ public partial interface IMyInterface : IJavaPeerable {
3811
set;
3912
}
4013

41-
string Key {
14+
Java.Lang.String? Key {
4215
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Key' and count(parameter)=0]"
4316
get;
4417

@@ -54,13 +27,45 @@ public partial interface IMyInterface : IJavaPeerable {
5427
set;
5528
}
5629

30+
static unsafe int StaticCount {
31+
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_StaticCount' and count(parameter)=0]"
32+
get {
33+
const string __id = "get_StaticCount.()I";
34+
try {
35+
var __rm = _members.StaticMethods.InvokeInt32Method (__id, null);
36+
return __rm;
37+
} finally {
38+
}
39+
}
40+
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_StaticCount' and count(parameter)=1 and parameter[1][@type='int']]"
41+
set {
42+
const string __id = "set_StaticCount.(I)V";
43+
try {
44+
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
45+
__args [0] = new JniArgumentValue (value);
46+
_members.StaticMethods.InvokeVoidMethod (__id, __args);
47+
} finally {
48+
}
49+
}
50+
}
51+
5752
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='GetCountForKey' and count(parameter)=1 and parameter[1][@type='java.lang.String']]"
58-
int GetCountForKey (string key);
53+
int GetCountForKey (Java.Lang.String? key);
5954

6055
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='Key' and count(parameter)=0]"
61-
string Key ();
56+
Java.Lang.String? Key ();
6257

6358
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='AbstractMethod' and count(parameter)=0]"
6459
void AbstractMethod ();
6560

61+
// Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='StaticMethod' and count(parameter)=0]"
62+
public static unsafe void StaticMethod ()
63+
{
64+
const string __id = "StaticMethod.()V";
65+
try {
66+
_members.StaticMethods.InvokeVoidMethod (__id, null);
67+
} finally {
68+
}
69+
}
70+
6671
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
public delegate int MyIGetCountForKeyHandler (string key);
1+
public delegate int MyIGetCountForKeyHandler (Java.Lang.String? key);
22

0 commit comments

Comments
 (0)