Skip to content

Commit 0e01fb5

Browse files
authored
[Java.Interop.Tools.JavaSource] Merge @return block values (#836)
Context: dotnet/android#5485 In an attempt to generate updated documentation for API-30 I noticed a minor issue in generator Javadoc import (7574f16): when a `<javadoc/>` element contains multiple `@return` values: <class name="Example" …> <method name="getP" …> <javadoc> <![CDATA[ … @return some docs @return additional docs ]]> </javadoc> </method> </class> We would generate multiple `<returns/>` elements, one for each `@return`: partial class Example { /// <returns>some docs</returns> /// <returns>additional docs</returns> public int P { [Register("getP", …)] get => … } } This is "fine", as far as the C# compiler is concerned, which results in a Documentation XML file containing both `<returns/>`: <doc> <members> <member name="P:Example.P"> <returns>some docs</returns> <returns>additional docs</returns> </member> </members> </doc> The problem is when we later try to *import* this documentation via `mdoc update --import`, as dotnet/android#5485 does; if it's a *method* which contains multiple `<returns/>` elements and mdoc 5.7.4.9 is used (included with macOS Mono 6.12): $ mdoc update -o docs assembly.dll --import assembly.xml Then the resulting imported [**mdoc**(5)][0] documentation only contains the *first* element: <Docs> <summary>To be added.</summary> <returns>some docs</returns> <remarks>To be added.</remarks> </Docs> Using [mdoc 5.8.0][1] will preserve both `<returns/>` elements, but "higher level" tooling such as HTML rendering or IntelliSense may not properly support multiple `<returns/>` elements. *However*, if it's a *property* which contains multiple `<returns/>` elements, then `mdoc update` will convert each `<returns/>` element into a `<value/>` element: $ mdoc update -o docs assembly.dll --import assembly.xml … <Docs> <summary>To be added.</summary> <value>some docs</value> <value>additional docs</value> <remarks>To be added.</remarks> </Docs> This is "odd", but it gets worse: on subsequent `mdoc update` invocations, *additional* `<value/>` elements are created! $ mdoc update -o docs assembly.dll --import assembly.xml … <Docs> <summary>To be added.</summary> <value>additional docs</value> <value>some docs</value> <value>additional docs</value> <remarks>To be added.</remarks> </Docs> $ mdoc update -o docs assembly.dll --import assembly.xml … <Docs> <summary>To be added.</summary> <value>some docs</value> <value>additional docs</value> <value>some docs</value> <value>additional docs</value> <remarks>To be added.</remarks> </Docs> While an `mdoc` bug, we can prevent this from happening by updating the Javadoc importer so that multiple `@returns` blocks are *merged* into a single `<returns/>` element: partial class Example { /// <returns>some docs additional docs</returns> public int P {…} } [0]: http://docs.go-mono.com/?link=man%3amdoc(5) [1]: https://www.nuget.org/packages/mdoc/5.8.0
1 parent 12e670a commit 0e01fb5

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

src/Java.Interop.Tools.JavaSource/Java.Interop.Tools.JavaSource/SourceJavadocToXmldocGrammar.BlockTagsBnfTerms.cs

+13-3
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,20 @@ internal void CreateRules (SourceJavadocToXmldocGrammar grammar)
114114
if (!grammar.ShouldImport (ImportJavadoc.ReturnTag)) {
115115
return;
116116
}
117-
var r = new XElement ("returns",
117+
// When encountering multiple @return keys in a line, append subsequent @return key content to the original <returns> element.
118+
var jdi = FinishParse (context, parseNode);
119+
if (jdi.Returns.Count == 0) {
120+
var r = new XElement ("returns",
118121
AstNodeToXmlContent (parseNode.ChildNodes [1]));
119-
FinishParse (context, parseNode).Returns.Add (r);
120-
parseNode.AstNode = r;
122+
FinishParse (context, parseNode).Returns.Add (r);
123+
parseNode.AstNode = r;
124+
} else {
125+
var r = jdi.Returns.First () as XElement;
126+
if (r != null) {
127+
r.Add (" ", AstNodeToXmlContent (parseNode.ChildNodes [1]));
128+
parseNode.AstNode = r;
129+
}
130+
}
121131
};
122132

123133
SeeDeclaration.Rule = "@see" + BlockValues;

tests/Java.Interop.Tools.JavaSource-Tests/SourceJavadocToXmldocParserTests.cs

+24-15
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,19 @@ namespace Java.Interop.Tools.JavaSource.Tests
1717
[TestFixture]
1818
public class SourceJavadocToXmldocParserTests : SourceJavadocToXmldocGrammarFixture {
1919

20-
[Test]
21-
public void TryParse ()
20+
[Test, TestCaseSource (nameof (TryParse_Success))]
21+
public void TryParse (ParseResult parseResult)
2222
{
23-
foreach (var values in TryParse_Success) {
24-
ParseTree parseTree;
25-
var p = new SourceJavadocToXmldocParser (XmldocStyle.Full);
26-
var n = p.TryParse (values.Javadoc, null, out parseTree);
27-
Assert.IsFalse (parseTree.HasErrors (), DumpMessages (parseTree, p));
28-
Assert.AreEqual (values.FullXml, GetMemberXml (n), $"while parsing input: ```{values.Javadoc}```");
23+
ParseTree parseTree;
24+
var p = new SourceJavadocToXmldocParser (XmldocStyle.Full);
25+
var n = p.TryParse (parseResult.Javadoc, null, out parseTree);
26+
Assert.IsFalse (parseTree.HasErrors (), DumpMessages (parseTree, p));
27+
Assert.AreEqual (parseResult.FullXml, GetMemberXml (n), $"while parsing input: ```{parseResult.Javadoc}```");
2928

30-
p = new SourceJavadocToXmldocParser (XmldocStyle.IntelliSense);
31-
n = p.TryParse (values.Javadoc, null, out parseTree);
32-
Assert.IsFalse (parseTree.HasErrors (), DumpMessages (parseTree, p));
33-
Assert.AreEqual (values.IntelliSenseXml, GetMemberXml (n), $"while parsing input: ```{values.Javadoc}```");
34-
}
29+
p = new SourceJavadocToXmldocParser (XmldocStyle.IntelliSense);
30+
n = p.TryParse (parseResult.Javadoc, null, out parseTree);
31+
Assert.IsFalse (parseTree.HasErrors (), DumpMessages (parseTree, p));
32+
Assert.AreEqual (parseResult.IntelliSenseXml, GetMemberXml (n), $"while parsing input: ```{parseResult.Javadoc}```");
3533
}
3634

3735
static string GetMemberXml (IEnumerable<XNode> members)
@@ -40,7 +38,7 @@ static string GetMemberXml (IEnumerable<XNode> members)
4038
return e.ToString ();
4139
}
4240

43-
static readonly ParseResult[] TryParse_Success = new ParseResult[]{
41+
public static readonly ParseResult[] TryParse_Success = new ParseResult[]{
4442
new ParseResult {
4543
Javadoc = "Summary.\n\nP2.\n\n<p>Hello!</p>",
4644
FullXml = @"<member>
@@ -78,6 +76,17 @@ static string GetMemberXml (IEnumerable<XNode> members)
7876
<returns>
7977
<c>true</c> if something
8078
or other; otherwise <c>false</c>.</returns>
79+
</member>",
80+
},
81+
new ParseResult {
82+
Javadoc = "@return {@code true} if something else @return {@code false}.",
83+
FullXml = @"<member>
84+
<returns>
85+
<c>true</c> if something else <c>false</c>.</returns>
86+
</member>",
87+
IntelliSenseXml = @"<member>
88+
<returns>
89+
<c>true</c> if something else <c>false</c>.</returns>
8190
</member>",
8291
},
8392
new ParseResult {
@@ -166,7 +175,7 @@ more description here.</para>
166175
},
167176
};
168177

169-
class ParseResult {
178+
public class ParseResult {
170179
public string Javadoc;
171180
public string FullXml;
172181
public string IntelliSenseXml;

0 commit comments

Comments
 (0)