Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

IOORE importing type with name ending in a period #835

Description

@jpobst

Context: com.google.firebase.firestore.model.Document

The following code:

  private static final Comparator<Document> KEY_COMPARATOR =
      (left, right) -> left.getKey().compareTo(right.getKey());

  /** A document comparator that returns document by key and key only. */
  public static Comparator<Document> keyComparator() {
    return KEY_COMPARATOR;
  }

is being parsed out as:

<class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object" jni-extends="Ljava/lang/Object;" final="false" name="Document." static="false" visibility="public" jni-signature="Lcom/google/firebase/firestore/model/Document$;"></class>

The name='Document.' causes an IndexOutOfRangeException building the model from the XML:

   at System.String.get_Chars(Int32 index)
   at MonoDroid.Generation.XmlApiImporter.CreateGenBaseSupport(XElement pkg, XElement elem, Boolean isInterface) in C:\code\xamarin-android-backport\external\Java.Interop\tools\generator\Java.Interop.Tools.Generator.Importers\XmlApiImporter.cs:line 290
   at MonoDroid.Generation.XmlApiImporter.CreateClass(XElement pkg, XElement elem, CodeGenerationOptions options) in C:\code\xamarin-android-backport\external\Java.Interop\tools\generator\Java.Interop.Tools.Generator.Importers\XmlApiImporter.cs:line 110
   at MonoDroid.Generation.XmlApiImporter.ParsePackage(XElement ns, CodeGenerationOptions options) in C:\code\xamarin-android-backport\external\Java.Interop\tools\generator\Java.Interop.Tools.Generator.Importers\XmlApiImporter.cs:line 66
   at MonoDroid.Generation.XmlApiImporter.Parse(XDocument doc, CodeGenerationOptions options) in C:\code\xamarin-android-backport\external\Java.Interop\tools\generator\Java.Interop.Tools.Generator.Importers\XmlApiImporter.cs:line 35

