-
Notifications
You must be signed in to change notification settings - Fork 60
Description
Context? #1266
Context: #1267 (comment)
Currently, generator
s Symbol Table uses Java names as the keys:
java-interop/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs
Line 59 in 23e9e04
AddType (new SimpleSymbol ("IntPtr.Zero", "void", "void", "V")); |
Keys will be strings such as Java builtin types like boolean
and int
, and "fully qualified dotted" Java names such as java.lang.Object
and android.app.Activity
.
There are (at least?) two issues with this setup:
- Nested type semantics
- Potential ambiguity with JNI names
For nested type semantics, consider #1267:
[Register ("com/mypackage/FieldClass")]
public class FieldClass : Java.Lang.Object {
public NestedFieldClass field;
public class NestedFieldClass : Java.Lang.Object {
}
}
The above could be a hand-written C# snippet added to a binding assembly, and then referenced by generator
when emitting a new set of bindings.
The (long-standing so not necessarily a "real") concern is that when generator
processes the above, the symbol table will have:
- an entry
com.mypackage.FieldClass
forFieldClass
(as per[Register]
), and - an entry
Com.Mypackage.FieldClass.NestedFieldClass
for FieldClass.NestedFieldClass`.
This nested name is wrong; it should instead be one of:
com.mypackage.FieldClass.NestedFieldClass
(append nested name to declaring type name), or- Whatever
jcw-gen
would emit for this type, which could becom.mypackage.FieldClass_NestedFieldClass
, or something like that. (Requires testing.)
Then there's #1266: somehow -- we're not quite sure we fully understand yet -- JniTypeSignatureAttribute.SimpleReference
is being used as a key for the Symbol Table.
Given:
java-interop/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs
Lines 349 to 350 in 23e9e04
[JniTypeSignature ("B", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)] | |
public sealed class JavaSByteArray : JavaPrimitiveArray<SByte> { |
and a Java type:
// Java
public abstract /* partial */ class androidx.work.WorkRequest.Builder<
B extends androidx.work.WorkRequest$Builder<B, ?>,
W extends androidx.work.WorkRequest>
{
public final B setId(java.util.UUID);
}
then the return value of WorkRequest.Builder.setId()
is being detected as JavaSByteArray
instead of WorkRequest.Builder
.
Aside: how?!
Lines 75 to 96 in 23e9e04
internal static RegisterAttribute? RegisterFromJniTypeSignatureAttribute (CustomAttribute attr) | |
{ | |
// attr.Resolve (); | |
RegisterAttribute? r = null; | |
if (attr.ConstructorArguments.Count == 1) | |
r = new RegisterAttribute ((string) attr.ConstructorArguments [0].Value, attr); | |
if (r != null) { | |
var v = attr.Properties.FirstOrDefault (p => p.Name == "GenerateJavaPeer"); | |
if (v.Name == null) { | |
r.DoNotGenerateAcw = false; | |
} else if (v.Name == "GenerateJavaPeer") { | |
r.DoNotGenerateAcw = !(bool) v.Argument.Value; | |
} | |
var isKeyProp = attr.Properties.FirstOrDefault (p => p.Name == "IsKeyword"); | |
var isKeyword = isKeyProp.Name != null && ((bool) isKeyProp.Argument.Value) == true; | |
var arrRankProp = attr.Properties.FirstOrDefault (p => p.Name == "ArrayRank"); | |
if (arrRankProp.Name != null && arrRankProp.Argument.Value is int rank) { | |
r.Name = new string ('[', rank) + (isKeyword ? r.Name : "L" + r.Name + ";"); | |
} | |
} | |
return r; | |
} |
certainly looks like [JniTypeSignature("B", ArrayRank=1, IsKeyword=true)]
should result in a Register
attribute with a name of [B
. How/where would this value be "cleaned up"?
The scenario described in #1266 should not happen. An idea to do that would be to alter the symbol table keys to instead be JNI type signatures. B
would thus only be "byte", while LB;
would be a class B{}
in the global package, and Ljava/lang/Object;
would be java.lang.Object
.