Skip to content

Commit dda3904

Browse files
committed
[Java.Interop] Add JniTypeSignature.Parse()
Rename JniRuntime.JniTypeManager.GetTypeSignature(string) to JniTypeSignature.Parse(string). Implementation-wise, JniRuntime.JniTypeManager.GetTypeSignature() could be a static method; it doesn't use any other instance methods, nor does it use any virtual methods. The question then becomes, *should* it have some virtuals? Should it *itself* be `virtual`, allowing subclasses to "fixup" JNI signatures to "something else"? *Maybe*, but I can't think of a good reason to support that semantic. Meanwhile, *preventing* it from being an overridable method *simplifies* reasoning about things, as there's no runtime variable behavior involved, so you can "know" that if you have a JNI signature, you can get a JniTypeSignature, and nothing should go wrong (unless the JNI signature is invalid!). This keeps things "sane".
1 parent 1ceac93 commit dda3904

File tree

9 files changed

+125
-104
lines changed

9 files changed

+125
-104
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,8 @@ Dictionary<string, List<JavaFieldInfo>> LookupFields ()
227227

228228
var n_type = JniEnvironment.InstanceMethods.CallObjectMethod (field, Field_getType);
229229
using (var type = new JniType (ref n_type, JniObjectReferenceOptions.CopyAndDispose)) {
230-
var info = JniEnvironment.Runtime.TypeManager.GetTypeSignature (type.Name);
231-
overloads.Add (new JavaFieldInfo (Members, name + "\u0000" + info.QualifiedReference, isStatic));
230+
var sig = JniTypeSignature.Parse (type.Name);
231+
overloads.Add (new JavaFieldInfo (Members, name + "\u0000" + sig.QualifiedReference, isStatic));
232232
}
233233

