diff options
author | Jérémie Laval <jeremie.laval@gmail.com> | 2013-03-23 19:07:47 +0400 |
---|---|---|
committer | Jérémie Laval <jeremie.laval@gmail.com> | 2013-03-23 19:11:49 +0400 |
commit | 605e4d6313259e649542e1ba8aff8326027d9b36 (patch) | |
tree | daacffedaa0814191c0675b7e9e698db630ed808 /mcs | |
parent | ab79cb82bc59d4858ffa6ff0e13ce9aeb2aabaeb (diff) |
[monodoc] Remove previous horrible generic backtick notation hack and properly handle them in node search.
Diffstat (limited to 'mcs')
-rw-r--r-- | mcs/class/monodoc/Monodoc.Ecma/EcmaDesc.cs | 24 | ||||
-rw-r--r-- | mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs | 47 | ||||
-rw-r--r-- | mcs/class/monodoc/Test/Monodoc/HelpSourceTests.cs | 22 |
3 files changed, 72 insertions, 21 deletions
diff --git a/mcs/class/monodoc/Monodoc.Ecma/EcmaDesc.cs b/mcs/class/monodoc/Monodoc.Ecma/EcmaDesc.cs index 5f4349609ac..c16645971de 100644 --- a/mcs/class/monodoc/Monodoc.Ecma/EcmaDesc.cs +++ b/mcs/class/monodoc/Monodoc.Ecma/EcmaDesc.cs @@ -319,27 +319,11 @@ namespace Monodoc.Ecma { if (args == null || !args.Any ()) return string.Empty; + // If we only have the number of generic arguments, use ` notation + if (args.First () == null) + return "`" + args.Count (); - IEnumerable<string> argsList = null; - - // HACK: If we don't have fully specified EcmaDesc for generic arguments - // we use the most common names for the argument length configuration - if (args.Any (a => a == null)) { - var argCount = args.Count (); - switch (argCount) { - case 1: - argsList = new string[] { "T" }; - break; - case 2: - argsList = new string[] { "TKey", "TValue" }; - break; - default: - argsList = Enumerable.Range (1, argCount).Select (i => "T" + i); - break; - } - } else { - argsList = args.Select (t => FormatNamespace (t) + t.ToCompleteTypeName ()); - } + IEnumerable<string> argsList = args.Select (t => FormatNamespace (t) + t.ToCompleteTypeName ()); return "<" + string.Join (",", argsList) + ">"; } diff --git a/mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs b/mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs index 1633ae3800e..e3371d141d0 100644 --- a/mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs +++ b/mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs @@ -212,7 +212,10 @@ namespace Monodoc.Providers currentNode = result; result = null; searchNode.Caption = desc.ToCompleteTypeName (); - index = currentNode.ChildNodes.BinarySearch (searchNode, EcmaTypeNodeComparer.Instance); + if (!desc.GenericTypeArgumentsIsNumeric) + index = currentNode.ChildNodes.BinarySearch (searchNode, EcmaTypeNodeComparer.Instance); + else + index = GenericTypeBacktickSearch (currentNode.ChildNodes, desc); if (index >= 0) result = currentNode.ChildNodes[index]; if ((desc.DescKind == EcmaDesc.Kind.Type && !desc.IsEtc) || index < 0) @@ -249,6 +252,48 @@ namespace Monodoc.Providers return result; } + static int GenericTypeBacktickSearch (IList<Node> childNodes, EcmaDesc desc) + { + /* Our strategy is to search for the non-generic variant of the type + * (which in most case should fail) and then use the closest index + * to linearily search for the generic variant with the right generic arg number + */ + var searchNode = new Node () { Caption = desc.TypeName }; + int index = childNodes.BinarySearch (searchNode, EcmaTypeNodeComparer.Instance); + // Place the index in the right start position + if (index < 0) + index = ~index; + + for (int i = index; i < childNodes.Count; i++) { + var currentNode = childNodes[i]; + // Find the index of the generic argument list + int genericIndex = currentNode.Caption.IndexOf ('<'); + // If we are not on the same base type name anymore, there is no point + int captionSlice = genericIndex != -1 ? genericIndex : currentNode.Caption.LastIndexOf (' '); + if (string.Compare (searchNode.Caption, 0, + currentNode.Caption, 0, + Math.Max (captionSlice, searchNode.Caption.Length), + StringComparison.Ordinal) != 0) + break; + + var numGenerics = CountTypeGenericArguments (currentNode.Caption, genericIndex); + if (numGenerics == desc.GenericTypeArguments.Count) { + // Simple comparison if we are not looking for an inner type + if (desc.NestedType == null) + return i; + // If more complicated, we fallback to using EcmaUrlParser + var caption = currentNode.Caption; + caption = "T:" + caption.Substring (0, caption.LastIndexOf (' ')).Replace ('.', '+'); + EcmaDesc otherDesc; + var parser = new EcmaUrlParser (); + if (parser.TryParse (caption, out otherDesc) && desc.NestedType.Equals (otherDesc.NestedType)) + return i; + } + } + + return -1; + } + // This comparer returns the answer straight from caption comparison class EcmaGenericNodeComparer : IComparer<Node> { diff --git a/mcs/class/monodoc/Test/Monodoc/HelpSourceTests.cs b/mcs/class/monodoc/Test/Monodoc/HelpSourceTests.cs index fdcdb679695..0e36598fb5b 100644 --- a/mcs/class/monodoc/Test/Monodoc/HelpSourceTests.cs +++ b/mcs/class/monodoc/Test/Monodoc/HelpSourceTests.cs @@ -113,6 +113,28 @@ namespace MonoTests.Monodoc Assert.IsTrue (rootTree.RenderUrl ("T:System.Collections.Concurrent.IProducerConsumerCollection`1", generator, out result), "#1"); Assert.IsTrue (rootTree.RenderUrl ("T:System.Collections.Generic.Dictionary`2", generator, out result), "#2"); Assert.IsTrue (rootTree.RenderUrl ("T:System.Action`4", generator, out result), "#3"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.EventHandler`1", generator, out result), "#4"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`5", generator, out result), "#5a"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`4", generator, out result), "#5b"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`6", generator, out result), "#5c"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`7", generator, out result), "#5d"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`3", generator, out result), "#5e"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`2", generator, out result), "#5f"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`1", generator, out result), "#5g"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`8", generator, out result), "#5h"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Func`9", generator, out result), "#5i"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Action`3", generator, out result), "#6a"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Action`2", generator, out result), "#6b"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Action`4", generator, out result), "#6c"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.IComparable`1", generator, out result), "#7"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Lazy`1", generator, out result), "#8"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Tuple`1", generator, out result), "#9a"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Tuple`2", generator, out result), "#9b"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Tuple`3", generator, out result), "#9c"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Tuple`4", generator, out result), "#9d"); + Assert.IsTrue (rootTree.RenderUrl ("T:System.Collections.Generic.Dictionary`2+ValueCollection", generator, out result), "#10"); + Assert.IsFalse (rootTree.RenderUrl ("T:System.EventHandler`2", generator, out result), "#11"); + Assert.IsFalse (rootTree.RenderUrl ("T:System.Lazy`2", generator, out result), "#12"); } [Test] |