Skip to content

Commit ae5b249

Browse files
committed
[class-parse] Import parameter names for unresolvable types
Fixes: #920 Context: 69e1b80 `java-source-utils.jar` isn't always able to fully resolve types. When it is unable to do so, it uses an "alternate encoding": > In some scenarios, types won't be resolvable. What should output be? > > We don't want to *require* that everything be resolvable -- it's painful, and > possibly impossible, e.g. w/ internal types -- so instead we should "demark" > the unresolvable types. > > `.params.txt` output will use `.*` as a type prefix, e.g. > > method(.*UnresolvableType foo, int bar); > > `docs.xml` will output `L.*UnresolvableType;`. The problem is that `class-parse --parameter-names=PATH` didn't check for this "unresolvable type" pattern, so if you had a method which contained them, e.g. the `target` parameter in: <interface jni-signature="Landroidx/core/view/NestedScrollingParent3;" name="NestedScrollingParent3"> <method jni-return="V" jni-signature="(L.*View;IIIII[I)V" name="onNestedScroll" return="void"> <parameter jni-type="L.*View;" name="target" type=".*View"/> <parameter jni-type="I" name="dxConsumed" type="int"/> <parameter jni-type="I" name="dyConsumed" type="int"/> <parameter jni-type="I" name="dxUnconsumed" type="int"/> <parameter jni-type="I" name="dyUnconsumed" type="int"/> <parameter jni-type="I" name="type" type="int"/> <parameter jni-type="[I" name="consumed" type="int[]"/> then `class-parse --parameter-names=params.xml lib.jar` wouldn't try to "loosely match" these parameter types. Consequently, parameter names were not imported. Update `ApiXmlDocScraper.GetParameterNames()` twofold: 1. Use XLinq instead of computing an XPath expression, and 2. Loosely match parameter types when `//parameter/@jni-name` starts with `L.*`. This allows us to import parameter names for unresolvable types.
1 parent 0293360 commit ae5b249

File tree

1 file changed

+53
-30
lines changed

1 file changed

+53
-30
lines changed

src/Xamarin.Android.Tools.Bytecode/JavaDocumentScraper.cs

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -362,37 +362,60 @@ public ApiXmlDocScraper (string apiXmlFile)
362362

363363
public string[]? GetParameterNames (string package, string type, string method, string[] ptypes, bool isVarArgs)
364364
{
365-
var methodOrCtor = method == "constructor" ?
366-
"constructor[" : $"method[@name='{method}'";
367-
368-
var pcount = ptypes.Length;
369-
370-
var xpath = new StringBuilder ();
371-
372-
xpath.Append ($"/api/package[@name='{package}']/*[self::class or self::interface]/");
373-
374-
if (method == "constructor")
375-
xpath.Append ("constructor[");
376-
else
377-
xpath.Append ($"method[@name='{method}'");
378-
379-
xpath.Append ($" and count(parameter)={pcount}");
380-
381-
if (pcount > 0) {
382-
xpath.Append (" and ");
383-
xpath.Append (string.Join (" and ", ptypes.Select ((pt, pindex) => $"parameter[{pindex + 1}][@type='{pt}']")));
365+
Console.WriteLine ($"# jonp: GetParameterNames: package={package}; type={type}; method={method}");
366+
var xtype = xdoc
367+
.Elements ("api")
368+
.Elements ("package")
369+
.Where (p => ((string) p.Attribute ("name")) == package)
370+
.Elements ()
371+
.Where (t => ((string) t.Attribute ("name")) == type)
372+
.FirstOrDefault ();
373+
if (xtype == null) {
374+
return null;
375+
}
376+
Console.WriteLine ($"# jonp: found xtype={(string) xtype.Attribute ("name")}");
377+
378+
var members = method == "constructor"
379+
? xtype.Elements ("constructor")
380+
: xtype.Elements ("method").Where (m => ((string) m.Attribute ("name")) == method);
381+
var pcount = ptypes.Length;
382+
members = members
383+
.Where (m => m.Elements ("parameter").Count () == pcount);
384+
385+
XElement? member = null;
386+
foreach (var m in members) {
387+
Console.WriteLine ($"# jonp: looking at member {m}");
388+
var found = true;
389+
int i = 0;
390+
foreach (var p in m.Elements ("parameter")) {
391+
if (!ParameterTypesMatch (p, ptypes [i++])) {
392+
found = false;
393+
break;
394+
}
395+
}
396+
if (found) {
397+
member = m;
398+
break;
399+
}
400+
}
401+
if (member == null)
402+
return null;
403+
return member.Elements ("parameter")
404+
.Select (p => (string) p.Attribute ("name"))
405+
.ToArray ();
406+
407+
bool ParameterTypesMatch (XElement parameter, string ptype)
408+
{
409+
var xtype = (string) parameter.Attribute ("jni-type");
410+
var jtype = (string) parameter.Attribute ("type");
411+
Console.WriteLine ($"# jonp: ParameterTypesMatch: xtype={xtype} jtype={jtype} ptype={ptype}");
412+
if (!xtype.StartsWith ("L.*", StringComparison.Ordinal)) {
413+
return xtype == ptype || jtype == ptype;
414+
}
415+
jtype = "." + jtype.Substring (".*".Length);
416+
Console.WriteLine ($"# jonp: ParameterTypesMatch: \"{ptype}\".EndsWith(\"{jtype}\")? {ptype.EndsWith (jtype, StringComparison.Ordinal)}");
417+
return ptype.EndsWith (jtype, StringComparison.Ordinal);
384418
}
385-
386-
xpath.Append ("]");
387-
388-
var methodElem = xdoc.XPathSelectElement (xpath.ToString ());
389-
390-
if (methodElem != null)
391-
return methodElem.Elements ("parameter")
392-
.Select (pe => pe.Attribute ("name")?.Value ?? "")
393-
.ToArray ();
394-
395-
return null;
396419
}
397420
}
398421
}

0 commit comments

Comments
 (0)