Skip to content

Commit 08fb6bb

Browse files
committed
[Java.Interop] GetSimpleReferences():fallback for GetTypeSignatures()
Context: dotnet/android#9768 dotnet/android#9768 attempts to add types from `Java.Interop.dll` to the .NET for Android typemaps, in order to fix Debug warnings like: I monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Java.Interop.ManagedPeer, Java.Interop' Unfortunately, this causes the assertion: AssertGetJniTypeInfoForType (typeof (JavaArray<JavaObject>), "[Ljava/lang/Object;", false, 1); within `Java.InteropTests.JniTypeManagerTests.GetTypeSignature_Type()` to fail: Expected string length 19 but was 33. Strings differ at index 0. Expected: "[Ljava/lang/Object;" But was: "crc64d5d92128469ae06d/JavaArray_1" -----------^ The immediate cause of the failure is that `JniRuntime.JniTypeManager.GetTypeSignature()` called `JniRuntime.JniTypeManager.GetSimpleReference()` *before* it tried to see if the type was `JavaArray<T>`. As `Java.Interop.dll` was now being processed for typemap purposes, and because `JavaArray<T>` did not have a `[JniTypeSignatureAttribute]`, the typemap got the default behavior of `crc64[hash…]`. The broader cause is that `GetSimpleReference()` should be the *fallback* implementation, used after all other attempts to get a JNI name have failed. Update `GetTypeSignature()` and `GetTypeSignatures()` so that `GetSimpleReference()` and/or `GetSimpleReferences()` are in fact treated as fallbacks. Additionally, update `AssertGetJniTypeInfoForType()` to assert that the value returned by `GetTypeSignature()` is the same as the value return3ed by` GetTypeSignatures().First()`. This was *commented* as being the case, but we should *verify* that as well. Finally, update `AssertGetJniTypeInfoForType()` so that when the assertion fails, the source `type` value is provided.
1 parent 6bc87e8 commit 08fb6bb

File tree

2 files changed

+50
-39
lines changed

2 files changed

+50
-39
lines changed

src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,18 @@ public JniTypeSignature GetTypeSignature (Type type)
156156
if (GetBuiltInTypeArraySignature (type, ref signature))
157157
return signature.AddArrayRank (rank);
158158

159-
var simpleRef = GetSimpleReference (type);
160-
if (simpleRef != null)
161-
return new JniTypeSignature (simpleRef, rank, false);
159+
var isGeneric = type.IsGenericType;
160+
var genericDef = isGeneric ? type.GetGenericTypeDefinition () : type;
161+
if (isGeneric) {
162+
if (genericDef == typeof (JavaArray<>) || genericDef == typeof (JavaObjectArray<>)) {
163+
var r = GetTypeSignature (type.GenericTypeArguments [0]);
164+
return r.AddArrayRank (rank + 1);
165+
}
166+
167+
var genericSimpleRef = GetSimpleReference (genericDef);
168+
if (genericSimpleRef != null)
169+
return new JniTypeSignature (genericSimpleRef, rank, false);
170+
}
162171

163172
var name = type.GetCustomAttribute<JniTypeSignatureAttribute> (inherit: false);
164173
if (name != null) {
@@ -171,20 +180,9 @@ public JniTypeSignature GetTypeSignature (Type type)
171180
return new JniTypeSignature (name.SimpleReference, name.ArrayRank + rank, name.IsKeyword);
172181
}
173182

174-
var isGeneric = type.IsGenericType;
175-
var genericDef = isGeneric ? type.GetGenericTypeDefinition () : type;
176-
if (isGeneric) {
177-
if (genericDef == typeof (JavaArray<>) || genericDef == typeof (JavaObjectArray<>)) {
178-
var r = GetTypeSignature (type.GenericTypeArguments [0]);
179-
return r.AddArrayRank (rank + 1);
180-
}
181-
}
182-
183-
if (isGeneric) {
184-
simpleRef = GetSimpleReference (genericDef);
185-
if (simpleRef != null)
186-
return new JniTypeSignature (simpleRef, rank, false);
187-
}
183+
var simpleRef = GetSimpleReference (type);
184+
if (simpleRef != null)
185+
return new JniTypeSignature (simpleRef, rank, false);
188186

