Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/Xamarin.Android.Tools.Bytecode/ClassPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public enum JavaDocletType {
Java6,
Java7,
Java8,
_ApiXml
_ApiXml,
JavaApiParameterNamesXml,
}

public class ClassPath {
Expand Down Expand Up @@ -231,15 +232,16 @@ void FixupParametersFromDocs (XElement api)
}
}

IAndroidDocScraper CreateDocScraper (string src)
IJavaMethodParameterNameProvider CreateDocScraper (string src)
{
switch (AndroidDocScraper.GetDocletType (src)) {
switch (JavaMethodParameterNameProvider.GetDocletType (src)) {
default: return new DroidDoc2Scraper (src);
case JavaDocletType.DroidDoc: return new DroidDocScraper (src);
case JavaDocletType.Java6: return new JavaDocScraper (src);
case JavaDocletType.Java7: return new Java7DocScraper (src);
case JavaDocletType.Java8: return new Java8DocScraper (src);
case JavaDocletType._ApiXml: return new ApiXmlDocScraper (src);
case JavaDocletType.JavaApiParameterNamesXml: return new JavaParameterNamesLoader (src);
}
}

Expand Down
21 changes: 14 additions & 7 deletions src/Xamarin.Android.Tools.Bytecode/JavaDocumentScraper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ protected override string StripTagsFromParameters (string value)
}
}

public abstract class AndroidDocScraper : IAndroidDocScraper
public abstract class AndroidDocScraper : IJavaMethodParameterNameProvider
{
readonly String pattern_head;
readonly String reset_pattern_head;
Expand Down Expand Up @@ -290,6 +290,14 @@ public static void LoadXml (String filename)
Log.Error ("Annotations parser error: " + ex);
}
}
}

public interface IJavaMethodParameterNameProvider
{
String[] GetParameterNames (string package, string type, string method, string[] ptypes, bool isVarArgs);
}

public static class JavaMethodParameterNameProvider {

public static JavaDocletType GetDocletType (string path)
{
Expand Down Expand Up @@ -322,18 +330,17 @@ public static JavaDocletType GetDocletType (string path)
}
if (rawXML.Contains ("<api>") && rawXML.Contains ("<package"))
kind = JavaDocletType._ApiXml;
else if (rawXML.StartsWith ("package", StringComparison.Ordinal) ||
rawXML.StartsWith (";", StringComparison.Ordinal)) {
kind = JavaDocletType.JavaApiParameterNamesXml;
}
}

return kind;
}
}

public interface IAndroidDocScraper
{
String[] GetParameterNames (string package, string type, string method, string[] ptypes, bool isVarArgs);
}

