Forget to commit.
[mono.git] / mcs / mcs / typemanager.cs
index 308faf58212b6d1db024b322a0a3047d32450a89..ef1a806073e195c6677067be9ad0bf24d36fcf62 100644 (file)
@@ -31,7 +31,10 @@ using System.Diagnostics;
 
 namespace Mono.CSharp {
 
-public partial class TypeManager {
+#if GMCS_SOURCE
+       partial
+#endif
+       class TypeManager {
        //
        // A list of core types that the compiler requires or uses
        //
@@ -57,7 +60,6 @@ public partial class TypeManager {
        static public Type multicast_delegate_type;
        static public Type void_type;
        static public Type null_type;
-       static public Type enumeration_type;
        static public Type array_type;
        static public Type runtime_handle_type;
        static public Type icloneable_type;
@@ -168,7 +170,7 @@ public partial class TypeManager {
        static public MethodInfo string_concat_object_object;
        static public MethodInfo string_concat_object_object_object;
        static public MethodInfo string_concat_object_dot_dot_dot;
-       static public MethodInfo string_isinterneted_string;
+       static public MethodInfo string_isinterned_string;
        static public MethodInfo system_type_get_type_from_handle;
        static public MethodInfo bool_movenext_void;
        static public MethodInfo ienumerable_getenumerator_void;
@@ -276,9 +278,7 @@ public partial class TypeManager {
                builder_to_method = null;
                
                fields = null;
-               fieldbuilders_to_fields = null;
                events = null;
-               priv_fields_events = null;
                type_hash = null;
                propertybuilder_to_property = null;
 
@@ -389,6 +389,7 @@ public partial class TypeManager {
 #endif
 
                // to uncover regressions
+               AllClsTopLevelTypes = null;
                cons_param_array_attribute = null;
        }
 
@@ -437,11 +438,6 @@ public partial class TypeManager {
 
        public static MemberCache LookupMemberCache (Type t)
        {
-#if GMCS_SOURCE && MS_COMPATIBLE
-        if (t.IsGenericType && !t.IsGenericTypeDefinition)
-            t = t.GetGenericTypeDefinition ();
-#endif
-
                if (t is TypeBuilder) {
                        IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
                        if (container != null)
@@ -669,6 +665,16 @@ public partial class TypeManager {
                + match.Groups [2].Captures [0].Value;
        }
 
+       // Used for error reporting to show symbolic name instead of underlying value
+       public static string CSharpEnumValue (Type t, object value)
+       {
+               Enum e = LookupDeclSpace (t) as Enum;
+               if (e == null)
+                       return System.Enum.GetName (t, value);
+
+               return e.GetDefinition (value).GetSignatureForError ();
+       }
+
         /// <summary>
        ///  Returns the signature of the method with full namespace classification
        /// </summary>
@@ -770,10 +776,9 @@ public partial class TypeManager {
 
                ParameterData iparams = GetParameterData (mb);
                string parameters = iparams.GetSignatureForError ();
-               string accessor = "";
+               int accessor_end = 0;
 
-               // Is property
-               if (mb.IsSpecialName) {
+               if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
                        Operator.OpType ot = Operator.GetOperatorType (mb.Name);
                        if (ot != Operator.OpType.TOP) {
                                sig.Append ("operator ");
@@ -782,28 +787,24 @@ public partial class TypeManager {
                                return sig.ToString ();
                        }
 
-                       if (mb.Name.StartsWith ("get_") || mb.Name.StartsWith ("set_")) {
-                               accessor = mb.Name.Substring (0, 3);
+                       bool is_getter = mb.Name.StartsWith ("get_");
+                       bool is_setter = mb.Name.StartsWith ("set_");
+                       if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
+                               accessor_end = 3;
+                       } else if (mb.Name.StartsWith ("remove_")) {
+                               accessor_end = 6;
                        }
-               }
 
-               // Is indexer
-               if (mb.IsSpecialName && !mb.IsConstructor) {
-                       if (iparams.Count > (mb.Name.StartsWith ("get_") ? 0 : 1)) {
+                       // Is indexer
+                       if (iparams.Count > (is_getter ? 0 : 1)) {
                                sig.Append ("this[");
-                               if (show_accessor) {
+                               if (is_getter)
                                        sig.Append (parameters.Substring (1, parameters.Length - 2));
-                               }
-                               else {
-                                       int before_ret_val = parameters.LastIndexOf (',');
-                                       if (before_ret_val < 0)
-                                               sig.Append (parameters.Substring (1, parameters.Length - 2));
-                                       else
-                                               sig.Append (parameters.Substring (1, before_ret_val - 1));
-                               }
+                               else
+                                       sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
                                sig.Append (']');
                        } else {
-                               sig.Append (mb.Name.Substring (4));
+                               sig.Append (mb.Name.Substring (accessor_end + 1));
                        }
                } else {
                        if (mb.Name == ".ctor")
@@ -828,9 +829,9 @@ public partial class TypeManager {
                        sig.Append (parameters);
                }
 
-               if (show_accessor && accessor.Length > 0) {
+               if (show_accessor && accessor_end > 0) {
                        sig.Append ('.');
-                       sig.Append (accessor);
+                       sig.Append (mb.Name.Substring (0, accessor_end));
                }
 
                return sig.ToString ();
@@ -850,7 +851,7 @@ public partial class TypeManager {
 
        static public string CSharpSignature (EventInfo ei)
        {
-               return CSharpName (ei.DeclaringType) + '.' + ei.Name;
+               return CSharpName (ei.DeclaringType) + "." + ei.Name;
        }
 
        /// <summary>
@@ -862,8 +863,12 @@ public partial class TypeManager {
                Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
                FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
                Type t = fne == null ? null : fne.Type;
-               if (t == null)
+               if (t == null) {
                        Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
+                       return null;
+               }
+
+               AttributeTester.RegisterNonObsoleteType (t);
                return t;
        }
 
@@ -992,7 +997,9 @@ public partial class TypeManager {
        public static void InitCoreTypes ()
        {
                object_type   = CoreLookupType ("System", "Object");
+               system_object_expr.Type = object_type;
                value_type    = CoreLookupType ("System", "ValueType");
+               system_valuetype_expr.Type = value_type;
 
                InitEnumUnderlyingTypes ();
 
@@ -1143,7 +1150,6 @@ public partial class TypeManager {
                        }
                }
 
-               system_object_expr.Type = object_type;
                system_string_expr.Type = string_type;
                system_boolean_expr.Type = bool_type;
                system_decimal_expr.Type = decimal_type;
@@ -1161,7 +1167,6 @@ public partial class TypeManager {
                system_void_expr.Type = void_type;
                system_asynccallback_expr.Type = asynccallback_type;
                system_iasyncresult_expr.Type = iasyncresult_type;
-               system_valuetype_expr.Type = value_type;
 
                //
                // These are only used for compare purposes
@@ -1202,7 +1207,7 @@ public partial class TypeManager {
                        string_type, "Concat", params_object);
 
                Type [] string_ = { string_type };
-               string_isinterneted_string = GetMethod (
+               string_isinterned_string = GetMethod (
                        string_type, "IsInterned", string_);
                
                Type [] runtime_type_handle = { runtime_handle_type };
@@ -1345,7 +1350,7 @@ public partial class TypeManager {
                                              MemberFilter filter, object criteria)
        {
 #if MS_COMPATIBLE && GMCS_SOURCE
-               if (t.IsGenericType && !t.IsGenericTypeDefinition)
+               if (t.IsGenericType)
                        t = t.GetGenericTypeDefinition ();
 #endif
 
@@ -1635,7 +1640,7 @@ public partial class TypeManager {
                if (t is TypeBuilder) {
                        TypeContainer tc = LookupTypeContainer (t);
                        if (tc.Fields != null){
-                               foreach (FieldMember f in tc.Fields){
+                               foreach (FieldBase f in tc.Fields){
                                        // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
                                        if ((f.ModFlags & Modifiers.STATIC) != 0)
                                                continue;
@@ -1982,13 +1987,9 @@ public partial class TypeManager {
                return (PropertyBase)propertybuilder_to_property [pi];
        }
 
-       static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
+       static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
        {
-               if (fieldbuilders_to_fields.Contains (fb))
-                       return false;
-
                fieldbuilders_to_fields.Add (fb, f);
-               return true;
        }
 
        //
@@ -2003,23 +2004,11 @@ public partial class TypeManager {
 #endif
                return (FieldBase) fieldbuilders_to_fields [fb];
        }
-       
-       static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
-       {
-               if (events == null)
-                       events = new Hashtable ();
-
-               if (!events.Contains (eb)) {
-                       events.Add (eb, new Pair (add, remove));
-               }
-       }
 
        static public MethodInfo GetAddMethod (EventInfo ei)
        {
                if (ei is MyEventBuilder) {
-                       Pair pair = (Pair) events [ei];
-
-                       return (MethodInfo) pair.First;
+                       return ((MyEventBuilder)ei).GetAddMethod (true);
                }
                return ei.GetAddMethod (true);
        }
@@ -2027,36 +2016,27 @@ public partial class TypeManager {
        static public MethodInfo GetRemoveMethod (EventInfo ei)
        {
                if (ei is MyEventBuilder) {
-                       Pair pair = (Pair) events [ei];
-
-                       return (MethodInfo) pair.Second;
+                       return ((MyEventBuilder)ei).GetRemoveMethod (true);
                }
                return ei.GetRemoveMethod (true);
        }
 
-       static Hashtable priv_fields_events;
-
-       static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
+       static public void RegisterEventField (EventInfo einfo, EventField e)
        {
-               if (priv_fields_events == null)
-                       priv_fields_events = new Hashtable ();
-
-               if (priv_fields_events.Contains (einfo))
-                       return false;
-
-               priv_fields_events.Add (einfo, builder);
+               if (events == null)
+                       events = new Hashtable ();
 
-               return true;
+               events.Add (einfo, e);
        }
 
-       static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
+       static public EventField GetEventField (EventInfo ei)
        {
-               if (priv_fields_events == null)
+               if (events == null)
                        return null;
-               else
-                       return (MemberInfo) priv_fields_events [ei];
+
+               return (EventField) events [ei];
        }
-               
+
        static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
                                             MethodBase set, Type[] args)
        {
@@ -2087,7 +2067,7 @@ public partial class TypeManager {
                if (tc.Fields == null)
                        return true;
 
-               foreach (FieldMember field in tc.Fields) {
+               foreach (FieldBase field in tc.Fields) {
                        if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
                                continue;
 
@@ -2730,8 +2710,13 @@ public partial class TypeManager {
 
        public static bool IsEqual (Type a, Type b)
        {
-               if (a.Equals (b))
+               if (a.Equals (b)) {
+                       // MS BCL returns true even if enum types are different
+                       if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
+                               return a.FullName == b.FullName;
+
                        return true;
+               }
 
 #if GMCS_SOURCE
                if (a.IsGenericParameter && b.IsGenericParameter) {
@@ -2801,7 +2786,7 @@ public partial class TypeManager {
                        BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
 
 #if MS_COMPATIBLE
-        return m;
+               return m;
 #endif
 
                if (m is ConstructorInfo) {
@@ -3316,19 +3301,79 @@ public partial class TypeManager {
                return null;
        }
 
-       // Tests whether external method is really special
-       public static bool IsSpecialMethod (MethodBase mb)
+       const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
+                                                                       BindingFlags.Static | BindingFlags.Instance | 
+                                                                       BindingFlags.DeclaredOnly;
+
+       // Currently is designed to work with external types only
+       public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
        {
+               if (!mb.IsSpecialName)
+                       return null;
+
                string name = mb.Name;
-               if (name.StartsWith ("get_") || name.StartsWith ("set_"))
-                       return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
-                               
+               if (name.Length < 5)
+                       return null;
+
+               if (name [3] != '_')
+                       return null;
+
+               if (name.StartsWith ("get") || name.StartsWith ("set")) {
+                       MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
+                               Type.FilterName, name.Substring (4));
+
+                       if (pi == null)
+                               return null;
+
+                       // This can happen when property is indexer (it can have same name but different parameters)
+                       foreach (PropertyInfo p in pi) {
+                               foreach (MethodInfo p_mi in p.GetAccessors (true)) {
+                                       if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
+                                               return p;
+                               }
+                       }
+               }
+
+               return null;
+       }
+
+       // Currently is designed to work with external types only
+       public static MemberInfo GetEventFromAccessor (MethodBase mb)
+       {
+               if (!mb.IsSpecialName)
+                       return null;
+
+               string name = mb.Name;
+               if (name.Length < 5)
+                       return null;
+
                if (name.StartsWith ("add_"))
-                       return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
+                       return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
 
                if (name.StartsWith ("remove_"))
-                       return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
+                       return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
+
+               return null;
+       }
+
+       // Tests whether external method is really special
+       public static bool IsSpecialMethod (MethodBase mb)
+       {
+               if (!mb.IsSpecialName)
+                       return false;
 
+               IMethodData md = TypeManager.GetMethod (mb);
+               if (md != null) 
+                       return (md is AbstractPropertyEventMethod || md is Operator);
+
+               PropertyInfo pi = GetPropertyFromAccessor (mb);
+               if (pi != null)
+                       return IsValidProperty (pi);
+                               
+               if (GetEventFromAccessor (mb) != null)
+                       return true;
+
+               string name = mb.Name;
                if (name.StartsWith ("op_")){
                        foreach (string oname in Unary.oper_names) {
                                if (oname == name)
@@ -3343,6 +3388,22 @@ public partial class TypeManager {
                return false;
        }
 
+       // Tests whether imported property is valid C# property.
+       // TODO: It seems to me that we should do a lot of sanity tests before
+       // we accept property as C# property
+       static bool IsValidProperty (PropertyInfo pi)
+       {
+               MethodInfo get_method = pi.GetGetMethod (true);
+               MethodInfo set_method = pi.GetSetMethod (true);
+               if (get_method != null && set_method != null) {
+                       int g_count = get_method.GetParameters ().Length;
+                       int s_count = set_method.GetParameters ().Length;
+                       if (g_count + 1 != s_count)
+                               return false;
+               }
+               return true;
+       }
+
 #endregion
        
 }