Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[generator] Support Buffer.duplicate() binding in API-34 (#1086)
Context: dotnet/android#7796 Context: 22d5687 Context: 5a0e37e Imagine the following covariant-return-type -using construct, which is new in API-34 `android.jar`: // Java public abstract class Buffer { public abstract Buffer duplicate (); } public abstract class CharBuffer extends Buffer { public abstract CharBuffer duplicate (); } By default this is bound as: // C# [Register(…)] public abstract partial class Buffer { [Register(…)] public abstract Buffer Duplicate (); } [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public abstract CharBuffer Duplicate (); } Alas, this results in [error CS0533][0]: error CS0533: 'CharBuffer.Duplicate()' hides inherited abstract member 'Buffer.Duplicate()' C# supports this semantic if we use [`abstract override`][1], similar to [reabstraction of Default Interface Methods][2] in 22d5687: public abstract class CharBuffer : Buffer { public override abstract CharBuffer Duplicate (); } Theoretically, we can tell `generator` how to fix this via the `//attr[@name='managedOverride']` metadata property (5a0e37e): <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']/method[@name='duplicate']" name="managedOverride">override</attr> However, `//attr[@name='managedOverride']` was not written to support updating`abstract` methods. Fix that oversight so that using `//attr[@name='managedOverride']` can be used to emit `override abstract`: [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public override abstract CharBuffer Duplicate (); } ~~ Method Invokers ~~ This gets us halfway there, but there is another issue: method invokers for both the class and base class methods are *also* emitted into the `*Invoker` subclass: partial class BufferInvoker : CharBuffer { public override sealed unsafe Buffer Duplicate() {…} // so far so good… } partial class CharBufferInvoker : CharBuffer { [Register ("duplicate", "()Ljava/nio/Buffer;", "")] public override sealed unsafe Buffer Duplicate() {…} [Register ("duplicate", "()Ljava/nio/CharBuffer;", "")] public override sealed unsafe CharBuffer Duplicate() {…} // uh oh } This results in the following error: error CS0111: Type 'CharBufferInvoker' already defines a member called 'Duplicate' with the same parameter types error CS0508: 'CharBufferInvoker.Duplicate()': return type must be 'CharBuffer' to match overridden member 'CharBuffer.Duplicate()' This perhaps(?) could be something `generator` could detect and prevent, but the feasibility and cost is unknown and expected to be high. Since this is a very rare case, we will fix it with metadata, however we have never had metadata to apply to invokers before. We have decided to support `//attr[@name='skipInvokerMethods']` metadata on the `class` that the invoker class would be created for: <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']" name="skipInvokerMethods">java/nio/Buffer.duplicate()Ljava/nio/Buffer;</attr> The value is a comma, space, and newline-separated list of "JNI signature-like" values consisting of: 1. The simplified JNI name of the declaring class that contains the the invoker method to skip, e.g. `java/nio/Buffer` 2. `.` 3. The Java name of the invoker method to skip, e.g. `duplicate`. 4. The JNI method signature of the method to skip, e.g. `()Ljava/nio/Buffer;` The above `java/nio/Buffer.duplicate()Ljava/nio/Buffer;` value tells `generator` to skip generating the `Buffer Buffer.duplicate ()` invoker method when generating the `CharBufferInvoker` type. Multiple invokers to skip can be specified as a comma or space separated list. [0]: https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0533 [1]: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#1467-abstract-methods [2]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#reabstraction
- Loading branch information