-
Notifications
You must be signed in to change notification settings - Fork 64
Description
Context? #1266
Context: #1267 (comment)
Currently, generators 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.FieldClassforFieldClass(as per[Register]), and - an entry
Com.Mypackage.FieldClass.NestedFieldClassfor 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-genwould 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.