Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs
diff options
context:
space:
mode:
authorJérémie Laval <jeremie.laval@gmail.com>2013-03-23 19:07:47 +0400
committerJérémie Laval <jeremie.laval@gmail.com>2013-03-23 19:11:49 +0400
commit605e4d6313259e649542e1ba8aff8326027d9b36 (patch)
treedaacffedaa0814191c0675b7e9e698db630ed808 /mcs
parentab79cb82bc59d4858ffa6ff0e13ce9aeb2aabaeb (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.cs24
-rw-r--r--mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs47
-rw-r--r--mcs/class/monodoc/Test/Monodoc/HelpSourceTests.cs22
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]