You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes: #1155
Context: https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html
A *bridge method* is a Java compiler-generated method "overload"
which deals with type coercion, to support Java type erasure:
package com.google.mlkit.vision.objects;
// https://developers.google.com/android/reference/com/google/mlkit/vision/objects/ObjectDetectorOptionsBase
public class ObjectDetectorOptionsBase {
/** @hide */ public static class Builder<B extends Builder> {
public B setDetectorMode(int detectorMode) {…}
}
}
package com.google.mlkit.vision.objects.defaults;
public class ObjectDetectorOptions {
// https://developers.google.com/android/reference/com/google/mlkit/vision/objects/defaults/ObjectDetectorOptions.Builder
public static class Builder extends ObjectDetectorOptionsBase.Builder<Builder> {
public Builder setDetectorMode(int detectorMode) {…}
}
}
It *looks like* there is only one
`ObjectDetectorOptions.Builder.setDetectorMode()` method, but there
are in fact *two*. The first is the bridge method (`ACC_BRIDGE`),
the second method is the "real" method; they differ on return type:
% javap -cp classes.jar -s -v 'com/google/mlkit/vision/objects/defaults/ObjectDetectorOptions$Builder'
…
public final com.google.mlkit.vision.objects.ObjectDetectorOptionsBase$Builder setDetectorMode(int);
descriptor: (I)Lcom/google/mlkit/vision/objects/ObjectDetectorOptionsBase$Builder;
flags: (0x1051) ACC_PUBLIC, ACC_FINAL, ACC_BRIDGE, ACC_SYNTHETIC
…
public com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions$Builder setDetectorMode(int);
descriptor: (I)Lcom/google/mlkit/vision/objects/defaults/ObjectDetectorOptions$Builder;
flags: (0x0001) ACC_PUBLIC
This is represented within `class-parse` XML as:
<method abstract="false" deprecated="not deprecated" final="false" name="setDetectorMode" jni-signature="(I)Lcom/google/mlkit/vision/objects/defaults/ObjectDetectorOptions$Builder;" bridge="false" native="false" return="com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions.Builder" jni-return="Lcom/google/mlkit/vision/objects/defaults/ObjectDetectorOptions$Builder;" static="false" synchronized="false" synthetic="false" visibility="public" return-not-null="true">
<parameter name="detectorMode" type="int" jni-type="I" />
</method>
<method abstract="false" deprecated="not deprecated" final="true" name="setDetectorMode" jni-signature="(I)Lcom/google/mlkit/vision/objects/ObjectDetectorOptionsBase$Builder;" bridge="true" native="false" return="java.lang.Object" jni-return="Lcom/google/mlkit/vision/objects/ObjectDetectorOptionsBase$Builder;" static="false" synchronized="false" synthetic="true" visibility="public" return-not-null="true">
<parameter name="p0" type="int" jni-type="I" />
</method>
The method with `bridge="true"` is the bridge method.
When bound in C#, this causes an issue because two methods cannot
have the same method name and parameter types:
// C# binding
public partial class ObjectDetectorOptions {
public partial class Builder {
public virtual MLKit.Vision.Objects.Defaults.ObjectDetectorOptions.Builder SetDetectorMode (int detectorMode);
public virtual MLKit.Vision.Objects.ObjectDetectorOptionsBase.Builder SetDetectorMode (int p0);
}
}
We can set `managedName` metadata to rename one of these methods:
<attr path="//method[@name='setDetectorMode' and @bridge='true']" name="managedName>SetDetectorMode2</attr>
However, we generate the callback delegate field with the algorithm
`$"cb_{JavaName}{IDSignature}"`, so this identifier is still used
twice, preventing C# compilation:
// C# binding
public partial class ObjectDetectorOptions {
public partial class Builder {
static Delegate cb_setDetectorMode_I;
static Delegate cb_setDetectorMode_I;
}
}
The solution is to add both the _managed_ name and the return type to
the callback naming algorithm to ensure that it will always be unique
for a method: `$"cb_{JavaName}_{Name}{IDSignatureWithReturnType}"`:
// C# binding
public partial class ObjectDetectorOptions {
public partial class Builder {
static Delegate cb_setDetectorMode_SetDetectorMode_I_Lcom_google_mlkit_vision_objects_defaults_ObjectDetectorOptions$Builder_;
static Delegate cb_setDetectorMode_SetDetectorMode2_I_Lcom_google_mlkit_vision_objects_ObjectDetectorOptions$Builder_;
}
}
Copy file name to clipboardExpand all lines: tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt
Copy file name to clipboardExpand all lines: tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1-NRT/WriteMethodWithCharSequenceArrays.txt
+4-4
Original file line number
Diff line number
Diff line change
@@ -29,13 +29,13 @@ public partial class MyClass : Java.Lang.Object {
0 commit comments