Skip to content

Commit 3fcce74

Browse files
authored
[Java.Interop.{Dynamic,Export}] Nullable Reference Type support (#980)
Annotate `Java.Interop.Dynamic.dll` and `Java.Interop.Export.dll` to support C#8 [Nullable Reference Types][0]. [0]: https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references
1 parent 843f3c7 commit 3fcce74

File tree

13 files changed

+160
-130
lines changed

13 files changed

+160
-130
lines changed

src/Java.Interop.Dynamic/Java.Interop.Dynamic.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
<Project Sdk="Microsoft.NET.Sdk">
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
5+
<LangVersion>8.0</LangVersion>
56
<ProjectGuid>{AD4468F8-8883-434B-9D4C-E1801BB3B52A}</ProjectGuid>
7+
<Nullable>enable</Nullable>
68
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
79
<SignAssembly>true</SignAssembly>
810
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile>

src/Java.Interop.Dynamic/Java.Interop.Dynamic/DynamicJavaClass.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ protected virtual void Dispose (bool disposing)
4242
return;
4343

4444
info.Dispose ();
45-
info = null;
45+
info = null!;
4646
disposed = true;
4747
}
4848

src/Java.Interop.Dynamic/Java.Interop.Dynamic/DynamicJavaInstance.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public DynamicJavaInstance (IJavaPeerable value)
2323

2424
Value = value;
2525

26-
var type = JniEnvironment.Types.GetJniTypeNameFromInstance (value.PeerReference);
26+
var type = JniEnvironment.Types.GetJniTypeNameFromInstance (value.PeerReference) ??
27+
throw new InvalidOperationException ($"Could not get JniType from value `{value}`.");
2728
klass = JavaClassInfo.GetClassInfo (type);
2829
}
2930

@@ -53,8 +54,8 @@ protected virtual void Dispose (bool disposing)
5354
}
5455

5556
disposed = true;
56-
Value = null;
57-
klass = null;
57+
Value = null!;
58+
klass = null!;
5859
}
5960

