Skip to content

Commit

Permalink
[generator] Ignore types without names (#837)
Browse files Browse the repository at this point in the history
Fixes: #835

Context: https://github.com/firebase/firebase-android-sdk/blob/1fba4a70395c20dcc858b22ee8247acbed7cf8d3/firebase-firestore/src/main/java/com/google/firebase/firestore/model/Document.java
Context: https://maven.google.com/web/index.html?q=firestore#com.google.firebase:firebase-firestore:22.1.2

Somehow Google has compiled `firebase-firestore.aar` to contain a
`Document$.class` with a "non-sensical" *empty* inner class name:

	<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"
	/>

The presence of a `//class[@name='Document.']` element causes an
`IndexOutOfRangeException` for `generator` when it tries to parse
`Document.` into a parent class name and nested class name.

	System.IndexOutOfRangeException: Index was outside the bounds of the array.
	  at MonoDroid.Generation.XmlApiImporter.CreateGenBaseSupport (System.Xml.Linq.XElement pkg, System.Xml.Linq.XElement elem, System.Boolean isInterface)
	  at MonoDroid.Generation.XmlApiImporter.CreateClass (System.Xml.Linq.XElement pkg, System.Xml.Linq.XElement elem, 
	  at MonoDroid.Generation.Parser.ParsePackage (System.Xml.Linq.XElement ns, System.Predicate`1[T] p)
	  at MonoDroid.Generation.Parser.ParsePackage (System.Xml.Linq.XElement ns)
	  at MonoDroid.Generation.Parser.Parse (System.Xml.Linq.XDocument doc, System.Collections.Generic.IEnumerable`1[T] fixups, 
	  at MonoDroid.Generation.Parser.Parse (System.String filename, System.Collections.Generic.IEnumerable`1[T] fixups, 
	  at Xamarin.Android.Binder.CodeGenerator.Run (Xamarin.Android.Binder.CodeGeneratorOptions options, 
	  at Xamarin.Android.Binder.CodeGenerator.Run (Xamarin.Android.Binder.CodeGeneratorOptions options)
	  at Xamarin.Android.Binder.CodeGenerator.Main (System.String[] args)

We cannot reproduce *how* to get a `Document$.class` file, so we're
currently assuming this is some sort of bytecode manipulation.
As such, we are going to have `generator` ignore types with an empty
name and types that end in a period, which would indicate a nested
type with an empty name.
  • Loading branch information
jpobst authored May 12, 2021
1 parent 0e01fb5 commit 9b89e90
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 6 deletions.
36 changes: 36 additions & 0 deletions tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,5 +266,41 @@ public void IgnoreKotlinInternalMembers ()
Assert.AreEqual (0, klass.Fields.Count);
Assert.AreEqual (0, klass.Methods.Count);
}

[Test]
public void IgnoreTypesWithInvalidNames ()
{
var xml = XDocument.Parse (@"
<api>
<package name='com.example.test' jni-name='com/example/test'>
<class name='' visibility='public' />
<class name='Document.' visibility='public' />
<interface name='' visibility='public' />
<interface name='Document.' visibility='public' />
</package>
</api>");

var gens = XmlApiImporter.Parse (xml, opt);

// None of these should be parsed because they have invalid names
Assert.AreEqual (0, gens.Count);
}

[Test]
public void IgnoreUserObfuscatedTypes ()
{
var xml = XDocument.Parse (@"
<api>
<package name='com.example.test' jni-name='com/example/test'>
<class name='MyClass' visibility='public' obfuscated='true' />
<interface name='MyInterface' visibility='public' obfuscated='true' />
</package>
</api>");

var gens = XmlApiImporter.Parse (xml, opt);

// None of these should be parsed because the user has said they are obfuscated
Assert.AreEqual (0, gens.Count);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,12 @@ public static List<GenBase> ParsePackage (XElement ns, CodeGenerationOptions opt

switch (elem.Name.LocalName) {
case "class":
if (elem.XGetAttribute ("obfuscated") == "true")
continue;
gen = CreateClass (ns, elem, options);
if (ShouldBind (elem))
gen = CreateClass (ns, elem, options);
break;
case "interface":
if (elem.XGetAttribute ("obfuscated") == "true")
continue;
gen = CreateInterface (ns, elem, options);
if (ShouldBind (elem))
gen = CreateInterface (ns, elem, options);
break;
default:
Report.LogCodedWarning (0, Report.WarningUnexpectedPackageChildNode, elem.Name.ToString ());
Expand Down Expand Up @@ -522,5 +520,20 @@ static void SetLineInfo (ISourceLineInfo model, XNode node, CodeGenerationOption
model.LinePosition = info.LinePosition;
}
}

static bool ShouldBind (XElement elem)
{
// Don't bind things the user has said are "obfuscated"
if (elem.XGetAttribute ("obfuscated") == "true")
return false;

var java_name = elem.XGetAttribute ("name");

// Ignore types that do not have a name (nested classes would end in a period like "Document.")
if (!java_name.HasValue () || java_name.EndsWith (".", StringComparison.Ordinal))
return false;

return true;
}
}
}

0 comments on commit 9b89e90

Please sign in to comment.