Skip to content

Commit ce9d952

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 ce9d952

File tree

1 file changed

+47
-29
lines changed

1 file changed

+47
-29
lines changed

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

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -362,37 +362,55 @@ 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+
var xtype = xdoc
366+
.Elements ("api")
367+
.Elements ("package")
368+
.Where (p => ((string) p.Attribute ("name")) == package)
369+
.Elements ()
370+
.Where (t => ((string) t.Attribute ("name")) == type)
371+
.FirstOrDefault ();
372+
if (xtype == null) {
373+
return null;
384374
}
385375

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;
376+
var members = method == "constructor"
377+
? xtype.Elements ("constructor")
378+
: xtype.Elements ("method").Where (m => ((string) m.Attribute ("name")) == method);
379+
var pcount = ptypes.Length;
380+
members = members
381+
.Where (m => m.Elements ("parameter").Count () == pcount);
382+
383+
XElement? member = null;
384+
foreach (var m in members) {
385+
var found = true;
386+
int i = 0;
387+
foreach (var p in m.Elements ("parameter")) {
388+
if (!ParameterTypesMatch (p, ptypes [i++])) {
389+
found = false;
390+
break;
391+
}
392+
}
393+
if (found) {
394+
member = m;
395+
break;
396+
}
397+
}
398+
if (member == null)
399+
return null;
400+
return member.Elements ("parameter")
401+
.Select (p => (string) p.Attribute ("name"))
402+
.ToArray ();
403+
404+
bool ParameterTypesMatch (XElement parameter, string ptype)
405+
{
406+
var xtype = (string) parameter.Attribute ("jni-type");
407+
var jtype = (string) parameter.Attribute ("type");
408+
if (!xtype.StartsWith ("L.*", StringComparison.Ordinal)) {
409+
return xtype == ptype || jtype == ptype;
410+
}
411+
jtype = "." + jtype.Substring (".*".Length);
412+
return ptype.EndsWith (jtype, StringComparison.Ordinal);
413+
}
396414
}
397415
}
398416
}

0 commit comments

Comments
 (0)