Small bug fix, to render better an acurrate error
[mono.git] / mcs / mcs / typemanager.cs
index 2c46d7ec6389408771be316b261c8649e5f4dec0..58f9a0168cc7ed2386ff67a511741714f536acbd 100755 (executable)
@@ -23,6 +23,7 @@ using System.Globalization;
 using System.Collections;
 using System.Reflection;
 using System.Reflection.Emit;
+using System.Text;
 using System.Text.RegularExpressions;
 using System.Runtime.CompilerServices;
 using System.Diagnostics;
@@ -60,6 +61,7 @@ public class TypeManager {
        static public Type icloneable_type;
        static public Type type_type;
        static public Type ienumerator_type;
+       static public Type ienumerable_type;
        static public Type idisposable_type;
        static public Type default_member_type;
        static public Type iasyncresult_type;
@@ -78,6 +80,7 @@ public class TypeManager {
        static public Type void_ptr_type;
        static public Type indexer_name_type;
        static public Type exception_type;
+       static public Type invalid_operation_exception_type;
        static public object obsolete_attribute_type;
        static public object conditional_attribute_type;
        static public Type in_attribute_type;
@@ -136,6 +139,8 @@ public class TypeManager {
        static public MethodInfo system_type_get_type_from_handle;
        static public MethodInfo object_getcurrent_void;
        static public MethodInfo bool_movenext_void;
+       static public MethodInfo ienumerable_getenumerator_void;
+       static public MethodInfo void_reset_void;
        static public MethodInfo void_dispose_void;
        static public MethodInfo void_monitor_enter_object;
        static public MethodInfo void_monitor_exit_object;
@@ -155,9 +160,11 @@ public class TypeManager {
        //
        // The attribute constructors.
        //
+       static public ConstructorInfo object_ctor;
        static public ConstructorInfo cons_param_array_attribute;
        static public ConstructorInfo void_decimal_ctor_five_args;
        static public ConstructorInfo unverifiable_code_ctor;
+       static public ConstructorInfo invalid_operation_ctor;
        
        // <remarks>
        //   Holds the Array of Assemblies that have been loaded
@@ -469,6 +476,8 @@ public class TypeManager {
                modules = n;
        }
 
+       static Hashtable references = new Hashtable ();
+       
        //
        // Gets the reference to T version of the Type (T&)
        //
@@ -478,13 +487,22 @@ public class TypeManager {
                
                Type ret = t.Assembly.GetType (tname);
 
+               //
                // If the type comes from the assembly we are building
-               if (ret == null)
-                       ret = t.Module.GetType (tname);
+               // We need the Hashtable, because .NET 1.1 will return different instance types
+               // every time we call ModuleBuilder.GetType.
+               //
+               if (ret == null){
+                       if (references [t] == null)
+                               references [t] = CodeGen.ModuleBuilder.GetType (tname);
+                       ret = (Type) references [t];
+               }
 
                return ret;
        }
 
+       static Hashtable pointers = new Hashtable ();
+
        //
        // Gets the pointer to T version of the Type  (T*)
        //
@@ -493,10 +511,18 @@ public class TypeManager {
                string tname = t.FullName + "*";
                
                Type ret = t.Assembly.GetType (tname);
-
+               
+               //
                // If the type comes from the assembly we are building
-               if (ret == null)
-                       ret = t.Module.GetType (tname);
+               // We need the Hashtable, because .NET 1.1 will return different instance types
+               // every time we call ModuleBuilder.GetType.
+               //
+               if (ret == null){
+                       if (pointers [t] == null)
+                               pointers [t] = CodeGen.ModuleBuilder.GetType (tname);
+                       
+                       ret = (Type) pointers [t];
+               }
 
                return ret;
        }
@@ -548,11 +574,16 @@ public class TypeManager {
        }
 
        //
-       // This version tries to reduce the impact of calling LookupType by validating if
-       // the namespace exists
+       // UNUSED: This version tries to reduce the impact of calling LookupType by validating if
+       // UNUSED: the namespace exists
        //
-       public static Type LookupType (string ns, string name, out string res)
+       public static Type xLookupType (string ns, string name, out string res)
        {
+               // CURRENTLY UNUSED
+               // CURRENTLY UNUSED
+               // CURRENTLY UNUSED
+               // CURRENTLY UNUSED
+               
                if (!IsNamespace (ns)){
                        res = null;
                        return null;
@@ -560,8 +591,13 @@ public class TypeManager {
 
                res = DeclSpace.MakeFQN (ns, name);
                return LookupType (res);
+               // CURRENTLY UNUSED
+               // CURRENTLY UNUSED
+               // CURRENTLY UNUSED
+               // CURRENTLY UNUSED
+               // CURRENTLY UNUSED
        }
-       
+
        /// <summary>
        ///   Returns the Type associated with @name, takes care of the fact that
        ///   reflection expects nested types to be separated from the main type
@@ -579,27 +615,27 @@ public class TypeManager {
                if (t != null)
                        return t;
 
-#if SIMPLE_SPEEDUP
+               // Two thirds of the failures are caught here.
                if (negative_hits.Contains (name))
                        return null;
-#endif
-               
-               //
-               // 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;
 
                for (int n = 1; n <= count; n++){
                        string top_level_type = String.Join (".", elements, 0, n);
 
+                       // One third of the failures are caught here.
+                       if (negative_hits.Contains (top_level_type))
+                               continue;
+                       
                        t = (Type) types [top_level_type];
                        if (t == null){
                                t = LookupTypeReflection (top_level_type);
-                               if (t == null)
+                               if (t == null){
+                                       negative_hits [top_level_type] = true;
                                        continue;
+                               }
                        }
                        
                        if (count == n){
@@ -615,15 +651,15 @@ public class TypeManager {
                                return null;
                        
                        string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
-                       t = LookupTypeDirect (newt);
-                       if (t != null)
-                               types [newt] = t;
+                       //Console.WriteLine ("Looking up: " + newt + " " + name);
+                       t = LookupTypeReflection (newt);
+                       if (t == null)
+                               negative_hits [name] = true;
+                       else
+                               types [name] = t;
                        return t;
                }
-
-#if SIMPLE_SPEEDUP
                negative_hits [name] = true;
-#endif
                return null;
        }
 
@@ -675,8 +711,9 @@ public class TypeManager {
                        foreach (Assembly a in assemblies){
                                foreach (Type t in a.GetTypes ()){
                                        string ns = t.Namespace;
-                                       
-                                       if (ns == "")
+
+                                       // t.Namespace returns null for <PrivateImplDetails>
+                                       if (ns == ""|| ns == null)
                                                continue;
                                        if (namespaces_hash.Contains (ns))
                                                continue;
@@ -687,6 +724,7 @@ public class TypeManager {
                //
                // Now insert all the namespaces defined by the application
                //
+               StringBuilder s = null;
                foreach (Namespace ns in Namespace.UserDefinedNamespaces){
                        string name = ns.Name;
                        if (name == "")
@@ -695,6 +733,26 @@ public class TypeManager {
                                throw new Exception ();
                        if (namespaces_hash.Contains (name))
                                continue;
+                       
+                       if (name.IndexOf ('.') != -1){
+                               if (s == null)
+                                       s = new StringBuilder ();
+                               string [] pieces = name.Split ('.');
+                               for (int i = 1; i < pieces.Length; i++){
+                                       s.Length = 0;
+                               
+                                       s.Append (pieces [0]);
+                                       for (int j = 1; j < i; j++){
+                                               s.Append (".");
+                                               s.Append (pieces [j]);
+                                       }
+                                       string n = s.ToString ();
+                                       if (namespaces_hash.Contains (n))
+                                               continue;
+                                       namespaces_hash [n] = true;
+                               }
+                       }
+                       
                        namespaces_hash [name] = true;
                }
 
@@ -711,11 +769,19 @@ public class TypeManager {
 
        public static bool IsNamespace (string name)
        {
-               foreach (string ns in namespaces){
-                       if (name == ns)
-                               return true;
-               }
-               return false;
+               if (Array.BinarySearch (namespaces, name) < 0)
+                       return false;
+               
+               return true;
+       }
+
+       public static bool NamespaceClash (string name)
+       {
+               if (Array.BinarySearch (namespaces, name) < 0)
+                       return false;
+
+               Report.Error (519, String.Format ("`{0}' clashes with a predefined namespace", name));
+               return true;
        }
 
        /// <summary>
@@ -782,7 +848,7 @@ public class TypeManager {
        /// </summary>
        static Type CoreLookupType (string name)
        {
-               Type t = LookupType (name);
+               Type t = LookupTypeDirect (name);
 
                if (t == null){
                        Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
@@ -896,6 +962,7 @@ public class TypeManager {
                asynccallback_type   = CoreLookupType ("System.AsyncCallback");
                iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
                ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
+               ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
                idisposable_type     = CoreLookupType ("System.IDisposable");
                icloneable_type      = CoreLookupType ("System.ICloneable");
                monitor_type         = CoreLookupType ("System.Threading.Monitor");
@@ -910,10 +977,8 @@ public class TypeManager {
                in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
 
                //
-               // Temporary while people upgrade their corlibs
-               //
-               //
-               // Change from LookupType to CoreLookupType before release
+               // Sigh. Remove this before the release.  Wonder what versions of Mono
+               // people are running.
                //
                guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
 
@@ -924,6 +989,7 @@ public class TypeManager {
                indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
 
                exception_type        = CoreLookupType ("System.Exception");
+               invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
 
                //
                // Attribute types
@@ -1024,6 +1090,8 @@ public class TypeManager {
                        ienumerator_type, "get_Current", void_arg);
                bool_movenext_void = GetMethod (
                        ienumerator_type, "MoveNext", void_arg);
+               void_reset_void = GetMethod (
+                       ienumerator_type, "Reset", void_arg);
                void_dispose_void = GetMethod (
                        idisposable_type, "Dispose", void_arg);
                int_get_offset_to_string_data = GetMethod (
@@ -1032,7 +1100,9 @@ public class TypeManager {
                        array_type, "get_Length", void_arg);
                int_array_get_rank = GetMethod (
                        array_type, "get_Rank", void_arg);
-
+               ienumerable_getenumerator_void = GetMethod (
+                       ienumerable_type, "GetEnumerator", void_arg);
+               
                //
                // Int32 arguments
                //
@@ -1088,7 +1158,17 @@ public class TypeManager {
 
                unverifiable_code_ctor = GetConstructor (
                        unverifiable_code_type, void_arg);
-               
+
+               //
+               // InvalidOperationException
+               //
+               invalid_operation_ctor = GetConstructor (
+                       invalid_operation_exception_type, void_arg);
+
+
+               // Object
+               object_ctor = GetConstructor (object_type, void_arg);
+
        }
 
        const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;