-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
generator
Symbol Table semantics
#1268
Comments
Context: #1266 Context: #1268 While the issue described in #1266 is definitely an issue, that example was merely setting up the scenario needed to expose another bug: When a `Java.Lang.Object` or `Java.Interop.JavaObject` subclass has a `public` or `internal` field whose type is a nested type: // C# namespace Com.Mypackage; [Register ("com/mypackage/FieldClass")] public class FieldClass : Java.Lang.Object { public NestedFieldClass field; public class NestedFieldClass : Java.Lang.Object { } } We correctly import the `Field.TypeName` as `Com.Mypackage.FieldClass.NestedFieldClass`, however we also create `Field.SetterParameter` with the "same" type, but we do not replace the `/` nested type separator with a period, resulting in `Com.Mypackage.FieldClass/NestedFieldClass`. Later, when validating the `Field`, we successfully find `Field.TypeName` in the symbol table, but fail to find `Field.SetterParameter` as the symbol table expects a period nested type separator. (Note this only happens because `NestedFieldClass` does not have a `[Register]` attribute, thus it gets added to the symbol table with its managed name rather than its Java name.) This causes `generator` to crash with: System.NotSupportedException: Unable to generate setter parameter list in managed type Com.Mypackage.FieldClass at MonoDroid.Generation.Field.Validate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) at MonoDroid.Generation.GenBase.OnValidate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) at MonoDroid.Generation.ClassGen.OnValidate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) at MonoDroid.Generation.GenBase.Validate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) Fix this by applying the same `FullNameCorrected()` logic that is applied to `Field.TypeName`.
…#1266) Context: #1268 Context: 78d5937 Commit 78d5937 included this snippet: > Update `generator` to support using `Java.Base.dll` as a referenced > assembly for binding purposes, in particular by supporting the use > of `[JniTypeSignatureAttribute]` on already bound types. Aside: the symbol table used by `generator` uses the "full Java name" as the key. Which means that after 78d5937, types with `JniTypeSignatureAttribute.SimpleReference` values are now added to the symbol table, which in turn means that when given: // C# [JniTypeSignature ("B", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)] public sealed partial class JavaSByteArray : JavaPrimitiveArray<SByte> { } when `generator` needs to find type information corresponding to the Java name of `B`, it will find `JavaSByteArray`! This apparently breaks binding the [`androidx.work:work-runtime`][0] Maven package, as [`androidx.work.WorkRequest.Builder.setId(UUID)`][1] has a return type of `B`, a generic type parameter: // 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); } As a workaround, only use `[JniTypeSignature]` when using `generator --codegen-target=JavaInterop1`. `generator --codegen-target=XAJavaInterop1` will only look for `[RegisterAttribute]` when constructing the symbol table. This commit plumbs `CodeGenerationOptions` deeper into `generator` and a new `ApiImporterOptions` into `Java.Interop.Tools.JavaTypeSystem` that is used to determine whether we should be importing `[JniTypeSignatureAttribute]` types. TODO? #1268 [0]: https://maven.google.com/web/index.html#androidx.work:work-runtime [1]: https://developer.android.com/reference/androidx/work/WorkRequest.Builder?hl=en#setId(java.util.UUID)
I think we're conflating different processes here that have different codebases. The linked java-interop/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs Lines 118 to 124 in 2a1e180
Thus something like [JniTypeSignature ("B", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)] Note for // Also incorrect
[JniTypeSignature ("byte", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)] java-interop/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs Line 61 in 2a1e180
I do not think this one is an issue. The We do have a bug here that the symbol table also should not be queried for a generic type parameter name like |
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
Keys will be strings such as Java builtin types like
boolean
andint
, and "fully qualified dotted" Java names such asjava.lang.Object
andandroid.app.Activity
.There are (at least?) two issues with this setup:
For nested type semantics, consider #1267:
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:com.mypackage.FieldClass
forFieldClass
(as per[Register]
), andCom.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), orjcw-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
and a Java type:
then the return value of
WorkRequest.Builder.setId()
is being detected asJavaSByteArray
instead ofWorkRequest.Builder
.Aside: how?!
java-interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CecilExtensions.cs
Lines 75 to 96 in 23e9e04
certainly looks like
[JniTypeSignature("B", ArrayRank=1, IsKeyword=true)]
should result in aRegister
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", whileLB;
would be aclass B{}
in the global package, andLjava/lang/Object;
would bejava.lang.Object
.The text was updated successfully, but these errors were encountered: