Skip to content

Commit

Permalink
[Java.Interop.Tools.JavaSource] Handle common parsing exceptions (#1060)
Browse files Browse the repository at this point in the history
Fixes the 91 instances of exceptions being thrown when generating API
docs for the API-33 version of Mono.Android.  The two most common
instances were:

	System.IndexOutOfRangeException: Index was outside the bounds of the array.
	  at Java.Interop.Tools.JavaSource.UnknownHtmlElementStartTerminal.TryMatch (Irony.Parsing.ParsingContext context, Irony.Parsing.ISourceStream source) [0x0003e] in /Users/builder/azdo/_work/4/s/external/Java.Interop/src/Java.Interop.Tools.JavaSource/Java.Interop.Tools.JavaSource/SourceJavadocToXmldocGrammar.HtmlBnfTerms.cs:390

	System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
	Parameter name: index
	  at System.Collections.Generic.List`1[T].get_Item (System.Int32 index) [0x00009] in <08f46039e5064c628bf7795f9b970b7b>:0
	  at Java.Interop.Tools.JavaSource.SourceJavadocToXmldocGrammar+BlockTagsBnfTerms+<>c__DisplayClass1_0.<CreateRules>b__8 (Irony.Ast.AstContext context, Irony.Parsing.ParseTreeNode parseNode) [0x00025] in /Users/builder/azdo/_work/4/s/external/Java.Interop/src/Java.Interop.Tools.JavaSource/Java.Interop.Tools.JavaSource/SourceJavadocToXmldocGrammar.BlockTagsBnfTerms.cs:151

35 of the 118 href element parsing errors have also been fixed.
  • Loading branch information
pjcollins authored Nov 29, 2022
1 parent 984711a commit 3a9f770
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,12 @@ internal void CreateRules (SourceJavadocToXmldocGrammar grammar)
if (!grammar.ShouldImport (ImportJavadoc.ReturnTag)) {
return;
}
// When encountering multiple @return keys in a line, append subsequent @return key content to the original <returns> element.
var jdi = FinishParse (context, parseNode);
// If we have no return value, continue
if (parseNode.ChildNodes.Count < 2) {
return;
}
// When encountering multiple @return keys in a line, append subsequent @return key content to the original <returns> element.
if (jdi.Returns.Count == 0) {
var r = new XElement ("returns",
AstNodeToXmlContent (parseNode.ChildNodes [1]));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq;

using Irony.Ast;
Expand Down Expand Up @@ -111,20 +113,17 @@ internal void CreateRules (SourceJavadocToXmldocGrammar grammar)
}
}

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) &&
var seeElement = TryParseHRef (unparsedAElementValue);
if (seeElement == null)
seeElement = TryParseHRef (WebUtility.HtmlDecode (unparsedAElementValue), logError: true);

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;
parseNode.AstNode = seeElement;
} else {
// TODO: Need to convert relative paths or code references to appropriate CREF value.
parseNode.AstNode = new XText (unparsedAElementValue);
}
};

Expand Down Expand Up @@ -185,6 +184,17 @@ static IEnumerable<XElement> GetParagraphs (ParseTreeNodeList children)
}
}

static XElement? TryParseHRef (string unparsedAElementValue, bool logError = false)
{
try {
return XElement.Parse ($"<see href={unparsedAElementValue}</see>");
} catch (Exception x) {
if (logError)
Console.Error.WriteLine ($"## Unable to parse HTML element: <see href={unparsedAElementValue}</see>\n{x.GetType ()}: {x.Message}");
return null;
}
}

public readonly NonTerminal AllHtmlTerms = new NonTerminal (nameof (AllHtmlTerms), ConcatChildNodes);

public readonly NonTerminal TopLevelInlineDeclaration = new NonTerminal (nameof (TopLevelInlineDeclaration), ConcatChildNodes);
Expand Down Expand Up @@ -387,7 +397,7 @@ public override void Init (GrammarData grammarData)
source.PreviewPosition += 1;
int start = source.Location.Position;
int stop = start;
while (source.Text [stop] != '>' && stop < source.Text.Length)
while (stop < source.Text.Length && source.Text [stop] != '>' )
stop++;
if (addingRemarks) {
Console.Error.WriteLine ($"# Unsupported HTML element: {source.Text.Substring (start, stop - start)}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public void HyperLinkDeclaration ()
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=\"http://www.ietf.org/rfc/rfc2396.txt\">RFC&nbsp;2396: Uniform Resource Identifiers (URI): Generic Syntax</a>");
Assert.IsFalse (r.HasErrors (), DumpMessages (r, p));
Assert.AreEqual ("<see href=\"http://www.ietf.org/rfc/rfc2396.txt\">RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax</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",
Expand Down

0 comments on commit 3a9f770

Please sign in to comment.