Skip to content

ApiXmlAdjuster removes required methods from interfaces #814

@jpobst

Description

@jpobst

If ApiXmlAdjuster cannot resolve part of a method (return type, parameter type, etc), it removes the method from its containing type. However, if the containing type is an interface and the method is not default or static, removing the method causes the interface to be un-implementable. The entire interface must be removed.

Note that generator has this logic and if IT invalidates a method it will invalidate the interface, however ApiXmlAdjuster does not have this logic, and generator does not know what ApiXmlAdjuster has removed.

Example:

Given an interface like this:

// api.xml.class-parse
<interface
  abstract="true"
  deprecated="not deprecated"
  final="false"
  name="Size"
  jni-signature="Landroidx/annotation/Size;"
  source-file-name="Size.java"
  static="false"
  visibility="public">
  <method
    abstract="true"
    deprecated="not deprecated"
    final="false"
    name="max"
    native="false"
    return="android.dummy.Potato"  <-- Type that does not exist
    jni-return="Landroid/dummy/Potato;"
    static="false"
    synchronized="false"
    visibility="public"
    bridge="false"
    synthetic="false"
    jni-signature="()Landroid/dummy/Potato;" />
  <method
    abstract="true"
    deprecated="not deprecated"
    final="false"
    name="min"
    native="false"
    return="long"
    jni-return="J"
    static="false"
    synchronized="false"
    visibility="public"
    bridge="false"
    synthetic="false"
    jni-signature="()J" />
</interface>

ApiXmlAdjuster will remove the method that contains a return type that it cannot resolve:

Error while processing '[Method] android.dummy.Potato max()' in '[Interface] androidx.annotation.Size':
  Type 'android.dummy.Potato' was not found.

However it leaves the rest of the interface intact.

https://github.com/xamarin/java.interop/blob/main/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiTypeResolverExtensions.cs#L117-L118

// api.xml
<interface abstract="true" deprecated="not deprecated" final="false" name="Size" static="false" visibility="public" jni-signature="Landroidx/annotation/Size;">
  <method abstract="true" deprecated="not deprecated" final="false" name="min" jni-signature="()J" bridge="false" native="false" return="long" jni-return="J" static="false" synchronized="false" synthetic="false" visibility="public" />
</interface>

This causes our C# binding of the interface to not include the required interface method:

// Metadata.xml XPath interface reference: path="/api/package[@name='androidx.annotation']/interface[@name='Size']"
[Register ("androidx/annotation/Size", "", "AndroidX.Annotations.ISizeInvoker")]
public partial interface ISize : IJavaObject, IJavaPeerable {
  // Metadata.xml XPath method reference: path="/api/package[@name='androidx.annotation']/interface[@name='Size']/method[@name='min' and count(parameter)=0]"
  [Register ("min", "()J", "GetMinHandler:AndroidX.Annotations.ISizeInvoker, Xamarin.AndroidX.Annotation")]
  long Min ();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    generatorIssues binding a Java library (generator, class-parse, etc.)

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions