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
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal void CreateRules (SourceJavadocToXmldocGrammar grammar)
| SpecialDeclaration
| FormCtrlDeclaration
*/
| InlineHyperLinkDeclaration
| grammar.InlineTagsTerms.AllInlineTerms
| UnknownHtmlElementStart
,
Expand Down Expand Up @@ -94,6 +95,36 @@ internal void CreateRules (SourceJavadocToXmldocGrammar grammar)
FinishParse (context, parseNode).Remarks.Add (p);
parseNode.AstNode = p;
};

InlineHyperLinkDeclaration.Rule = InlineHyperLinkOpenTerm + InlineDeclarations + CreateEndElement ("a", grammar, optional: true);
InlineHyperLinkDeclaration.AstConfig.NodeCreator = (context, parseNode) => {
var unparsedAElementValue = string.Empty;
foreach (var cn in parseNode.ChildNodes) {
if (cn.ChildNodes?.Count > 1) {
foreach (var gcn in cn.ChildNodes) {
unparsedAElementValue += gcn.AstNode?.ToString ();
}
} else {
unparsedAElementValue += cn.AstNode?.ToString ();
}
}

XNode astNodeElement = new XText (unparsedAElementValue);
try {
var seeElement = XElement.Parse ($"<see href={unparsedAElementValue}</see>");
var hrefValue = seeElement.Attribute ("href")?.Value ?? string.Empty;
if (!string.IsNullOrEmpty (hrefValue) &&
(hrefValue.StartsWith ("http", StringComparison.OrdinalIgnoreCase) || hrefValue.StartsWith ("www", StringComparison.OrdinalIgnoreCase))) {
parseNode.AstNode = seeElement;
} else {
// TODO: Need to convert relative paths or code references to appropriate CREF value.
parseNode.AstNode = astNodeElement;
}
} catch (Exception) {
Console.Error.WriteLine ($"# Unable to parse HTML element: <see href={unparsedAElementValue}</see>");
parseNode.AstNode = astNodeElement;
}
};
}

static IEnumerable<XElement> GetParagraphs (ParseTreeNodeList children)
Expand Down Expand Up @@ -161,6 +192,13 @@ static IEnumerable<XElement> GetParagraphs (ParseTreeNodeList children)
public readonly NonTerminal BlockDeclaration = new NonTerminal (nameof (BlockDeclaration), ConcatChildNodes);
public readonly NonTerminal PBlockDeclaration = new NonTerminal (nameof (PBlockDeclaration), ConcatChildNodes);
public readonly NonTerminal PreBlockDeclaration = new NonTerminal (nameof (PreBlockDeclaration), ConcatChildNodes);
public readonly NonTerminal InlineHyperLinkDeclaration = new NonTerminal (nameof (InlineHyperLinkDeclaration), ConcatChildNodes);

public readonly Terminal InlineHyperLinkOpenTerm = new RegexBasedTerminal ("<a href=", @"<a\s*href=") {
AstConfig = new AstNodeConfig {
NodeCreator = (context, parseNode) => parseNode.AstNode = "",
},
};