public class ApiXmlDocScraper : IAndroidDocScraper
public class ApiXmlDocScraper : IJavaMethodParameterNameProvider
{
public ApiXmlDocScraper (string apiXmlFile)
{
Expand Down
135 changes: 135 additions & 0 deletions src/Xamarin.Android.Tools.Bytecode/JavaParameterNamesLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;

namespace Xamarin.Android.Tools.Bytecode
{
public class JavaParameterNamesLoader : IJavaMethodParameterNameProvider
{
List<Package> packages;

public JavaParameterNamesLoader(string path)
{
packages = this.LoadParameterFixupDescription(path);
}

class Parameter
{
public string Type { get; set; }
public string Name { get; set; }
}

class Method
{
public string Name { get; set; }
public List<Parameter> Parameters { get; set; }
}

class Type
{
public string Name { get; set; }
public List<Method> Methods { get; set; }
}

class Package
{
public string Name { get; set; }
public List<Type> Types { get; set; }
}

// from https://github.com/atsushieno/xamarin-android-docimporter-ng/blob/master/Xamarin.Android.Tools.JavaStubImporter/JavaApiParameterNamesXmlExporter.cs#L78
/*
* The Text Format is:
*
* package {packagename}
* #---------------------------------------
* interface {interfacename}{optional_type_parameters} -or-
* class {classname}{optional_type_parameters}
* {optional_type_parameters}{methodname}({parameters})
*
* Anything after # is treated as comment.
*
* optional_type_parameters: "" -or- "<A,B,C>" (no constraints allowed)
* parameters: type1 p0, type2 p1 (pairs of {type} {name}, joined by ", ")
*
* It is with strict indentations. two spaces for types, four spaces for methods.
*
* Constructors are named as "#ctor".
*
* Commas are used by both parameter types and parameter separators,
* but only parameter separators can be followed by a whitespace.
* It is useful when writing text parsers for this format.
*
* Type names may contain whitespaces in case it is with generic constraints (e.g. "? extends FooBar"),
* so when parsing a parameter type-name pair, the only trustworthy whitespace for tokenizing name is the *last* one.
*
*/
List<Package> LoadParameterFixupDescription (string path)
{
var fixup = new List<Package> ();
string package = null;
var types = new List<Type> ();
string type = null;
var methods = new List<Method> ();
foreach (var l in File.ReadAllLines (path)) {
var line = l.IndexOf ('#') >= 0 ? l.Substring (0, l.IndexOf ('#')) : l;
if (line.Trim ().Length == 0)
continue;
if (line.StartsWith ("package ", StringComparison.Ordinal)) {
package = line.Substring ("package ".Length);
types = new List<Type> ();
fixup.Add (new Package { Name = package, Types = types });
continue;
} else if (line.StartsWith (" ", StringComparison.Ordinal)) {
int open = line.IndexOf ('(');
string parameters = line.Substring (open + 1).TrimEnd (')');
string name = line.Substring (4, open - 4);
if (name.FirstOrDefault () == '<') // generic method can begin with type parameters.
name = name.Substring (name.IndexOf (' ') + 1);
methods.Add (new Method {
Name = name,
Parameters = parameters.Replace (", ", "\0").Split ('\0')
.Select (s => s.Split (' '))
.Select (a => new Parameter { Type = string.Join (" ", a.Take (a.Length - 1)), Name = a.Last () }).ToList ()
});
} else {
type = line.Substring (line.IndexOf (' ', 2) + 1);
// To match type name from class-parse, we need to strip off generic arguments here (generics are erased).
if (type.IndexOf ('<') > 0)
type = type.Substring (0, type.IndexOf ('<'));
methods = new List<Method> ();
types.Add (new Type { Name = type, Methods = methods });
}
}
return fixup;
}

public string[] GetParameterNames (string package, string type, string method, string[] ptypes, bool isVarArgs)
{
var methods = this.packages
.Where(p => p.Name == package)
.SelectMany(p => p.Types)
.Where(t => t.Name == type)
.SelectMany(t => t.Methods)
.Where(m => m.Name == method);
var namedMethod = methods.FirstOrDefault (m => ParametersEqual (m.Parameters, ptypes));
if (namedMethod == null)
return null;
return namedMethod.Parameters.Select (p => p.Name).ToArray ();
}

static bool ParametersEqual (List<Parameter> methodParameters, string[] ptypes)
{
if (methodParameters.Count != ptypes.Length)
return false;
for (int i = 0; i < ptypes.Length; ++i) {
if (methodParameters[i].Type != ptypes [i])
return false;
}
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package java.util
class Collection<E>
add(E e)
20 changes: 18 additions & 2 deletions src/Xamarin.Android.Tools.Bytecode/Tests/ParameterFixupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void DocletType_ShouldDetectApiXml ()
try {
tempFile = LoadToTempFile ("ParameterFixupApiXmlDocs.xml");

Assert.AreEqual (JavaDocletType._ApiXml, AndroidDocScraper.GetDocletType (tempFile));
Assert.AreEqual (JavaDocletType._ApiXml, JavaMethodParameterNameProvider.GetDocletType (tempFile));
} finally {
if (File.Exists (tempFile))
File.Delete (tempFile);
Expand All @@ -85,7 +85,23 @@ public void DocletType_ShouldDetectDroidDocs ()
if (!Directory.Exists (droidDocsPath))
Assert.Fail("The Android SDK Documentation path `{0}` was not found.", droidDocsPath);

Assert.AreEqual(JavaDocletType.DroidDoc2, AndroidDocScraper.GetDocletType(droidDocsPath));
Assert.AreEqual(JavaDocletType.DroidDoc2, JavaMethodParameterNameProvider.GetDocletType(droidDocsPath));
}

[Test]
public void XmlDeclaration_FixedUpFromParameterDescription ()
{
string tempFile = null;

try {
tempFile = LoadToTempFile ("ParameterDescription.txt");

AssertXmlDeclaration (new string [] { "Collection.class" }, "ParameterFixupFromDocs.xml", tempFile);
}
finally {
if (File.Exists (tempFile))
File.Delete (tempFile);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@
<EmbeddedResource Include="ParameterFixupApiXmlDocs.xml">
<LogicalName>ParameterFixupApiXmlDocs.xml</LogicalName>
</EmbeddedResource>
</ItemGroup>
<EmbeddedResource Include="ParameterDescription.txt">
<LogicalName>ParameterDescription.txt</LogicalName>
</EmbeddedResource> </ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<Compile Include="JavaDocumentScraper.cs" />
<Compile Include="ClassPath.cs" />
<Compile Include="Log.cs" />
<Compile Include="JavaParameterNamesLoader.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
3 changes: 3 additions & 0 deletions tools/class-parse/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public static void Main (string[] args)
{ "docspath=",
"Documentation {PATH} for parameter fixup",
doc => docsPaths.Add (doc) },
{ "parameter-names=",
"{PATH} for Java method parameter name information",
doc => docsPaths.Add (doc) },
{ "docstype=",
"OBSOLETE: Previously used to specify a doc type (now auto detected).",
t => docsType = t != null },
Expand Down