6061
DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject (Expression parameter)

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JavaClassInfo.cs

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static JavaClassInfo ()
6868
public static JavaClassInfo GetClassInfo (string jniClassName)
6969
{
7070
lock (Classes) {
71-
JavaClassInfo info = _GetClassInfo (jniClassName);
71+
JavaClassInfo? info = _GetClassInfo (jniClassName);
7272
if (info != null) {
7373
Interlocked.Increment (ref info.RefCount);
7474
return info;
@@ -80,7 +80,7 @@ public static JavaClassInfo GetClassInfo (string jniClassName)
8080
}
8181
}
8282

83-
static JavaClassInfo _GetClassInfo (string jniClassName)
83+
static JavaClassInfo? _GetClassInfo (string jniClassName)
8484
{
8585
lock (Classes) {
8686
WeakReference value;
@@ -114,19 +114,19 @@ public static int GetClassInfoCount (string jniClassName)
114114

115115
int RefCount = 1;
116116

117-
List<JavaConstructorInfo> constructors;
118-
Dictionary<string, List<JavaFieldInfo>> fields;
119-
Dictionary<string, List<JavaMethodInfo>> methods;
117+
List<JavaConstructorInfo>? constructors;
118+
Dictionary<string, List<JavaFieldInfo>>? fields;
119+
Dictionary<string, List<JavaMethodInfo>>? methods;
120120

121-
public List<JavaConstructorInfo> Constructors {
121+
public List<JavaConstructorInfo>? Constructors {
122122
get {return LookupConstructors ();}
123123
}
124124

125-
public Dictionary<string, List<JavaFieldInfo>> Fields {
125+
public Dictionary<string, List<JavaFieldInfo>>? Fields {
126126
get {return LookupFields ();}
127127
}
128128

129-
public Dictionary<string, List<JavaMethodInfo>> Methods {
129+
public Dictionary<string, List<JavaMethodInfo>>? Methods {
130130
get {return LookupMethods ();}
131131
}
132132

@@ -152,7 +152,7 @@ public void Dispose ()
152152
foreach (var name in methods.Keys.ToList ()) {
153153
foreach (var info in methods [name])
154154
info.Dispose ();
155-
methods [name] = null;
155+
methods.Remove (name);
156156
}
157157
}
158158

@@ -171,7 +171,7 @@ internal static JniObjectReference GetConstructorParameters (JniObjectReference
171171
return JniEnvironment.InstanceMethods.CallObjectMethod (method, Constructor_getParameterTypes);
172172
}
173173

174-
List<JavaConstructorInfo> LookupConstructors ()
174+
List<JavaConstructorInfo>? LookupConstructors ()
175175
{
176176
if (Members == null)
177177
return null;
@@ -199,7 +199,7 @@ List<JavaConstructorInfo> LookupConstructors ()
199199
}
200200
}
201201

202-
Dictionary<string, List<JavaFieldInfo>> LookupFields ()
202+
Dictionary<string, List<JavaFieldInfo>>? LookupFields ()
203203
{
204204
if (Members == null)
205205
return null;
@@ -216,17 +216,18 @@ Dictionary<string, List<JavaFieldInfo>> LookupFields ()
216216
for (int i = 0; i < len; ++i) {
217217
var field = JniEnvironment.Arrays.GetObjectArrayElement (fields, i);
218218
var n_name = JniEnvironment.InstanceMethods.CallObjectMethod (field, Field_getName);
219-
var name = JniEnvironment.Strings.ToString (ref n_name, JniObjectReferenceOptions.CopyAndDispose);
220219
var isStatic = IsStatic (field);
220+
var name = JniEnvironment.Strings.ToString (ref n_name, JniObjectReferenceOptions.CopyAndDispose) ??
221+
throw new InvalidOperationException ($"Could not determine field name at index {i}!");
221222

222-
List<JavaFieldInfo> overloads;
223-
if (!Fields.TryGetValue (name, out overloads))
224-
Fields.Add (name, overloads = new List<JavaFieldInfo> ());
223+
List<JavaFieldInfo>? overloads = null;
224+
if (!Fields?.TryGetValue (name, out overloads) ?? false)
225+
Fields!.Add (name, overloads = new List<JavaFieldInfo> ());
225226

226227
var n_type = JniEnvironment.InstanceMethods.CallObjectMethod (field, Field_getType);
227228
using (var type = new JniType (ref n_type, JniObjectReferenceOptions.CopyAndDispose)) {
228229
var sig = JniTypeSignature.Parse (type.Name);
229-
overloads.Add (new JavaFieldInfo (Members, name + "." + sig.QualifiedReference, isStatic));
230+
overloads?.Add (new JavaFieldInfo (Members, name + "." + sig.QualifiedReference, isStatic));
230231
}
231232

232233
JniObjectReference.Dispose (ref field);
@@ -239,7 +240,7 @@ Dictionary<string, List<JavaFieldInfo>> LookupFields ()
239240
}
240241
}
241242

242-
Dictionary<string, List<JavaMethodInfo>> LookupMethods ()
243+
Dictionary<string, List<JavaMethodInfo>>? LookupMethods ()
243244
{
244245
if (Members == null)
245246
return null;
@@ -256,19 +257,20 @@ Dictionary<string, List<JavaMethodInfo>> LookupMethods ()
256257
for (int i = 0; i < len; ++i) {
257258
var method = JniEnvironment.Arrays.GetObjectArrayElement (methods, i);
258259
var n_name = JniEnvironment.InstanceMethods.CallObjectMethod (method, Method_getName);
259-
var name = JniEnvironment.Strings.ToString (ref n_name, JniObjectReferenceOptions.CopyAndDispose);
260260
var isStatic = IsStatic (method);
261+
var name = JniEnvironment.Strings.ToString (ref n_name, JniObjectReferenceOptions.CopyAndDispose) ??
262+
throw new InvalidOperationException ($"Could not determine method name at index {i}!");
261263

262-
List<JavaMethodInfo> overloads;
263-
if (!Methods.TryGetValue (name, out overloads))
264-
Methods.Add (name, overloads = new List<JavaMethodInfo> ());
264+
List<JavaMethodInfo>? overloads = null;
265+
if (!Methods?.TryGetValue (name, out overloads) ?? false)
266+
Methods!.Add (name, overloads = new List<JavaMethodInfo> ());
265267

266268
var nrt = JniEnvironment.InstanceMethods.CallObjectMethod (method, Method_getReturnType);
267269
var rt = new JniType (ref nrt, JniObjectReferenceOptions.CopyAndDispose);
268270
var m = new JavaMethodInfo (Members, method, name, isStatic) {
269271
ReturnType = rt,
270272
};
271-
overloads.Add (m);
273+
overloads?.Add (m);
272274
JniObjectReference.Dispose (ref method);
273275
}
274276
} finally {
@@ -286,11 +288,11 @@ static bool IsStatic (JniObjectReference member)
286288
return (s & JavaModifiers.Static) == JavaModifiers.Static;
287289
}
288290

289-
internal unsafe bool TryInvokeMember (IJavaPeerable self, JavaMethodBase[] overloads, DynamicMetaObject[] args, out object value)
291+
internal unsafe bool TryInvokeMember (IJavaPeerable self, JavaMethodBase[] overloads, DynamicMetaObject[] args, out object? value)
290292
{
291293
value = null;
292-
var vms = (List<JniValueMarshaler>) null;
293-
var states = (JniValueMarshalerState[]) null;
294+
var vms = (List<JniValueMarshaler>?) null;
295+
var states = (JniValueMarshalerState[]?) null;
294296

295297
var jtypes = GetJniTypes (args);
296298
try {
@@ -313,18 +315,20 @@ internal unsafe bool TryInvokeMember (IJavaPeerable self, JavaMethodBase[] overl
313315
}
314316
finally {
315317
for (int i = 0; vms != null && i < vms.Count; ++i) {
318+
if (states == null) {
319+
continue;
320+
}
316321
vms [i].DestroyArgumentState (args [i].Value, ref states [i]);
317322
}
318323
for (int i = 0; i < jtypes.Count; ++i) {
319-
if (jtypes [i] != null)
320-
jtypes [i].Dispose ();
324+
jtypes [i]?.Dispose ();
321325
}
322326
}
323327
}
324328

325-
static List<JniType> GetJniTypes (DynamicMetaObject[] args)
329+
static List<JniType?> GetJniTypes (DynamicMetaObject[] args)
326330
{
327-
var r = new List<JniType> (args.Length);
331+
var r = new List<JniType?> (args.Length);
328332
var vm = JniEnvironment.Runtime;
329333
foreach (var a in args) {
330334
try {

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JavaConstructorInfo.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,17 @@ protected override string JniReturnType {
3636
get {return "V";}
3737
}
3838

39-
public override unsafe object Invoke (IJavaPeerable self, JniArgumentValue* arguments)
39+
public override unsafe object? Invoke (IJavaPeerable? self, JniArgumentValue* arguments)
4040
{
41+
var signature = JniSignature ?? throw new InvalidOperationException ("No JniSignature!");
4142
if (self == null) {
42-
var h = members.InstanceMethods.StartCreateInstance (JniSignature, typeof (JavaInstanceProxy), arguments);
43+
var h = members.InstanceMethods.StartCreateInstance (signature, typeof (JavaInstanceProxy), arguments);
4344
self = JniEnvironment.Runtime.ValueManager.GetValue<JavaInstanceProxy> (ref h, JniObjectReferenceOptions.CopyAndDispose);
45+
if (self == null) {
46+
throw new InvalidOperationException ($"Could not create instance of {members.ManagedPeerType}!");
47+
}
4448
}
45-
members.InstanceMethods.FinishCreateInstance (JniSignature, self, arguments);
49+
members.InstanceMethods.FinishCreateInstance (signature, self, arguments);
4650
return new DynamicJavaInstance (self);
4751
}
4852
}

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JavaFieldInfo.cs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public override string Name {
3838
}
3939
}
4040

41-
public object GetValue (IJavaPeerable self)
41+
public object? GetValue (IJavaPeerable self)
4242
{
4343
AssertSelf (self);
4444

@@ -59,7 +59,7 @@ void AssertSelf (IJavaPeerable self)
5959
"self");
6060
}
6161

62-
object GetStaticValue ()
62+
object? GetStaticValue ()
6363
{
6464
var n = GetSignatureStartIndex ();
6565
switch (JniSignature [n + 1]) {
@@ -80,7 +80,7 @@ object GetStaticValue ()
8080
}
8181
}
8282

83-
object GetInstanceValue (IJavaPeerable self)
83+
object? GetInstanceValue (IJavaPeerable self)
8484
{
8585
var n = GetSignatureStartIndex ();
8686
switch (JniSignature [n + 1]) {
@@ -110,7 +110,7 @@ int GetSignatureStartIndex ()
110110
return n;
111111
}
112112

113-
public void SetValue (IJavaPeerable self, object value)
113+
public void SetValue (IJavaPeerable self, object? value)
114114
{
115115
AssertSelf (self);
116116

@@ -121,18 +121,18 @@ public void SetValue (IJavaPeerable self, object value)
121121
}
122122
}
123123

124-
void SetStaticValue (object value)
124+
void SetStaticValue (object? value)
125125
{
126126
var n = GetSignatureStartIndex ();
127127
switch (JniSignature [n + 1]) {
128-
case 'Z': members.StaticFields.SetValue (JniSignature, (bool) value); break;
129-
case 'B': members.StaticFields.SetValue (JniSignature, (byte) value); break;
130-
case 'C': members.StaticFields.SetValue (JniSignature, (char) value); break;
131-
case 'S': members.StaticFields.SetValue (JniSignature, (short) value); break;
132-
case 'I': members.StaticFields.SetValue (JniSignature, (int) value); break;
133-
case 'J': members.StaticFields.SetValue (JniSignature, (long) value); break;
134-
case 'F': members.StaticFields.SetValue (JniSignature, (float) value); break;
135-
case 'D': members.StaticFields.SetValue (JniSignature, (double) value); break;
128+
case 'Z': members.StaticFields.SetValue (JniSignature, (bool) value!); break;
129+
case 'B': members.StaticFields.SetValue (JniSignature, (byte) value!); break;
130+
case 'C': members.StaticFields.SetValue (JniSignature, (char) value!); break;
131+
case 'S': members.StaticFields.SetValue (JniSignature, (short) value!); break;
132+
case 'I': members.StaticFields.SetValue (JniSignature, (int) value!); break;
133+
case 'J': members.StaticFields.SetValue (JniSignature, (long) value!); break;
134+
case 'F': members.StaticFields.SetValue (JniSignature, (float) value!); break;
135+
case 'D': members.StaticFields.SetValue (JniSignature, (double) value!); break;
136136
case 'L':
137137
case '[':
138138
if (value == null) {
@@ -152,18 +152,18 @@ void SetStaticValue (object value)
152152
}
153153
}
154154

155-
void SetInstanceValue (IJavaPeerable self, object value)
155+
void SetInstanceValue (IJavaPeerable self, object? value)
156156
{
157157
var n = GetSignatureStartIndex ();
158158
switch (JniSignature [n + 1]) {
159-
case 'Z': members.InstanceFields.SetValue (JniSignature, self, (bool) value); break;
160-
case 'B': members.InstanceFields.SetValue (JniSignature, self, (byte) value); break;
161-
case 'C': members.InstanceFields.SetValue (JniSignature, self, (char) value); break;
162-
case 'S': members.InstanceFields.SetValue (JniSignature, self, (short) value); break;
163-
case 'I': members.InstanceFields.SetValue (JniSignature, self, (int) value); break;
164-
case 'J': members.InstanceFields.SetValue (JniSignature, self, (long) value); break;
165-
case 'F': members.InstanceFields.SetValue (JniSignature, self, (float) value); break;
166-
case 'D': members.InstanceFields.SetValue (JniSignature, self, (double) value); break;
159+
case 'Z': members.InstanceFields.SetValue (JniSignature, self, (bool) value!); break;
160+
case 'B': members.InstanceFields.SetValue (JniSignature, self, (byte) value!); break;
161+
case 'C': members.InstanceFields.SetValue (JniSignature, self, (char) value!); break;
162+
case 'S': members.InstanceFields.SetValue (JniSignature, self, (short) value!); break;
163+
case 'I': members.InstanceFields.SetValue (JniSignature, self, (int) value!); break;
164+
case 'J': members.InstanceFields.SetValue (JniSignature, self, (long) value!); break;
165+
case 'F': members.InstanceFields.SetValue (JniSignature, self, (float) value!); break;
166+
case 'D': members.InstanceFields.SetValue (JniSignature, self, (double) value!); break;
167167
case 'L':
168168
case '[':
169169
if (value == null) {

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JavaMemberInfo.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ protected virtual void Dispose (bool disposing)
2020
{
2121
}
2222

23-
protected static object ToReturnValue (ref JniObjectReference handle, string signature, int n)
23+
protected static object? ToReturnValue (ref JniObjectReference handle, string signature, int n)
2424
{
2525
var instance = JniEnvironment.Runtime.ValueManager.GetValue<IJavaPeerable> (ref handle, JniObjectReferenceOptions.CopyAndDispose);
26+
if (instance == null) {
27+
return null;
28+
}
2629
switch (signature [n]) {
2730
case 'L':
2831
return new DynamicJavaInstance (instance);

0 commit comments

Comments
 (0)