瀏覽代碼

improvements and additional tests for nested types

Fred VanEijk 10 年之前
父節點
當前提交
a90a0d4917

+ 35 - 1
Jint.Tests/Runtime/Domain/ClassWithStaticFields.cs

@@ -14,5 +14,39 @@
         {
             Setter = "Setter";
         }
-    }
+    }
+
+    public class Nested
+    {
+        public class ClassWithStaticFields
+        {
+            public static string Get = "Get";
+            public static string Set = "Set";
+
+            public static string Getter
+            {
+                get { return "Getter"; }
+            }
+
+            public static string Setter
+            {
+                get
+                {
+                    return _setter;
+                }
+                set
+                {
+                    _setter = value;
+                }
+            }
+
+            public static readonly string Readonly = "Readonly";
+            private static string _setter;
+
+            static ClassWithStaticFields()
+            {
+                Setter = "Setter";
+            }
+        }
+    }
 }

+ 27 - 0
Jint.Tests/Runtime/Domain/Shape.cs

@@ -16,6 +16,33 @@ namespace Shapes
 
     public class Circle : Shape
     {
+        public class Meta
+        {
+            public Meta()
+            {
+                _description = "descp";
+            }
+          private string _description;
+
+          public string Description
+          {
+            get
+            {
+              return _description;
+            }
+            set
+            {
+              _description = value;
+            }
+          }
+
+          public enum Usage
+          {
+            Public,
+            Private,
+            Internal = 11
+          }
+        }
 
         public enum Kind
         {

+ 92 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -1155,5 +1155,97 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void ShouldImportNamespaceNestedNestedType()
+        {
+          RunTest(@"
+                var meta = importNamespace('Shapes.Circle.Meta');
+                var usages = meta.Usage;
+                assert(usages.Public === 0);
+                assert(usages.Private === 1);
+                assert(usages.Internal === 11);
+            ");
+        }
+
+        [Fact]
+        public void ShouldGetNestedNestedProp()
+        {
+            RunTest(@"
+                var meta = importNamespace('Shapes.Circle');
+                var m = new meta.Meta();
+                assert(m.Description === 'descp');
+            ");
+        }
+
+        [Fact]
+        public void ShouldSetNestedNestedProp()
+        {
+            RunTest(@"
+                var meta = importNamespace('Shapes.Circle');
+                var m = new meta.Meta();
+                m.Description = 'hello';
+                assert(m.Description === 'hello');
+            ");
+        }
+
+        [Fact]
+        public void CanGetStaticNestedField()
+        {
+            RunTest(@"
+                var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
+                var statics = domain.ClassWithStaticFields;
+                assert(statics.Get == 'Get');
+            ");
+        }
+
+        [Fact]
+        public void CanSetStaticNestedField()
+        {
+            RunTest(@"
+                var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
+                var statics = domain.ClassWithStaticFields;
+                statics.Set = 'hello';
+                assert(statics.Set == 'hello');
+            ");
+
+            Assert.Equal(Nested.ClassWithStaticFields.Set, "hello");
+        }
+
+        [Fact]
+        public void CanGetStaticNestedAccessor()
+        {
+            RunTest(@"
+                var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
+                var statics = domain.ClassWithStaticFields;
+                assert(statics.Getter == 'Getter');
+            ");
+        }
+
+        [Fact]
+        public void CanSetStaticNestedAccessor()
+        {
+            RunTest(@"
+                var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
+                var statics = domain.ClassWithStaticFields;
+                statics.Setter = 'hello';
+                assert(statics.Setter == 'hello');
+            ");
+
+            Assert.Equal(Nested.ClassWithStaticFields.Setter, "hello");
+        }
+
+        [Fact]
+        public void CantSetStaticNestedReadonly()
+        {
+            RunTest(@"
+                var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
+                var statics = domain.ClassWithStaticFields;
+                statics.Readonly = 'hello';
+                assert(statics.Readonly == 'Readonly');
+            ");
+
+            Assert.Equal(Nested.ClassWithStaticFields.Readonly, "Readonly");
+        }
+
     }
 }

+ 57 - 20
Jint/Runtime/Interop/NamespaceReference.cs

@@ -1,4 +1,5 @@
-using System;
+using System;
+using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Reflection;
@@ -110,7 +111,7 @@ namespace Jint.Runtime.Interop
                 }
             }
 
-            // search in lookup asemblies
+            // search in lookup assemblies
             foreach (var assembly in Engine.Options.GetLookupAssemblies())
             {
                 type = assembly.GetType(path);
@@ -118,30 +119,66 @@ namespace Jint.Runtime.Interop
                 {
                     Engine.TypeCache.Add(path, type);
                     return TypeReference.CreateTypeReference(Engine, type);
-                }
-				       
-                var lastPeriodPos = path.LastIndexOf(".", StringComparison.Ordinal);
-                var trimPath = path.Substring(0, lastPeriodPos);
-                var typeName = path.Substring(lastPeriodPos+1, path.Length - lastPeriodPos-1);
-                type = assembly.GetType(trimPath);
-                if (type != null)
-                foreach (Type nType in type.GetNestedTypes(BindingFlags.Public))
-                {
-	                if (nType.FullName.Contains(trimPath+"+"+typeName))
-	                {
-		                Engine.TypeCache.Add(path, nType);
-		                return TypeReference.CreateTypeReference(Engine, nType);
-	                }
-                }
+                }
+
+                var lastPeriodPos = path.LastIndexOf(".", StringComparison.Ordinal);
+                var trimPath = path.Substring(0, lastPeriodPos);
+                type = GetType(assembly, trimPath);
+                if (type != null)
+                  foreach (Type nType in GetAllNestedTypes(type))
+                  {
+                    if (nType.FullName.Replace("+", ".").Equals(path.Replace("+", ".")))
+                    {
+                      Engine.TypeCache.Add(path.Replace("+", "."), nType);
+                      return TypeReference.CreateTypeReference(Engine, nType);
+                    }
+                  }            
             }
 
             // the new path doesn't represent a known class, thus return a new namespace instance
 
             Engine.TypeCache.Add(path, null);
             return new NamespaceReference(Engine, path);
-        }
-
-        public override PropertyDescriptor GetOwnProperty(string propertyName)
+        }
+
+        /// <summary>   Gets a type. </summary>
+        ///<remarks>Nested type separators are converted to '.' instead of '+' </remarks>
+        /// <param name="assembly"> The assembly. </param>
+        /// <param name="typeName"> Name of the type. </param>
+        ///
+        /// <returns>   The type. </returns>
+
+        private static Type GetType(Assembly assembly, string typeName)
+        {
+            Type[] types = assembly.GetTypes();
+            foreach (Type t in types)
+            {
+                if (t.FullName.Replace("+", ".") == typeName.Replace("+", "."))
+                {
+                    return t;
+                }
+            }
+            return null;
+        }
+
+        private static IEnumerable<Type> GetAllNestedTypes(Type type)
+        {
+          var types = new List<Type>();
+          AddNestedTypesRecursively(types, type);
+          return types.ToArray();
+        }
+
+        private static void AddNestedTypesRecursively(List<Type> types, Type type)
+        {
+          Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public);
+          foreach (Type nestedType in nestedTypes)
+          {
+            types.Add(nestedType);
+            AddNestedTypesRecursively(types, nestedType);
+          }
+        }
+
+      public override PropertyDescriptor GetOwnProperty(string propertyName)
         {
             return PropertyDescriptor.Undefined;
         }