Activity

  1. added
    bugComponent does not function as intended
    generatorIssues binding a Java library (generator, class-parse, etc.)
    on May 11, 2021
  2. jpobst commented on May 11, 2021

    @jpobst
    ContributorAuthor

    Notes:

    This is an issue caused by a change between firebase-firestore 22.1.1 and 22.1.2.

    Java source code: https://github.com/firebase/firebase-android-sdk/blob/master/firebase-firestore/src/main/java/com/google/firebase/firestore/model/Document.java

    Java library: https://maven.google.com/web/index.html?q=firestore#com.google.firebase:firebase-firestore:22.1.2

    Decompilation:
    image

    class-parse

        <class
          abstract="false"
          deprecated="not deprecated"
          jni-extends="Ljava/lang/Object;"
          extends="java.lang.Object"
          extends-generic-aware="java.lang.Object"
          final="false"
          name="Document."
          jni-signature="Lcom/google/firebase/firestore/model/Document$;"
          source-file-name="Document.java"
          static="false"
          visibility="public" />
    

    adjusted

        <class abstract="false" deprecated="not deprecated" extends="java.lang.Object" 
    extends-generic-aware="java.lang.Object" jni-extends="Ljava/lang/Object;" final="false" 
    name="Document." static="false" visibility="public" 
    jni-signature="Lcom/google/firebase/firestore/model/Document$;"></class>
    
    
  3. AmrAlSayed0 commented on May 12, 2021

    @AmrAlSayed0

    This would also help with this issue #789 (comment).

  4. jonpryor commented on May 12, 2021

    @jonpryor
    Contributor

    I'm wondering about how specifically this is happening, as I cannot repro it:

    import java.util.Comparator;
    
    class Example implements Comparable<Example> {
        public int compareTo(Example a) {return 0;}
    
        static final Comparator<Example> COMPARATOR = (left, right) -> left.compareTo(right);
    
        public static Comparator<Example> keyComparator() { return COMPARATOR; }
    }

    Using both JDK 1.8 and JDK 11's javac, I do not get an Example$.class file as output. Instead, Example.COMPARATOR is implemented in terms of InvokeDynamic & a static method:

    $ javap -l -constants -c -private -s Example.class
    …
      private static int lambda$static$0(Example, Example);
        descriptor: (LExample;LExample;)I
        Code:
           0: aload_0
           1: aload_1
           2: invokevirtual dotnet/java-interop#4                  // Method compareTo:(LExample;)I
           5: ireturn
        LineNumberTable:
          line 6: 0
    
      static {};
        descriptor: ()V
        Code:
           0: invokedynamic dotnet/java-interop#5,  0              // InvokeDynamic #0:compare:()Ljava/util/Comparator;
           5: putstatic     dotnet/java-interop#2                  // Field COMPARATOR:Ljava/util/Comparator;
           8: return
        LineNumberTable:
          line 6: 0

    The lambda$static$0 method is from the lambda expression.

    (My Kotlin toolchain is screwed up, so I can't currently try to see what Kotlin would do in a similar scenario.)

    I thus don't understand where Document. is coming from. I certainly don't understand why Document. is public, of all things.

  5. jonpryor commented on May 12, 2021

    @jonpryor
    Contributor

    Doubly odd is that Document.class doesn't even mention Document$.class:

    $ javap -constants -p -l -c -verbose -private -s  Document.class| grep 'Document\$'
      dotnet/java-interop#28 = Utf8               com/google/firebase/firestore/model/Document$$Lambda$1
      dotnet/java-interop#29 = Class              dotnet/java-interop#28            // com/google/firebase/firestore/model/Document$$Lambda$1
      dotnet/java-interop#33 = Methodref          dotnet/java-interop#29.#32        // com/google/firebase/firestore/model/Document$$Lambda$1.lambdaFactory$:()Ljava/util/Comparator;
             0: invokestatic  dotnet/java-interop#33                 // Method com/google/firebase/firestore/model/Document$$Lambda$1.lambdaFactory$:()Ljava/util/Comparator;
    # note: no mention of `Document$`,
    # except as part of a larger `Document$$Lambda$1`

    Document$$Lambda$1.class does mention Document$, as an invokestatic target:

      public int compare(java.lang.Object, java.lang.Object);
        descriptor: (Ljava/lang/Object;Ljava/lang/Object;)I
        flags: (0x0001) ACC_PUBLIC
        Code:
          stack=2, locals=3, args_size=3
             0: aload_1
             1: checkcast     dotnet/java-interop#14                 // class com/google/firebase/firestore/model/Document
             4: aload_2
             5: checkcast     dotnet/java-interop#14                 // class com/google/firebase/firestore/model/Document
             8: invokestatic  dotnet/java-interop#20                 // Method com/google/firebase/firestore/model/Document$.lambda$static$0:(Lcom/google/firebase/firestore/model/Document;Lcom/google/firebase/firestore/model/Document;)I
            11: ireturn
    

    I have to wonder if there's some "Java bytecode post processing" going on…

  6. jonpryor commented on May 12, 2021

    @jonpryor
    Contributor

    Meanwhile, @jpobst mentioned:

    My current thought is to skip types with no effective "name" in XmlApiImporter in generator with a warning or a debug message.

    We already skip types with "obfuscated" names:

    https://github.com/xamarin/java.interop/blob/12e670a8560f69581d3a3adf0a9d91e8ce8c9afa/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs#L63-L72

    https://github.com/xamarin/java.interop/blob/12e670a8560f69581d3a3adf0a9d91e8ce8c9afa/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs#L490-L507

    so perhaps the "easy" fix is to extend IsObfuscatedName() so that Document. is treated as "obfuscated"?

  7. jpobst commented on May 12, 2021

    @jpobst
    ContributorAuthor

    I have to wonder if there's some "Java bytecode post processing" going on…

    Yeah, I couldn't repro it either, and thought this might be the case.

  8. locked and limited conversation to collaborators on Apr 12, 2024
  9. added a commit that references this issue on Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugComponent does not function as intendedgeneratorIssues binding a Java library (generator, class-parse, etc.)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions