Skip to content

Commit cee9974

Browse files
committed
[class-parse] Merge javadoc documentation
Context: #623 Context: #623 (comment) DO NOT MERGE UNTIL AFTER PR #623 IS MERGED. Update `class-parse --docspath=PATH` so that if `PATH` contains `<javadoc/>` elements, as produced by `tools/java-source-utils` (PR #623), then those `<javadoc/>` elements will be inserted into the generated API description. The intent is to eventually allow `generator` to emit the `<javadoc/>` data as C# XML Documentation, allowing a pipeline of: java -jar java-source-tools path/to/android.jar --output-javadoc android.xml mono class-parse.exe --docspath=android.xml -o api.xml … mono generator.exe api.xml …
1 parent fabebee commit cee9974

File tree

6 files changed

+171
-8
lines changed

6 files changed

+171
-8
lines changed

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

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,29 @@ public class ClassPath {
2727

2828
public string ApiSource { get; set; }
2929

30-
public IEnumerable<string> DocumentationPaths { get; set; }
30+
IEnumerable<string> docPaths;
31+
Dictionary<string, XDocument> xmlDocPaths;
32+
33+
public IEnumerable<string> DocumentationPaths {
34+
get {return docPaths;}
35+
set {
36+
if (xmlDocPaths != null)
37+
xmlDocPaths = null;
38+
this.docPaths = value;
39+
if (this.docPaths == null) {
40+
return;
41+
}
42+
foreach (var path in docPaths) {
43+
if (path == null)
44+
continue;
45+
if (JavaMethodParameterNameProvider.GetDocletType (path) != JavaDocletType._ApiXml)
46+
continue;
47+
if (xmlDocPaths == null)
48+
xmlDocPaths = new Dictionary<string, XDocument> ();
49+
xmlDocPaths [path] = XDocument.Load (path);
50+
}
51+
}
52+
}
3153

3254
public string AndroidFrameworkPlatform { get; set; }
3355

@@ -244,13 +266,15 @@ void FixupParametersFromDocs (XElement api)
244266

245267
IJavaMethodParameterNameProvider CreateDocScraper (string src)
246268
{
269+
if (xmlDocPaths != null && xmlDocPaths.TryGetValue (src, out var doc)) {
270+
return new ApiXmlDocScraper (doc);
271+
}
247272
switch (JavaMethodParameterNameProvider.GetDocletType (src)) {
248273
default: return new DroidDoc2Scraper (src);
249274
case JavaDocletType.DroidDoc: return new DroidDocScraper (src);
250275
case JavaDocletType.Java6: return new JavaDocScraper (src);
251276
case JavaDocletType.Java7: return new Java7DocScraper (src);
252277
case JavaDocletType.Java8: return new Java8DocScraper (src);
253-
case JavaDocletType._ApiXml: return new ApiXmlDocScraper (src);
254278
case JavaDocletType.JavaApiParameterNamesXml: return new JavaParameterNamesLoader (src);
255279
}
256280
}
@@ -310,11 +334,30 @@ public XElement ToXElement ()
310334
new XAttribute ("name", p),
311335
new XAttribute ("jni-name", p.Replace ('.', '/')),
312336
packagesDictionary [p].OrderBy (c => c.ThisClass.Name.Value, StringComparer.OrdinalIgnoreCase)
313-
.Select (c => new XmlClassDeclarationBuilder (c).ToXElement ()))));
337+
.Select (c => new XmlClassDeclarationBuilder (c, GetJavadocsElement (c)).ToXElement ()))));
314338
FixupParametersFromDocs (api);
315339
return api;
316340
}
317341

342+
XElement GetJavadocsElement (ClassFile type)
343+
{
344+
if (xmlDocPaths == null)
345+
return null;
346+
foreach (var path in docPaths) {
347+
if (!xmlDocPaths.TryGetValue (path, out var doc))
348+
continue;
349+
var typeXml = doc.Elements ("api")
350+
.Elements ("package")
351+
.Where (p => type.PackageName == (string) p.Attribute ("name"))
352+
.Elements ()
353+
.Where (e => type.FullJniName == (string) e.Attribute ("jni-signature"))
354+
.FirstOrDefault ();
355+
if (typeXml != null)
356+
return typeXml;
357+
}
358+
return null;
359+
}
360+
318361
public void SaveXmlDescription (string fileName)
319362
{
320363
var encoding = new UTF8Encoding (encoderShouldEmitUTF8Identifier: false);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ public static JavaDocletType GetDocletType (string path)
328328
int len = reader.ReadBlock (buf, 0, buf.Length);
329329
rawXML = new string (buf, 0, len).Trim ();
330330
}
331-
if (rawXML.Contains ("<api>") && rawXML.Contains ("<package"))
331+
if ((rawXML.Contains ("<api>") || rawXML.Contains ("<api ")) && rawXML.Contains ("<package"))
332332
kind = JavaDocletType._ApiXml;
333333
else if (rawXML.StartsWith ("package", StringComparison.Ordinal) ||
334334
rawXML.StartsWith (";", StringComparison.Ordinal)) {
@@ -342,9 +342,9 @@ public static JavaDocletType GetDocletType (string path)
342342

343343
public class ApiXmlDocScraper : IJavaMethodParameterNameProvider
344344
{
345-
public ApiXmlDocScraper (string apiXmlFile)
345+
public ApiXmlDocScraper (XDocument document)
346346
{
347-
xdoc = XDocument.Load (apiXmlFile);
347+
xdoc = document;
348348
}
349349

350350
XDocument xdoc;

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

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,26 @@ public class XmlClassDeclarationBuilder {
1212

1313
ClassFile classFile;
1414
ClassSignature signature;
15+
XElement javadocsSource;
1516

1617
bool IsInterface {
1718
get {return (classFile.AccessFlags & ClassAccessFlags.Interface) != 0;}
1819
}
1920

2021
public XmlClassDeclarationBuilder (ClassFile classFile)
22+
: this (classFile, null)
23+
{
24+
}
25+
26+
public XmlClassDeclarationBuilder (ClassFile classFile, XElement javadocsSource)
2127
{
2228
if (classFile == null)
2329
throw new ArgumentNullException ("classFile");
2430

2531
this.classFile = classFile;
2632
signature = classFile.GetSignature ();
33+
34+
this.javadocsSource = javadocsSource;
2735
}
2836

2937
public XElement ToXElement ()
@@ -45,12 +53,21 @@ public XElement ToXElement ()
4553
new XAttribute ("visibility", GetVisibility (classFile.Visibility)),
4654
GetTypeParmeters (signature == null ? null : signature.TypeParameters),
4755
GetImplementedInterfaces (),
56+
GetTypeJavadoc (),
4857
GetConstructors (),
4958
GetMethods (),
5059
GetFields ()
5160
);
5261
}
5362

63+
XElement GetTypeJavadoc ()
64+
{
65+
if (javadocsSource == null)
66+
return null;
67+
return javadocsSource.Element ("javadoc");
68+
69+
}
70+
5471
string GetElementName ()
5572
{
5673
if (IsInterface)
@@ -355,7 +372,21 @@ XElement GetMethod (string element, string name, MethodInfo method, string retur
355372
GetNotNull (method),
356373
GetTypeParmeters (msig == null ? null : msig.TypeParameters),
357374
GetMethodParameters (method),
358-
GetExceptions (method));
375+
GetExceptions (method),
376+
GetMethodJavadoc (element, name, method.Descriptor));
377+
}
378+
379+
XElement GetMethodJavadoc (string element, string name, string descriptor)
380+
{
381+
if (javadocsSource == null)
382+
return null;
383+
var r= javadocsSource.Elements (element)
384+
.Where (e => element == "constructor"
385+
? descriptor == (string) e.Attribute ("jni-signature")
386+
: name == (string) e.Attribute ("name") && descriptor == (string) e.Attribute ("jni-signature"))
387+
.Elements ("javadoc")
388+
.FirstOrDefault ();
389+
return r;
359390
}
360391