public readonly Terminal UnknownHtmlElementStart = new UnknownHtmlElementStartTerminal (nameof (UnknownHtmlElementStart)) {
AstConfig = new AstNodeConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@ internal void CreateRules (SourceJavadocToXmldocGrammar grammar)

DocRootDeclaration.Rule = grammar.ToTerm ("{@docRoot}");
DocRootDeclaration.AstConfig.NodeCreator = (context, parseNode) => {
parseNode.AstNode = new XText ("[TODO: @docRoot]");
var docRoot = grammar.XmldocSettings.DocRootValue;
if (!string.IsNullOrEmpty (docRoot)) {
if (!docRoot.EndsWith ("/", StringComparison.OrdinalIgnoreCase)) {
docRoot += "/";
}
} else {
docRoot = "{@docRoot}";
}
parseNode.AstNode = new XText (docRoot);
};

InheritDocDeclaration.Rule = grammar.ToTerm ("{@inheritDoc}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public partial class SourceJavadocToXmldocGrammar : Grammar {
public readonly InlineTagsBnfTerms InlineTagsTerms;
public readonly HtmlBnfTerms HtmlTerms;

public readonly XmldocStyle XmldocStyle;
public readonly XmldocSettings XmldocSettings;

public SourceJavadocToXmldocGrammar (XmldocStyle style)
public SourceJavadocToXmldocGrammar (XmldocSettings settings)
{
BlockTagsTerms = new BlockTagsBnfTerms ();
InlineTagsTerms = new InlineTagsBnfTerms ();
HtmlTerms = new HtmlBnfTerms ();

XmldocStyle = style;
XmldocSettings = settings;

BlockTagsTerms.CreateRules (this);
InlineTagsTerms.CreateRules (this);
Expand Down Expand Up @@ -55,7 +55,7 @@ public SourceJavadocToXmldocGrammar (XmldocStyle style)

internal bool ShouldImport (ImportJavadoc value)
{
var v = (ImportJavadoc) XmldocStyle;
var v = (ImportJavadoc) XmldocSettings.Style;
return v.HasFlag (value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,19 @@ public enum XmldocStyle {

public class SourceJavadocToXmldocParser : Irony.Parsing.Parser {

public SourceJavadocToXmldocParser (XmldocStyle style = XmldocStyle.Full)
: base (CreateGrammar (style))
public SourceJavadocToXmldocParser (XmldocSettings settings)
: base (CreateGrammar (settings))
{
XmldocStyle = style;
XmldocSettings = settings;
}

public XmldocStyle XmldocStyle { get; }
public XmldocSettings XmldocSettings { get; }

public XElement[]? ExtraRemarks { get; set; }

static Grammar CreateGrammar (XmldocStyle style)

static Grammar CreateGrammar (XmldocSettings settings)
{
return new SourceJavadocToXmldocGrammar (style) {
return new SourceJavadocToXmldocGrammar (settings) {
LanguageFlags = LanguageFlags.Default | LanguageFlags.CreateAst,
};
}
Expand Down Expand Up @@ -102,13 +102,13 @@ IEnumerable<XNode> CreateParseIterator (ParseTree parseTree)
var summary = CreateSummaryNode (info);
if (summary != null)
yield return summary;
var style = (ImportJavadoc) XmldocStyle;
var style = (ImportJavadoc) XmldocSettings.Style;
if (style.HasFlag (ImportJavadoc.Remarks) &&
(info.Remarks.Count > 0 || ExtraRemarks?.Length > 0)) {
yield return new XElement ("remarks", info.Remarks, ExtraRemarks);
(info.Remarks.Count > 0 || XmldocSettings.ExtraRemarks?.Length > 0)) {
yield return new XElement ("remarks", info.Remarks, XmldocSettings.ExtraRemarks);
}
else if (style.HasFlag (ImportJavadoc.ExtraRemarks) && ExtraRemarks?.Length > 0) {
yield return new XElement ("remarks", ExtraRemarks);
else if (style.HasFlag (ImportJavadoc.ExtraRemarks) && XmldocSettings.ExtraRemarks?.Length > 0) {
yield return new XElement ("remarks", XmldocSettings.ExtraRemarks);
}
foreach (var n in info.Returns) {
yield return n;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Xml.Linq;

namespace Java.Interop.Tools.JavaSource
{
public class XmldocSettings
{
public string DocRootValue { get; set; } = string.Empty;
public XElement []? ExtraRemarks { get; set; }
public XmldocStyle Style { get; set; } = XmldocStyle.Full;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,21 @@ public void PreBlockDeclaration ()
r.Root.AstNode.ToString ());

}

[Test]
public void HyperLinkDeclaration ()
{
var p = CreateParser (g => g.HtmlTerms.InlineHyperLinkDeclaration);

var r = p.Parse ("<a href=\"https://developer.android.com/guide/topics/manifest/application-element.html\">application</a>");
Assert.IsFalse (r.HasErrors (), DumpMessages (r, p));
Assert.AreEqual ("<see href=\"https://developer.android.com/guide/topics/manifest/application-element.html\">application</see>",
r.Root.AstNode.ToString ());

r = p.Parse ("<a href=\"AutofillService.html#FieldClassification\">field classification</a>");
Assert.IsFalse (r.HasErrors (), DumpMessages (r, p));
Assert.AreEqual ("\"AutofillService.html#FieldClassification\"&gt;field classification",
r.Root.AstNode.ToString ());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void DocRootDeclaration ()

var r = p.Parse ("{@docRoot}");
Assert.IsFalse (r.HasErrors (), DumpMessages (r, p));
Assert.AreEqual ("[TODO: @docRoot]", r.Root.AstNode.ToString ());
Assert.AreEqual (DocRootPrefixExpected, r.Root.AstNode.ToString ());
}

[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,16 @@ namespace Java.Interop.Tools.JavaSource.Tests
[TestFixture]
public class SourceJavadocToXmldocGrammarFixture {

protected const string DocRootPrefixActual = "https://developer.android.com";
protected const string DocRootPrefixExpected = DocRootPrefixActual + "/";

public static Parser CreateParser (Func<SourceJavadocToXmldocGrammar, NonTerminal> root)
{
var g = new SourceJavadocToXmldocGrammar (XmldocStyle.Full) {
var g = new SourceJavadocToXmldocGrammar (new XmldocSettings {
Style = XmldocStyle.Full,
DocRootValue = DocRootPrefixActual,
})
{
LanguageFlags = LanguageFlags.Default | LanguageFlags.CreateAst,
};
g.Root = root (g);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ public class SourceJavadocToXmldocParserTests : SourceJavadocToXmldocGrammarFixt
public void TryParse (ParseResult parseResult)
{
ParseTree parseTree;
var p = new SourceJavadocToXmldocParser (XmldocStyle.Full);
var p = new SourceJavadocToXmldocParser (new XmldocSettings {
Style = XmldocStyle.Full,
DocRootValue = DocRootPrefixActual,
});
var n = p.TryParse (parseResult.Javadoc, null, out parseTree);
Assert.IsFalse (parseTree.HasErrors (), DumpMessages (parseTree, p));
Assert.AreEqual (parseResult.FullXml, GetMemberXml (n), $"while parsing input: ```{parseResult.Javadoc}```");

p = new SourceJavadocToXmldocParser (XmldocStyle.IntelliSense);
p = new SourceJavadocToXmldocParser (new XmldocSettings {
Style = XmldocStyle.IntelliSense,
DocRootValue = DocRootPrefixActual,
});
n = p.TryParse (parseResult.Javadoc, null, out parseTree);
Assert.IsFalse (parseTree.HasErrors (), DumpMessages (parseTree, p));
Assert.AreEqual (parseResult.IntelliSenseXml, GetMemberXml (n), $"while parsing input: ```{parseResult.Javadoc}```");
Expand Down Expand Up @@ -168,6 +174,28 @@ more description here.</para>
</member>",
IntelliSenseXml = @"<member>
<summary>Summary.</summary>
</member>",
},
new ParseResult {
Javadoc = @"See <a href=""http://man7.org/linux/man-pages/man2/accept.2.html"">accept(2)</a>. Insert
more description here.
How about another link <a href=""http://man7.org/linux/man-pages/man2/accept.2.html"">accept(2)</a>
@param manifest The value of the <a
href=""{@docRoot}guide/topics/manifest/manifest-element.html#vcode"">{@code
android:versionCode}</a> manifest attribute.
",
FullXml = $@"<member>
<param name=""manifest"">The value of the <see href=""{DocRootPrefixExpected}guide/topics/manifest/manifest-element.html#vcode""><c>android:versionCode</c></see> manifest attribute.</param>
<summary>See <see href=""http://man7.org/linux/man-pages/man2/accept.2.html"">accept(2)</see>.</summary>
<remarks>
<para>See <see href=""http://man7.org/linux/man-pages/man2/accept.2.html"">accept(2)</see>. Insert
more description here.
How about another link <see href=""http://man7.org/linux/man-pages/man2/accept.2.html"">accept(2)</see></para>
</remarks>
</member>",
IntelliSenseXml = $@"<member>
<param name=""manifest"">The value of the <see href=""{DocRootPrefixExpected}guide/topics/manifest/manifest-element.html#vcode""><c>android:versionCode</c></see> manifest attribute.</param>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<see href="…"/> is a valid construct? I wonder when that happened…

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it happened in 2017. Now I feel old. mono/api-doc-tools@fb07047

<summary>See <see href=""http://man7.org/linux/man-pages/man2/accept.2.html"">accept(2)</see>.</summary>
</member>",
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public sealed class JavadocInfo {
public XElement[] Copyright { get; set; }

public XmldocStyle XmldocStyle { get; set; }
public string DocRootReplacement { get; set; }

string MemberDescription;

Expand All @@ -44,13 +45,15 @@ public static JavadocInfo CreateInfo (XElement element, XmldocStyle style, bool
var extras = GetExtra (element, style, declaringJniType, declaringMemberName, declaringMemberParamString, appendCopyrightExtra);
XElement[] extra = extras.Extras;
XElement[] copyright = extras.Copyright;
string docRoot = extras.DocRoot;

if (string.IsNullOrEmpty (javadoc) && extra == null)
return null;

var info = new JavadocInfo () {
ExtraRemarks = extra,
Copyright = copyright,
DocRootReplacement = docRoot,
Javadoc = javadoc,
MemberDescription = declaringMemberName == null
? declaringJniType
Expand Down Expand Up @@ -95,10 +98,10 @@ public static JavadocInfo CreateInfo (XElement element, XmldocStyle style, bool
return (declaringJniType, declaringMemberName, declaringMemberParameterString);
}

static (XElement[] Extras, XElement[] Copyright) GetExtra (XElement element, XmldocStyle style, string declaringJniType, string declaringMemberName, string declaringMemberParameterString, bool appendCopyrightExtra)
static (XElement[] Extras, XElement[] Copyright, string DocRoot) GetExtra (XElement element, XmldocStyle style, string declaringJniType, string declaringMemberName, string declaringMemberParameterString, bool appendCopyrightExtra)
{
if (!style.HasFlag (XmldocStyle.IntelliSenseAndExtraRemarks))
return (null, null);
return (null, null, null);

XElement javadocMetadata = null;
while (element != null) {
Expand All @@ -111,10 +114,12 @@ public static JavadocInfo CreateInfo (XElement element, XmldocStyle style, bool

List<XElement> extra = null;
IEnumerable<XElement> copyright = null;
string docRoot = null;
if (javadocMetadata != null) {
var link = javadocMetadata.Element ("link");
var urlPrefix = (string) link.Attribute ("prefix");
var linkStyle = (string) link.Attribute ("style");
docRoot = (string) link.Attribute ("docroot");
var kind = ParseApiLinkStyle (linkStyle);

XElement docLink = null;
Expand All @@ -128,7 +133,7 @@ public static JavadocInfo CreateInfo (XElement element, XmldocStyle style, bool
extra.AddRange (copyright);
}
}
return (extra?.ToArray (), copyright?.ToArray ());
return (extra?.ToArray (), copyright?.ToArray (), docRoot);
}

static ApiLinkStyle ParseApiLinkStyle (string style)
Expand Down Expand Up @@ -159,9 +164,11 @@ public IEnumerable<XNode> ParseJavadoc ()
IEnumerable<XNode> nodes = null;

try {
var parser = new SourceJavadocToXmldocParser (XmldocStyle) {
ExtraRemarks = ExtraRemarks,
};
var parser = new SourceJavadocToXmldocParser (new XmldocSettings {
Style = XmldocStyle,
ExtraRemarks = ExtraRemarks,
DocRootValue = DocRootReplacement,
});
nodes = parser.TryParse (Javadoc, fileName: null, out tree);
}
catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static void generateParamsTxt(String filename, JniPackagesInfo packages) throws

static void generateXml(JavaSourceUtilsOptions options, JniPackagesInfo packages) throws Throwable {
try (final JavadocXmlGenerator javadocXmlGen = new JavadocXmlGenerator(options.outputJavadocXml)) {
javadocXmlGen.writeCopyrightInfo(options.docCopyrightFile, options.docUrlPrefix, options.docUrlStyle);
javadocXmlGen.writeCopyrightInfo(options.docCopyrightFile, options.docUrlPrefix, options.docUrlStyle, options.docRootUrl);
javadocXmlGen.writePackages(packages);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public class JavaSourceUtilsOptions implements AutoCloseable {
" Stored in //javadoc-metadata/link/@style.\n" +
" Supported styles include:\n" +
" - developer.android.com/reference@2020-Nov\n" +
" --doc-root-url URL Base URL to use in place of @{docRoot} elements.\n" +
" Stored in //javadoc-metadata/link/@docroot.\n" +
"\n" +
"Output file options:\n" +
" -P, --output-params FILE Write method parameter names to FILE.\n" +
Expand All @@ -94,6 +96,7 @@ public class JavaSourceUtilsOptions implements AutoCloseable {
public File docCopyrightFile;
public String docUrlPrefix;
public String docUrlStyle;
public String docRootUrl;

private final Collection<File> sourceDirectoryFiles = new ArrayList<File>();
private File extractedTempDir;
Expand Down Expand Up @@ -204,6 +207,11 @@ private final JavaSourceUtilsOptions parse(Iterator<String> args) throws IOExcep
docUrlStyle = style;
break;
}
case "--doc-root-url": {
final String docRoot = getNextOptionValue(args, arg);
docRootUrl = docRoot;
break;
}
case "-j":
case "--jar": {
final File file = getNextOptionFile(args, arg);
Expand Down
Loading