234234
JniObjectReference.Dispose (ref field);

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JavaMethodBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public void LookupArguments ()
9292
for (int i = 0; i < len; ++i) {
9393
var p = JniEnvironment.Arrays.GetObjectArrayElement (parameters, i);
9494
try {
95-
var sig = mgr.GetTypeSignature (JniEnvironment.Types.GetJniTypeNameFromClass (p));
95+
var sig = JniTypeSignature.Parse (JniEnvironment.Types.GetJniTypeNameFromClass (p));
9696
sb.Append (sig.QualifiedReference);
9797
arguments.Add (p.NewGlobalRef ());
9898
} finally {

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JavaMethodInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected override string JniReturnType {
5454
get {
5555
if (ReturnType == null)
5656
return "V";
57-
return JniEnvironment.Runtime.TypeManager.GetTypeSignature (ReturnType.Name).QualifiedReference;
57+
return JniTypeSignature.Parse (ReturnType.Name).QualifiedReference;
5858
}
5959
}
6060

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JniMetaObject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public override DynamicMetaObject BindConvert (ConvertBinder binder)
4646
{
4747
var vm = JniEnvironment.Runtime;
4848
if (binder.Type == typeof (Type)) {
49-
var sig = vm.TypeManager.GetTypeSignature (info.JniClassName);
49+
var sig = JniTypeSignature.Parse (info.JniClassName);
5050
var type = vm.TypeManager.GetType (sig);
5151
var typeE = Expression.Convert (Expression.Constant (type), binder.Type);
5252
return new DynamicMetaObject (typeE, BindingRestrictions.GetTypeRestriction (typeE, binder.Type), type);

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

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -174,73 +174,6 @@ IEnumerable<Type> CreateGetTypesForSimpleReferenceEnumerator (string jniSimpleRe
174174
#endif // !XA_INTEGRATION
175175
yield break;
176176
}
177-
178-
public JniTypeSignature GetTypeSignature (string jniTypeReference)
179-
{
180-
if (jniTypeReference == null)
181-
throw new ArgumentNullException (nameof (jniTypeReference));
182-
int i = 0;
183-
int r = 0;
184-
var n = (string) null;
185-
var k = false;
186-
while (i < jniTypeReference.Length && jniTypeReference [i] == '[') {
187-
i++;
188-
r++;
189-
}
190-
switch (jniTypeReference [i]) {
191-
case 'B':
192-
case 'C':
193-
case 'D':
194-
case 'I':
195-
case 'F':
196-
case 'J':
197-
case 'S':
198-
case 'Z':
199-
if (jniTypeReference.Length - i > 1)
200-
n = jniTypeReference.Substring (i);
201-
else {
202-
n = jniTypeReference [i].ToString ();
203-
k = true;
204-
}
205-
break;
206-
case 'L':
207-
int s = jniTypeReference.IndexOf (';', i);
208-
if (s >= i && s != jniTypeReference.Length-1)
209-
throw new ArgumentException (
210-
string.Format ("Malformed JNI type reference: trailing text after ';' in '{0}'.", jniTypeReference),
211-
nameof (jniTypeReference));
212-
if (i == 0) {
213-
n = s > i
214-
? jniTypeReference.Substring (i + 1, s - i - 1)
215-
: jniTypeReference;
216-
} else {
217-
if (s < i)
218-
throw new ArgumentException (
219-
string.Format ("Malformed JNI type reference; no terminating ';' for type ref: '{0}'.", jniTypeReference.Substring (i)),
220-
nameof (jniTypeReference));
221-
if (s != jniTypeReference.Length - 1)
222-
throw new ArgumentException (
223-
string.Format ("Malformed jNI type reference: invalid trailing text: '{0}'.", jniTypeReference.Substring (i)),
224-
nameof (jniTypeReference));
225-
n = jniTypeReference.Substring (i + 1, s - i - 1);
226-
}
227-
break;
228-
default:
229-
if (i != 0)
230-
throw new ArgumentException (
231-
string.Format ("Malformed JNI type reference: found unrecognized char '{0}' in '{1}'.",
232-
jniTypeReference [i], jniTypeReference),
233-
nameof (jniTypeReference));
234-
n = jniTypeReference;
235-
break;
236-
}
237-
int bad = n.IndexOfAny (new[]{ '.', ';' });
238-
if (bad >= 0)
239-
throw new ArgumentException (
240-
string.Format ("Malformed JNI type reference: contains '{0}': {1}", n [bad], jniTypeReference),
241-
"jniTypeReference");
242-
return new JniTypeSignature (n, r, k);
243-
}
244177
}
245178
}
246179
}

src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ ConstructorInfo GetWrapperConstructor (JniObjectReference instance, Type fallbac
340340

341341
Type type = null;
342342
while (jniTypeName != null) {
343-
type = Runtime.TypeManager.GetType (Runtime.TypeManager.GetTypeSignature (jniTypeName));
343+
type = Runtime.TypeManager.GetType (JniTypeSignature.Parse (jniTypeName));
344344

345345
if (type != null) {
346346
var ctor = GetActivationConstructor (type);
@@ -432,7 +432,7 @@ public T CreateValue<T> (ref JniObjectReference reference, JniObjectReferenceOpt
432432

433433
internal Type GetRuntimeType (JniObjectReference reference)
434434
{
435-
var signature = Runtime.TypeManager.GetTypeSignature (JniEnvironment.Types.GetJniTypeNameFromInstance (reference));
435+
var signature = JniTypeSignature.Parse (JniEnvironment.Types.GetJniTypeNameFromInstance (reference));
436436
return Runtime.TypeManager.GetType (signature);
437437
}
438438

src/Java.Interop/Java.Interop/JniTypeSignature.cs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,94 @@ public JniTypeSignature GetPrimitiveWrapper ()
7676
}
7777
}
7878

79+
public static JniTypeSignature Parse (string signature)
80+
{
81+
JniTypeSignature r;
82+
var e = TryParseWithException (signature, out r);
83+
if (e != null)
84+
throw e;
85+
return r;
86+
}
87+
88+
public static bool TryParse (string signature, out JniTypeSignature result)
89+
{
90+
var e = TryParseWithException (signature, out result);
91+
if (e != null)
92+
return false;
93+
return true;
94+
}
95+
96+
static Exception TryParseWithException (string signature, out JniTypeSignature result)
97+
{
98+
result = default (JniTypeSignature);
99+
100+
if (signature == null)
101+
return new ArgumentNullException (nameof (signature));
102+
103+
int i = 0;
104+
int r = 0;
105+
var n = (string) null;
106+
var k = false;
107+
while (i < signature.Length && signature [i] == '[') {
108+
i++;
109+
r++;
110+
}
111+
switch (signature [i]) {
112+
case 'B':
113+
case 'C':
114+
case 'D':
115+
case 'I':
116+
case 'F':
117+
case 'J':
118+
case 'S':
119+
case 'Z':
120+
if (signature.Length - i > 1)
121+
n = signature.Substring (i);
122+
else {
123+
n = signature [i].ToString ();
124+
k = true;
125+
}
126+
break;
127+
case 'L':
128+
int s = signature.IndexOf (';', i);
129+
if (s >= i && s != signature.Length-1)
130+
return new ArgumentException (
131+
string.Format ("Malformed JNI type reference: trailing text after ';' in '{0}'.", signature),
132+
nameof (signature));
133+
if (i == 0) {
134+
n = s > i
135+
? signature.Substring (i + 1, s - i - 1)
136+
: signature;
137+
} else {
138+
if (s < i)
139+
return new ArgumentException (
140+
string.Format ("Malformed JNI type reference; no terminating ';' for type ref: '{0}'.", signature.Substring (i)),
141+
nameof (signature));
142+
if (s != signature.Length - 1)
143+
return new ArgumentException (
144+
string.Format ("Malformed jNI type reference: invalid trailing text: '{0}'.", signature.Substring (i)),
145+
nameof (signature));
146+
n = signature.Substring (i + 1, s - i - 1);
147+
}
148+
break;
149+
default:
150+
if (i != 0)
151+
return new ArgumentException (
152+
string.Format ("Malformed JNI type reference: found unrecognized char '{0}' in '{1}'.",
153+
signature [i], signature),
154+
nameof (signature));
155+
n = signature;
156+
break;
157+
}
158+
int bad = n.IndexOfAny (new[]{ '.', ';' });
159+
if (bad >= 0)
160+
return new ArgumentException (
161+
string.Format ("Malformed JNI type reference: contains '{0}': {1}", n [bad], signature),
162+
nameof (signature));
163+
result = new JniTypeSignature (n, r, k);
164+
return null;
165+
}
166+
79167
public override int GetHashCode ()
80168
{
81169
return QualifiedReference.GetHashCode ();

src/Java.Interop/Tests/Java.Interop/JniTypeManagerTests.cs

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static void AssertGetJniTypeInfoForType (Type type, string jniType, bool isKeywo
9090
{
9191
var manager = JniRuntime.CurrentRuntime.TypeManager;
9292
Func<string, Type> GetType = s => {
93-
var sig = manager.GetTypeSignature (s);
93+
var sig = JniTypeSignature.Parse (s);
9494
return manager.GetType (sig);
9595
};
9696
Assert.Throws<ArgumentNullException> (() => GetType (null));
@@ -139,40 +139,12 @@ static void AssertGetJniTypeInfoForType (Type type, string jniType, bool isKeywo
139139
Assert.AreEqual (null, GetType ("Ljava/lang/String"));
140140
}
141141

142-
[Test]
143-
public void GetTypeSignature_String ()
144-
{
145-
Assert.Throws<ArgumentNullException> (() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature ((string) null));
146-
Assert.Throws<ArgumentException> (() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature ("java.lang.String"));
147-
Assert.Throws<ArgumentException> (() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature ("Ljava/lang/String;I"));
148-
Assert.Throws<ArgumentException> (() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature ("ILjava/lang/String;"));
149-
150-
AssertGetJniTypeInfoForJniTypeReference ("java/lang/String", "java/lang/String");
151-
AssertGetJniTypeInfoForJniTypeReference ("Ljava/lang/String;", "java/lang/String");
152-
AssertGetJniTypeInfoForJniTypeReference ("[I", "I", true, 1);
153-
AssertGetJniTypeInfoForJniTypeReference ("[[I", "I", true, 2);
154-
AssertGetJniTypeInfoForJniTypeReference ("[Ljava/lang/Object;", "java/lang/Object", false, 1);
155-
156-
// Yes, these look _really_ weird...
157-
// Assume: class II {}
158-
AssertGetJniTypeInfoForJniTypeReference ("II", "II");
159-
// Assume: package Ljava.lang; class String {}
160-
AssertGetJniTypeInfoForJniTypeReference ("Ljava/lang/String", "Ljava/lang/String");
161-
}
162-
163-
static void AssertGetJniTypeInfoForJniTypeReference (string jniTypeReference, string jniTypeName, bool typeIsKeyword = false, int arrayRank = 0)
164-
{
165-
var info = JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (jniTypeReference);
166-
Assert.AreEqual (jniTypeName, info.SimpleReference, "JniTypeName for: " + jniTypeReference);
167-
Assert.AreEqual (arrayRank, info.ArrayRank, "ArrayRank for: " + jniTypeReference);
168-
}
169-
170142
[Test]
171143
public void GetTypeSignature ()
172144
{
173145
var jvm = JniRuntime.CurrentRuntime;
174146
Func<string, Type> GetTypeForSimpleReference = s => {
175-
var sig = jvm.TypeManager.GetTypeSignature (s);
147+
var sig = JniTypeSignature.Parse (s);
176148
return jvm.TypeManager.GetType (sig);
177149
};
178150
Assert.Throws<ArgumentNullException> (() => GetTypeForSimpleReference (null));

src/Java.Interop/Tests/Java.Interop/JniTypeSignatureTest.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,34 @@ public void QualifiedReference ()
5050
Assert.AreEqual ("[[B", info.QualifiedReference);
5151
Assert.AreEqual ("B", info.SimpleReference);
5252
}
53+
54+
[Test]
55+
public void Parse ()
56+
{
57+
Assert.Throws<ArgumentNullException> (() => JniTypeSignature.Parse ((string) null));
58+
Assert.Throws<ArgumentException> (() => JniTypeSignature.Parse ("java.lang.String"));
59+
Assert.Throws<ArgumentException> (() => JniTypeSignature.Parse ("Ljava/lang/String;I"));
60+
Assert.Throws<ArgumentException> (() => JniTypeSignature.Parse ("ILjava/lang/String;"));
61+
62+
AssertGetJniTypeInfoForJniTypeReference ("java/lang/String", "java/lang/String");
63+
AssertGetJniTypeInfoForJniTypeReference ("Ljava/lang/String;", "java/lang/String");
64+
AssertGetJniTypeInfoForJniTypeReference ("[I", "I", true, 1);
65+
AssertGetJniTypeInfoForJniTypeReference ("[[I", "I", true, 2);
66+
AssertGetJniTypeInfoForJniTypeReference ("[Ljava/lang/Object;", "java/lang/Object", false, 1);
67+
68+
// Yes, these look _really_ weird...
69+
// Assume: class II {}
70+
AssertGetJniTypeInfoForJniTypeReference ("II", "II");
71+
// Assume: package Ljava.lang; class String {}
72+
AssertGetJniTypeInfoForJniTypeReference ("Ljava/lang/String", "Ljava/lang/String");
73+
}
74+
75+
static void AssertGetJniTypeInfoForJniTypeReference (string jniTypeReference, string jniTypeName, bool typeIsKeyword = false, int arrayRank = 0)
76+
{
77+
var sig = JniTypeSignature.Parse (jniTypeReference);
78+
Assert.AreEqual (jniTypeName, sig.SimpleReference, "JniTypeName for: " + jniTypeReference);
79+
Assert.AreEqual (arrayRank, sig.ArrayRank, "ArrayRank for: " + jniTypeReference);
80+
}
5381
}
5482
}
5583

0 commit comments

Comments
 (0)