189187
return default;
190188
}
@@ -194,44 +192,48 @@ public IEnumerable<JniTypeSignature> GetTypeSignatures (Type type)
194192
{
195193
AssertValid ();
196194

195+
if (type == null)
196+
yield break;
197197
if (type.ContainsGenericParameters)
198198
throw new ArgumentException ($"'{type}' contains a generic type definition. This is not supported.", nameof (type));
199199

200200
type = GetUnderlyingType (type, out int rank);
201201

202-
var signature = new JniTypeSignature (null);
202+
var signature = JniTypeSignature.Empty;
203203
if (GetBuiltInTypeSignature (type, ref signature))
204204
yield return signature.AddArrayRank (rank);
205205
if (GetBuiltInTypeArraySignature (type, ref signature))
206206
yield return signature.AddArrayRank (rank);
207207

208-
foreach (var simpleRef in GetSimpleReferences (type)) {
209-
if (simpleRef == null)
210-
continue;
211-
yield return new JniTypeSignature (simpleRef, rank, false);
212-
}
213-
214-
var name = type.GetCustomAttribute<JniTypeSignatureAttribute> (inherit: false);
215-
if (name != null) {
216-
yield return new JniTypeSignature (name.SimpleReference, name.ArrayRank + rank, name.IsKeyword);
217-
}
218-
219-
var isGeneric = type.IsGenericType;
220-
var genericDef = isGeneric ? type.GetGenericTypeDefinition () : type;
208+
var isGeneric = type.IsGenericType;
209+
var genericDef = isGeneric ? type.GetGenericTypeDefinition () : type;
221210
if (isGeneric) {
222-
if (genericDef == typeof(JavaArray<>) || genericDef == typeof(JavaObjectArray<>)) {
211+
if (genericDef == typeof (JavaArray<>) || genericDef == typeof (JavaObjectArray<>)) {
223212
var r = GetTypeSignature (type.GenericTypeArguments [0]);
224213
yield return r.AddArrayRank (rank + 1);
225214
}
226-
}
227215

228-
if (isGeneric) {
229-
foreach (var simpleRef in GetSimpleReferences (genericDef)) {
230-
if (simpleRef == null)
216+
foreach (var genericSimpleRef in GetSimpleReferences (genericDef)) {
217+
if (genericSimpleRef == null)
231218
continue;
232-
yield return new JniTypeSignature (simpleRef, rank, false);
219+
yield return new JniTypeSignature (genericSimpleRef, rank, false);
233220
}
234221
}
222+
223+
var name = type.GetCustomAttribute<JniTypeSignatureAttribute> (inherit: false);
224+
if (name != null) {
225+
var altRef = GetReplacementType (name.SimpleReference);
226+
if (altRef != null) {
227+
yield return new JniTypeSignature (altRef, name.ArrayRank + rank, name.IsKeyword);
228+
}
229+
yield return new JniTypeSignature (name.SimpleReference, name.ArrayRank + rank, name.IsKeyword);
230+
}
231+
232+
foreach (var simpleRef in GetSimpleReferences (type)) {
233+
if (simpleRef == null)
234+
continue;
235+
yield return new JniTypeSignature (simpleRef, rank, false);
236+
}
235237
}
236238

237239
static Type GetUnderlyingType (Type type, out int rank)

tests/Java.Interop-Tests/Java.Interop/JniTypeManagerTests.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,24 @@ public void GetTypeSignature_Type ()
7979

8080
#if !__ANDROID__
8181
// Re-enable once typemap files contain `JavaObject` subclasses, not just Java.Lang.Object subclasses
82+
//
83+
// Note: dotnet/android@5c23bcda updates Java.Lang.Object to inherit JavaObject; this is not enough,
84+
// as `<GenerateJavaStubs/>` only processes assemblies if they reference Mono.Android.dll.
8285
AssertGetJniTypeInfoForType (typeof (GenericHolder<int>), GenericHolder<int>.JniTypeName, false, 0);
8386
#endif // !__ANDROID__
8487
}
8588

8689
static void AssertGetJniTypeInfoForType (Type type, string jniType, bool isKeyword, int arrayRank)
8790
{
8891
var info = JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (type);
89-
Assert.AreEqual (jniType, info.Name);
90-
Assert.AreEqual (arrayRank, info.ArrayRank);
92+
93+
// `GetTypeSignature() and `GetTypeSignatures()` should be "in sync"; verify that!
94+
var info2 = JniRuntime.CurrentRuntime.TypeManager.GetTypeSignatures (type).FirstOrDefault ();
95+
96+
Assert.AreEqual (jniType, info.Name, $"info.Name for `{type}`");
97+
Assert.AreEqual (jniType, info2.Name, $"info.Name for `{type}`");
98+
Assert.AreEqual (arrayRank, info.ArrayRank, $"info.ArrayRank for `{type}`");
99+
Assert.AreEqual (arrayRank, info2.ArrayRank, $"info.ArrayRank for `{type}`");
91100
}
92101

93102
[Test]

0 commit comments

Comments
 (0)