Skip to content

Commit 9b89e90

Browse files
authored
[generator] Ignore types without names (#837)
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.
1 parent 0e01fb5 commit 9b89e90

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,5 +266,41 @@ public void IgnoreKotlinInternalMembers ()
266266
Assert.AreEqual (0, klass.Fields.Count);
267267
Assert.AreEqual (0, klass.Methods.Count);
268268
}
269+
270+
[Test]
271+
public void IgnoreTypesWithInvalidNames ()
272+
{
273+
var xml = XDocument.Parse (@"
274+
<api>
275+
<package name='com.example.test' jni-name='com/example/test'>
276+
<class name='' visibility='public' />
277+
<class name='Document.' visibility='public' />
278+
<interface name='' visibility='public' />
279+
<interface name='Document.' visibility='public' />
280+
</package>
281+
</api>");
282+
283+
var gens = XmlApiImporter.Parse (xml, opt);
284+
285+
// None of these should be parsed because they have invalid names
286+
Assert.AreEqual (0, gens.Count);
287+
}
288+
289+
[Test]
290+
public void IgnoreUserObfuscatedTypes ()
291+
{
292+
var xml = XDocument.Parse (@"
293+
<api>
294+
<package name='com.example.test' jni-name='com/example/test'>
295+
<class name='MyClass' visibility='public' obfuscated='true' />
296+
<interface name='MyInterface' visibility='public' obfuscated='true' />
297+
</package>
298+
</api>");
299+
300+
var gens = XmlApiImporter.Parse (xml, opt);
301+
302+
// None of these should be parsed because the user has said they are obfuscated
303+
Assert.AreEqual (0, gens.Count);
304+
}
269305
}
270306
}

tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,12 @@ public static List<GenBase> ParsePackage (XElement ns, CodeGenerationOptions opt
6161

6262
switch (elem.Name.LocalName) {
6363
case "class":
64-
if (elem.XGetAttribute ("obfuscated") == "true")
65-
continue;
66-
gen = CreateClass (ns, elem, options);
64+
if (ShouldBind (elem))
65+
gen = CreateClass (ns, elem, options);
6766
break;
6867
case "interface":
69-
if (elem.XGetAttribute ("obfuscated") == "true")
70-
continue;
71-
gen = CreateInterface (ns, elem, options);
68+
if (ShouldBind (elem))
69+
gen = CreateInterface (ns, elem, options);
7270
break;
7371
default:
7472
Report.LogCodedWarning (0, Report.WarningUnexpectedPackageChildNode, elem.Name.ToString ());
@@ -522,5 +520,20 @@ static void SetLineInfo (ISourceLineInfo model, XNode node, CodeGenerationOption
522520
model.LinePosition = info.LinePosition;
523521
}
524522
}
523+
524+
static bool ShouldBind (XElement elem)
525+
{
526+
// Don't bind things the user has said are "obfuscated"
527+
if (elem.XGetAttribute ("obfuscated") == "true")
528+
return false;
529+
530+
var java_name = elem.XGetAttribute ("name");
531+
532+
// Ignore types that do not have a name (nested classes would end in a period like "Document.")
533+
if (!java_name.HasValue () || java_name.EndsWith (".", StringComparison.Ordinal))
534+
return false;
535+
536+
return true;
537+
}
525538
}
526539
}

0 commit comments

Comments
 (0)