[monodoc] Fixed several issues with `.ToEcmaCRef` method.
authorJoel Martinez <joelmartinez@gmail.com>
Thu, 29 Oct 2015 19:36:29 +0000 (15:36 -0400)
committerJoel Martinez <joelmartinez@gmail.com>
Tue, 3 Nov 2015 20:13:51 +0000 (15:13 -0500)
In particular:

- Issues with cref formatting for subtypes.
- Added support for Explicitly implemented members.
- Added support for generic member parameters.

A number of unit tests were added to verify this functionality.

mcs/class/monodoc/Monodoc.Ecma/EcmaDesc.cs
mcs/class/monodoc/Test/Monodoc.Ecma/EcmaUrlTests.cs

index ccf4b4bb12d91b9720c874de7062d13928296514..2f46c6cc0fddccb6aa562c3bc515ef73c0727b35 100644 (file)
@@ -226,32 +226,24 @@ namespace Monodoc.Ecma
                        return sb.ToString ();
                }
 
-               void ConstructCRef (StringBuilder sb)
+               void ConstructCRef (StringBuilder sb, bool skipLeadingDot = false)
                {
+                       if (string.IsNullOrEmpty (Namespace))
+                               skipLeadingDot = true;
+
                        sb.Append (Namespace);
                        if (DescKind == Kind.Namespace)
                                return;
 
-                       sb.Append ('.');
+                       if (!skipLeadingDot)
+                               sb.Append ('.');
+
                        sb.Append (TypeName);
-                       if (GenericTypeArguments != null && GenericTypeArgumentsIsNumeric) {
-                               sb.AppendFormat ("`{0}", GenericTypeArgumentsCount);
-                       } else if (GenericTypeArguments != null) {
-                               sb.Append ('<');
-                               int i=0;
-                               foreach (var t in GenericTypeArguments) {
-                                       if (i > 0) {
-                                               sb.Append (",");
-                                       }
-                                       t.ConstructCRef (sb);
+                       AppendGenericArguments (sb, GenericTypeArguments, GenericTypeArgumentsIsNumeric, GenericTypeArgumentsCount);
 
-                                       i++;
-                               }
-                               sb.Append ('>');
-                       }
                        if (NestedType != null) {
                                sb.Append ('+');
-                               NestedType.ConstructCRef (sb);
+                               NestedType.ConstructCRef (sb, skipLeadingDot: true);
                        }
                        if (ArrayDimensions != null && ArrayDimensions.Count > 0) {
                                for (int i = 0; i < ArrayDimensions.Count; i++) {
@@ -263,9 +255,18 @@ namespace Monodoc.Ecma
                        if (DescKind == Kind.Type)
                                return;
 
+                       if (ExplicitImplMember != null) {
+                               sb.Append ('$');
+                               ExplicitImplMember.DescKind = this.DescKind;
+                               ExplicitImplMember.ConstructCRef (sb, skipLeadingDot: false);
+                               return;
+                       }
+
                        sb.Append (".");
                        sb.Append (MemberName);
 
+                       AppendGenericArguments (sb, GenericMemberArguments, GenericMemberArgumentsIsNumeric, GenericMemberArgumentsCount);
+
                        if (MemberArguments != null && MemberArgumentsCount > 0) {
                                sb.Append ("(");
                                int i=0;
@@ -280,6 +281,25 @@ namespace Monodoc.Ecma
                        }
                }
 
+               void AppendGenericArguments (StringBuilder sb, IEnumerable<EcmaDesc> arguments, bool isNumeric, int argumentsCount)
+               {
+                       if (arguments != null && isNumeric) {
+                               sb.AppendFormat ("`{0}", argumentsCount);
+                       } else if (arguments != null) {
+                               sb.Append ('<');
+                               int i=0;
+                               foreach (var t in arguments) {
+                                       if (i > 0) {
+                                               sb.Append (",");
+                                       }
+                                       t.ConstructCRef (sb);
+
+                                       i++;
+                               }
+                               sb.Append ('>');
+                       }
+               }
+
                public override string ToString ()
                {
                        return string.Format ("({8}) {0}::{1}{2}{3}{7} {4}{5}{6} {9} {10}",
index 1c8d44311e616b1b250ec5688addd98e553d3809..8e27bc08b13e52b531fbac1494e57989c73d3db9 100644 (file)
@@ -52,6 +52,22 @@ namespace MonoTests.Monodoc.Ecma
                        Assert.AreEqual (expected, actual, "Converted URL differs");
                }
 
+               void AssertEcmaString (string expected, EcmaDesc actual)
+               {
+                       string actualString = actual.ToEcmaCref ();
+                       Assert.AreEqual (expected, actualString);
+               }
+
+               IEnumerable<EcmaDesc> GenericTypeArgumentsList (params string[] parameters) 
+               {
+                       foreach (var p in parameters)
+                               yield return new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               TypeName = p,
+                                               Namespace = string.Empty
+                                       };
+               }
+
                [Test]
                public void CommonMethodUrlIsValidTest ()
                {
@@ -454,38 +470,370 @@ namespace MonoTests.Monodoc.Ecma
                        AssertUrlDesc (ast, "P:System.Web.SessionState.HttpSessionStateContainer$System.Web.SessionState.IHttpSessionState.Item(System.Int32)");
                }
 
-               /*              [Test]
-               public void TreeParsabilityTest ()
+               [Test]
+               public void ToEcmaCref_Namespace ()
                {
-                       var rootTree = RootTree.LoadTree ("/home/jeremie/monodoc/");
-                       Node result;
-                       var generator = new CheckGenerator ();
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Namespace,
+                               Namespace = "System.IO",
+                       };
 
-                       foreach (var leaf in GetLeaves (rootTree.RootNode).Where (IsEcmaNode))
-                               AssertUrl (leaf.PublicUrl);
+                       AssertEcmaString ("N:System.IO", actual);
                }
 
-               IEnumerable<Node> GetLeaves (Node node)
+               [Test]
+               public void ToEcmaCref_SimpleType ()
                {
-                       if (node == null)
-                               yield break;
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Type,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                       };
 
-                       if (node.IsLeaf)
-                               yield return node;
-                       else {
-                               foreach (var child in node.Nodes) {
-                                       if (!string.IsNullOrEmpty (child.Element) && !child.Element.StartsWith ("root:/"))
-                                               yield return child;
-                                       foreach (var childLeaf in GetLeaves (child))
-                                               yield return childLeaf;
-                               }
-                       }
+                       AssertEcmaString ("T:System.IO.Path", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_NestedType ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Type,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               NestedType = new EcmaDesc {
+                                       DescKind = EcmaDesc.Kind.Type,
+                                       TypeName = "TheNestedType",
+                               },
+                       };
+
+                       AssertEcmaString ("T:System.IO.Path+TheNestedType", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_NestedType_FourDeep ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Type,
+                               Namespace = "Mono",
+                               TypeName = "DocTest",
+                               NestedType = new EcmaDesc {
+                                       DescKind = EcmaDesc.Kind.Type,
+                                       TypeName = "NestedClass",
+                                       NestedType = new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               TypeName = "Double",
+                                               NestedType = new EcmaDesc {
+                                                       DescKind = EcmaDesc.Kind.Type,
+                                                       TypeName = "Triple",
+                                                       NestedType = new EcmaDesc {
+                                                               DescKind = EcmaDesc.Kind.Type,
+                                                               TypeName = "Quadruple",
+                                                       },
+                                               },
+                                       },
+                               },
+                       };
+
+                       string targetUrl = "T:Mono.DocTest+NestedClass+Double+Triple+Quadruple";
+                       AssertEcmaString (targetUrl, actual);
+                       AssertUrlDesc (actual, targetUrl);
+               }
+
+               [Test]
+               public void ToEcmaCref_NestedType_Field ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Field,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               NestedType = new EcmaDesc {
+                                       DescKind = EcmaDesc.Kind.Type,
+                                       TypeName = "TheNestedType",
+                               },
+                               MemberName = "NestedField"
+                       };
+
+                       AssertEcmaString ("F:System.IO.Path+TheNestedType.NestedField", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_SimpleType_WithGenerics ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Type,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               GenericTypeArguments = GenericTypeArgumentsList ("K").ToArray ()
+                       };
+
+                       AssertEcmaString ("T:System.IO.Path<K>", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Nestedype_WithGenerics ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Type,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               NestedType = new EcmaDesc {
+                                       DescKind = EcmaDesc.Kind.Type,
+                                       TypeName = "TheNestedType",
+                               },
+                               GenericTypeArguments = GenericTypeArgumentsList ("K").ToArray ()
+                       };
+
+                       AssertEcmaString ("T:System.IO.Path<K>+TheNestedType", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Nestedype_WithGenericsOnBoth ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Type,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               NestedType = new EcmaDesc {
+                                       DescKind = EcmaDesc.Kind.Type,
+                                       TypeName = "TheNestedType",
+                                       GenericTypeArguments = GenericTypeArgumentsList ("T", "V").ToArray (),
+                               },
+                               GenericTypeArguments = GenericTypeArgumentsList ("K").ToArray ()
+                       };
+
+                       AssertEcmaString ("T:System.IO.Path<K>+TheNestedType<T,V>", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Nestedype_Property_WithGenericsOnBoth ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Property,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               NestedType = new EcmaDesc {
+                                       DescKind = EcmaDesc.Kind.Type,
+                                       TypeName = "TheNestedType",
+                                       GenericTypeArguments = GenericTypeArgumentsList ("T", "V").ToArray (),
+                               },
+                               GenericTypeArguments = GenericTypeArgumentsList ("K").ToArray (),
+                               MemberName = "TheProperty"
+                       };
+
+                       AssertEcmaString ("P:System.IO.Path<K>+TheNestedType<T,V>.TheProperty", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Field ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Field,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               MemberName = "TheField"
+                       };
+
+                       AssertEcmaString ("F:System.IO.Path.TheField", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_ExplicitlyImplemented_Field ()
+               {
+                       var explicitImpl = new EcmaDesc {
+                               Namespace = "System.Web.SessionState",
+                               TypeName = "IHttpSessionState",
+                               MemberName = "Item",
+                       };
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Field,
+                               TypeName = "HttpSessionStateContainer",
+                               Namespace = "System.Web.SessionState",
+                               ExplicitImplMember = explicitImpl,
+                       };
+                       AssertEcmaString ("F:System.Web.SessionState.HttpSessionStateContainer$System.Web.SessionState.IHttpSessionState.Item", actual);
+               }               
+
+               [Test]
+               public void ToEcmaCref_Property ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Property,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               MemberName = "TheProperty",
+                       };
+
+                       AssertEcmaString ("P:System.IO.Path.TheProperty", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_ExplicitlyImplemented_Property ()
+               {
+                       var explicitImpl = new EcmaDesc {
+                               Namespace = "System.Web.SessionState",
+                               TypeName = "IHttpSessionState",
+                               MemberName = "Item",
+                       };
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Property,
+                               TypeName = "HttpSessionStateContainer",
+                               Namespace = "System.Web.SessionState",
+                               ExplicitImplMember = explicitImpl,
+                       };
+                       AssertEcmaString ("P:System.Web.SessionState.HttpSessionStateContainer$System.Web.SessionState.IHttpSessionState.Item", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_ExplicitlyImplemented_Method ()
+               {
+                       var explicitImpl = new EcmaDesc {
+                               Namespace = "System.Web.SessionState",
+                               TypeName = "IHttpSessionState",
+                               MemberName = "Item",
+                               MemberArguments = new [] {
+                                       new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               Namespace = "System",
+                                               TypeName = "Int32",
+                                       },
+                               },
+                       };
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Method,
+                               TypeName = "HttpSessionStateContainer",
+                               Namespace = "System.Web.SessionState",
+                               ExplicitImplMember = explicitImpl,
+                       };
+                       AssertEcmaString ("M:System.Web.SessionState.HttpSessionStateContainer$System.Web.SessionState.IHttpSessionState.Item(System.Int32)", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Event ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Event,
+                               Namespace = "System.IO",
+                               TypeName = "Path",
+                               MemberName = "TheEvent",
+                       };
+
+                       AssertEcmaString ("E:System.IO.Path.TheEvent", actual);
                }
 
-               bool IsEcmaNode (Node node)
+               [Test]
+               public void ToEcmaCref_Operator ()
                {
-                       var url = node.PublicUrl;
-                       return url != null && url.Length > 2 && url[1] == ':';
-               }*/
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Operator,
+                               Namespace = "System",
+                               TypeName = "Int32",
+                               MemberName = "Addition",
+                       };
+
+                       AssertEcmaString ("O:System.Int32.Addition", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Operator_Conversion ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Operator,
+                               Namespace = "System",
+                               TypeName = "Int32",
+                               MemberName = "ExplicitConversion",
+                               MemberArguments = new [] { 
+                                       new EcmaDesc { 
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               Namespace = "System",
+                                               TypeName = "Double",
+                                       },
+                                       new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               Namespace = "System",
+                                               TypeName = "Int32",
+                                       }
+                               },
+                       };
+
+                       AssertEcmaString ("O:System.Int32.ExplicitConversion(System.Double,System.Int32)", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Method ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Method,
+                               Namespace = "System",
+                               TypeName = "Int32",
+                               MemberName = "Add"
+                       };
+
+                       AssertEcmaString ("M:System.Int32.Add", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Method_Parameters ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Method,
+                               Namespace = "System",
+                               TypeName = "Int32",
+                               MemberName = "Add",
+                               MemberArguments = new [] { 
+                                       new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               Namespace = "System",
+                                               TypeName = "Double",
+                                       },
+                                       new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               Namespace = "System",
+                                               TypeName = "Int32",
+                                       },
+                               },
+                       };
+
+                       AssertEcmaString ("M:System.Int32.Add(System.Double,System.Int32)", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Method_Generics ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Method,
+                               Namespace = "System",
+                               TypeName = "Int32",
+                               MemberName = "Add",
+                               GenericMemberArguments = GenericTypeArgumentsList ("T", "K").ToArray (),
+                       };
+
+                       AssertEcmaString ("M:System.Int32.Add<T,K>", actual);
+               }
+
+               [Test]
+               public void ToEcmaCref_Method_Generics_PlusParameters ()
+               {
+                       var actual = new EcmaDesc {
+                               DescKind = EcmaDesc.Kind.Method,
+                               Namespace = "System",
+                               TypeName = "Int32",
+                               MemberName = "Add",
+                               GenericMemberArguments = GenericTypeArgumentsList ("T", "K").ToArray (),
+                               MemberArguments = new [] { 
+                                       new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               Namespace = "",
+                                               TypeName = "T",
+                                       },
+                                       new EcmaDesc {
+                                               DescKind = EcmaDesc.Kind.Type,
+                                               Namespace = "",
+                                               TypeName = "K",
+                                       },
+                               },
+                       };
+
+                       AssertEcmaString ("M:System.Int32.Add<T,K>(T,K)", actual);
+               }
        }
 }