2003-07-16 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / mbas / typemanager.cs
index 2f7413c9e5a9fcf165b6928c2cff4f46c61ac4e7..9332c1718fc92c76f6ee1b0cf65db022906fc2b0 100644 (file)
@@ -163,13 +163,13 @@ public class TypeManager {
        //   This is the type_cache from the assemblies to avoid
        //   hitting System.Reflection on every lookup.
        // </summary>
-       static Hashtable types;
+       static CaseInsensitiveHashtable types;
 
        // <remarks>
        //  This is used to hotld the corresponding TypeContainer objects
        //  since we need this in FindMembers
        // </remarks>
-       static Hashtable typecontainers;
+       static CaseInsensitiveHashtable typecontainers;
 
        // <remarks>
        //   Keeps track of those types that are defined by the
@@ -295,8 +295,8 @@ public class TypeManager {
                modules = null;
                user_types = new ArrayList ();
                
-               types = new Hashtable ();
-               typecontainers = new Hashtable ();
+               types = new CaseInsensitiveHashtable ();
+               typecontainers = new CaseInsensitiveHashtable ();
                
                builder_to_declspace = new PtrHashtable ();
                builder_to_attr = new PtrHashtable ();
@@ -456,8 +456,54 @@ public class TypeManager {
                modules = n;
        }
 
+       //
+       // Low-level lookup, cache-less
+       //
+       static Type LookupTypeReflection (string name)
+       {
+               Type t;
+
+               foreach (Assembly a in assemblies){
+                       t = a.GetType (name);
+                       if (t != null)
+                               return t;
+               }
+
+               foreach (ModuleBuilder mb in modules) {
+                       t = mb.GetType (name);
+                       if (t != null){
+                               return t;
+                       }
+               }
+               return null;
+       }
+
+       //
+       // This function is used when you want to avoid the lookups, and want to go
+       // directly to the source.  This will use the cache.
+       //
+       // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
+       // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
+       // way to test things other than doing a fullname compare
+       //
+       public static Type LookupTypeDirect (string name)
+       {
+               Type t = (Type) types [name];
+               if (t != null)
+                       return t;
+
+               t = LookupTypeReflection (name);
+               if (t == null)
+                       return null;
+
+               types [name] = t;
+               return t;
+       }
+       
        /// <summary>
-       ///   Returns the Type associated with @name
+       ///   Returns the Type associated with @name, takes care of the fact that
+       ///   reflection expects nested types to be separated from the main type
+       ///   with a "+" instead of a "."
        /// </summary>
        public static Type LookupType (string name)
        {
@@ -471,32 +517,44 @@ public class TypeManager {
                if (t != null)
                        return t;
 
-               foreach (Assembly a in assemblies){
-                       t = a.GetType (name);
-                       if (t != null){
-                               types [name] = t;
+               //
+               // Optimization: ComposedCast will work with an existing type, and might already have the
+               // full name of the type, so the full system lookup can probably be avoided.
+               //
+               
+               string [] elements = name.Split ('.');
+               int count = elements.Length;
 
-                               return t;
-                       }
-               }
+               for (int n = 1; n <= count; n++){
+                       string top_level_type = String.Join (".", elements, 0, n);
 
-               foreach (ModuleBuilder mb in modules) {
-                       t = mb.GetType (name);
-                       if (t != null) {
+                       t = (Type) types [top_level_type];
+                       if (t == null){
+                               t = LookupTypeReflection (top_level_type);
+                               if (t == null)
+                                       continue;
+                       }
+                       
+                       if (count == n){
                                types [name] = t;
                                return t;
-                       }
+                       } 
+                       
+                       string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
+                       t = LookupTypeDirect (newt);
+                       if (t != null)
+                               types [newt] = t;
+                       return t;
                }
-               
                return null;
        }
 
        //
        // Returns a list of all namespaces in the assemblies and types loaded.
        //
-       public static Hashtable GetNamespaces ()
+       public static CaseInsensitiveHashtable GetNamespaces ()
        {
-               Hashtable namespaces = new Hashtable ();
+               CaseInsensitiveHashtable namespaces = new CaseInsensitiveHashtable ();
 
                foreach (Assembly a in assemblies){
                        foreach (Type t in a.GetTypes ()){
@@ -625,7 +683,7 @@ public class TypeManager {
        /// <summary>
        ///    Returns the ConstructorInfo for "args"
        /// </summary>
-       static ConstructorInfo GetConstructor (Type t, Type [] args)
+       public static ConstructorInfo GetConstructor (Type t, Type [] args)
        {
                MemberList list;
                Signature sig;
@@ -880,7 +938,7 @@ public class TypeManager {
 
        const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
 
-       static Hashtable type_hash = new Hashtable ();
+       static CaseInsensitiveHashtable type_hash = new CaseInsensitiveHashtable ();
 
        /// <remarks>
        ///   This is the "old", non-cache based FindMembers() function.  We cannot use
@@ -890,7 +948,7 @@ public class TypeManager {
                                              MemberFilter filter, object criteria)
        {
                DeclSpace decl = (DeclSpace) builder_to_declspace [t];
-
+bf |= BindingFlags.IgnoreCase;
                //
                // `builder_to_declspace' contains all dynamic types.
                //
@@ -1034,7 +1092,47 @@ public class TypeManager {
                else
                        return false;
        }
-       
+
+       //
+       // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
+       //
+       public static bool IsUnmanagedType (Type t)
+       {
+               if (IsBuiltinType (t) && t != TypeManager.string_type)
+                       return true;
+
+               if (IsEnumType (t))
+                       return true;
+
+               if (t.IsPointer)
+                       return true;
+
+               if (IsValueType (t)){
+                       if (t is TypeBuilder){
+                               TypeContainer tc = LookupTypeContainer (t);
+
+                               foreach (Field f in tc.Fields){
+                                       if (f.FieldBuilder.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldBuilder.FieldType))
+                                               return false;
+                               }
+                       } else {
+                               FieldInfo [] fields = t.GetFields ();
+
+                               foreach (FieldInfo f in fields){
+                                       if (f.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldType))
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
+
+               return false;
+       }
+               
        public static bool IsValueType (Type t)
        {
                if (t.IsSubclassOf (TypeManager.value_type))
@@ -1074,7 +1172,10 @@ public class TypeManager {
        //
        public static bool IsNestedChildOf (Type type, Type parent)
        {
-               return IsSubclassOrNestedChildOf (type, parent) && !type.IsSubclassOf (parent);
+               if ((type == parent) || type.IsSubclassOf (parent))
+                       return false;
+               else
+                       return IsSubclassOrNestedChildOf (type, parent);
        }
 
        /// <summary>
@@ -1086,7 +1187,7 @@ public class TypeManager {
                }
        }
 
-       public static Hashtable TypeContainers {
+       public static CaseInsensitiveHashtable TypeContainers {
                get {
                        return typecontainers;
                }
@@ -1204,7 +1305,7 @@ public class TypeManager {
        //  This is a workaround the fact that GetValue is not
        //  supported for dynamic types
        // </remarks>
-       static Hashtable fields = new Hashtable ();
+       static CaseInsensitiveHashtable fields = new CaseInsensitiveHashtable ();
        static public bool RegisterFieldValue (FieldBuilder fb, object value)
        {
                if (fields.Contains (fb))
@@ -1220,7 +1321,7 @@ public class TypeManager {
                return fields [fb];
        }
 
-       static Hashtable fieldbuilders_to_fields = new Hashtable ();
+       static CaseInsensitiveHashtable fieldbuilders_to_fields = new CaseInsensitiveHashtable ();
        static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
        {
                if (fieldbuilders_to_fields.Contains (fb))
@@ -1235,12 +1336,12 @@ public class TypeManager {
                return (FieldBase) fieldbuilders_to_fields [fb];
        }
        
-       static Hashtable events;
+       static CaseInsensitiveHashtable events;
 
        static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
        {
                if (events == null)
-                       events = new Hashtable ();
+                       events = new CaseInsensitiveHashtable ();
 
                if (events.Contains (eb))
                        return false;
@@ -1270,12 +1371,12 @@ public class TypeManager {
                        return ei.GetAddMethod ();
        }
 
-       static Hashtable priv_fields_events;
+       static CaseInsensitiveHashtable priv_fields_events;
 
        static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
        {
                if (priv_fields_events == null)
-                       priv_fields_events = new Hashtable ();
+                       priv_fields_events = new CaseInsensitiveHashtable ();
 
                if (priv_fields_events.Contains (einfo))
                        return false;
@@ -1290,12 +1391,12 @@ public class TypeManager {
                return (MemberInfo) priv_fields_events [ei];
        }
                
-       static Hashtable properties;
+       static CaseInsensitiveHashtable properties;
        
        static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
        {
                if (properties == null)
-                       properties = new Hashtable ();
+                       properties = new CaseInsensitiveHashtable ();
 
                if (properties.Contains (pb))
                        return false;
@@ -1315,37 +1416,6 @@ public class TypeManager {
                return true;
        }
 
-       //
-       // FIXME: we need to return the accessors depending on whether
-       // they are visible or not.
-       //
-       static public MethodInfo [] GetAccessors (PropertyInfo pi)
-       {
-               MethodInfo [] ret;
-
-               if (pi is PropertyBuilder){
-                       Pair pair = (Pair) properties [pi];
-
-                       ret = new MethodInfo [2];
-                       ret [0] = (MethodInfo) pair.First;
-                       ret [1] = (MethodInfo) pair.Second;
-
-                       return ret;
-               } else {
-                       MethodInfo [] mi = new MethodInfo [2];
-
-                       //
-                       // Why this and not pi.GetAccessors?
-                       // Because sometimes index 0 is the getter
-                       // sometimes it is 1
-                       //
-                       mi [0] = pi.GetGetMethod (true);
-                       mi [1] = pi.GetSetMethod (true);
-
-                       return mi;
-               }
-       }
-
        static public MethodInfo GetPropertyGetter (PropertyInfo pi)
        {
                if (pi is PropertyBuilder){
@@ -1902,12 +1972,6 @@ public class TypeManager {
                                if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
                                        return false;
 
-                               // Although a derived class can access protected members of its base class
-                               // it cannot do so through an instance of the base class (CS1540).
-                               if ((closure_invocation_type != closure_start_type) &&
-                                   closure_invocation_type.IsSubclassOf (closure_start_type))
-                                       return false;
-
                                return true;
                        }
 
@@ -2046,7 +2110,10 @@ public class TypeManager {
                                } else
                                        private_ok = always_ok_flag;
 
-                               if (private_ok || invocation_type.IsSubclassOf (current_type))
+                               if (invocation_type.IsSubclassOf (current_type))
+                                       private_ok = true;
+                               
+                               if (private_ok)
                                        bf = original_bf | BindingFlags.NonPublic;
                        } else {
                                private_ok = false;
@@ -2091,7 +2158,7 @@ public class TypeManager {
                        
                        if (list.Count == 0)
                                continue;
-                       
+                               
                        //
                        // Events and types are returned by both `static' and `instance'
                        // searches, which means that our above FindMembers will