361392
static XAttribute GetNative (MethodInfo method)
@@ -500,10 +531,22 @@ IEnumerable<XElement> GetFields ()
500531
GetNotNull (field),
501532
GetValue (field),
502533
new XAttribute ("visibility", visibility),
503-
new XAttribute ("volatile", (field.AccessFlags & FieldAccessFlags.Volatile) != 0));
534+
new XAttribute ("volatile", (field.AccessFlags & FieldAccessFlags.Volatile) != 0),
535+
GetFieldJavadoc (field.Name));
504536
}
505537
}
506538

539+
XElement GetFieldJavadoc (string fieldName)
540+
{
541+
if (javadocsSource == null)
542+
return null;
543+
return javadocsSource
544+
.Elements ("field")
545+
.Where (f => fieldName == (string) f.Attribute ("name"))
546+
.Elements ("javadoc")
547+
.FirstOrDefault ();
548+
}
549+
507550
string GetGenericType (FieldInfo field)
508551
{
509552
var signature = field.GetSignature ();

tests/Xamarin.Android.Tools.Bytecode-Tests/ParameterFixupTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ public void XmlDeclaration_FixedUpFromDocumentation()
3030
}
3131
}
3232

33+
[Test]
34+
public void XmlDeclaration_FixedUpFromApiXmlJavadocs ()
35+
{
36+
string tempFile = null;
37+
38+
try {
39+
tempFile = LoadToTempFile ("ParameterFixupApiXmlJavadocs.xml");
40+
41+
AssertXmlDeclaration ("Collection.class", "ParameterFixupFromJavadocs.xml", tempFile);
42+
} finally {
43+
if (File.Exists (tempFile))
44+
File.Delete (tempFile);
45+
}
46+
}
47+
3348
[Test]
3449
public void XmlDeclaration_FixedUpFromApiXmlDocumentation ()
3550
{
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
2+
<api>
3+
<package name="java.util">
4+
<class name="Collection" jni-signature="Ljava/util/Collection;">
5+
<javadoc><![CDATA[Imported Collection documentation? Maybe!]]></javadoc>
6+
<method name="add" jni-signature="(Ljava/lang/Object;)Z">
7+
<parameter name="e" type="E" />
8+
<javadoc><![CDATA[Imported Collection.add documentation? Maybe!]]></javadoc>
9+
</method>
10+
</class>
11+
</package>
12+
</api>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<api
2+
api-source="class-parse">
3+
<package
4+
name="java.util"
5+
jni-name="java/util">
6+
<interface
7+
abstract="true"
8+
deprecated="not deprecated"
9+
final="false"
10+
name="Collection"
11+
jni-signature="Ljava/util/Collection;"
12+
source-file-name="Collection.java"
13+
static="false"
14+
visibility="public">
15+
<typeParameters>
16+
<typeParameter
17+
name="E"
18+
jni-classBound="Ljava/lang/Object;"
19+
classBound="java.lang.Object"
20+
interfaceBounds=""
21+
jni-interfaceBounds="" />
22+
</typeParameters>
23+
<implements
24+
name="java.lang.Iterable"
25+
name-generic-aware="java.lang.Iterable&lt;E&gt;"
26+
jni-type="Ljava/lang/Iterable&lt;TE;&gt;;" />
27+
<javadoc><![CDATA[Imported Collection documentation? Maybe!]]></javadoc>
28+
<method
29+
abstract="true"
30+
deprecated="not deprecated"
31+
final="false"
32+
name="add"
33+
native="false"
34+
return="boolean"
35+
jni-return="Z"
36+
static="false"
37+
synchronized="false"
38+
visibility="public"
39+
bridge="false"
40+
synthetic="false"
41+
jni-signature="(Ljava/lang/Object;)Z">
42+
<parameter
43+
name="e"
44+
type="E"
45+
jni-type="TE;" />
46+
<javadoc><![CDATA[Imported Collection.add documentation? Maybe!]]></javadoc>
47+
</method>
48+
</interface>
49+
</package>
50+
</api>

0 commit comments

Comments
 (0)