- public static bool IsAttributeType (Type t)
- {
- return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
- }
-
- //
- // Whether a type is unmanaged. This is used by the unsafe code (25.2)
- //
- // mcs4: delete, DeclSpace.IsUnmanagedType is replacement
- public static bool IsUnmanagedType (Type t)
- {
- DeclSpace ds = TypeManager.LookupDeclSpace (t);
- if (ds != null)
- return ds.IsUnmanagedType ();
-
- // builtins that are not unmanaged types
- if (t == TypeManager.object_type || t == TypeManager.string_type)
- return false;
-
- if (IsGenericType (t) || IsGenericParameter (t))
- return false;
-
- if (IsBuiltinOrEnum (t))
- return true;
-
- // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
- if (t.IsPointer)
- return IsUnmanagedType (GetElementType (t));
-
- // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
- if (t.IsArray)
- return false;
-
- if (!IsValueType (t))
- return false;
-
- for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
- if (IsGenericTypeDefinition (p))
- return false;
- }
-
- bool retval = true;
- {
- FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
-
- foreach (FieldInfo f in fields){
- if (!IsUnmanagedType (f.FieldType)){
- retval = false;
- }
- }
- }
-
- return retval;
- }
-
- //
- // Null is considered to be a reference type
- //
- public static bool IsReferenceType (Type t)
- {
- if (TypeManager.IsGenericParameter (t)) {
- GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
- if (constraints == null)
- return false;
-
- return constraints.IsReferenceType;
- }
-
- return !IsStruct (t) && !IsEnumType (t);
- }
-
- public static bool IsValueType (Type t)
- {
- if (TypeManager.IsGenericParameter (t)) {
- GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
- if (constraints == null)
- return false;
-
- return constraints.IsValueType;
- }
-
- return IsStruct (t) || IsEnumType (t);
- }
-
- public static bool IsStruct (Type t)
- {
- return t.BaseType == value_type && t != enum_type && t.IsSealed;
- }
-
- public static bool IsInterfaceType (Type t)
- {
- TypeContainer tc = (TypeContainer) builder_to_declspace [t];
- if (tc == null)
- return false;
-
- return tc.Kind == Kind.Interface;
- }
-
- public static bool IsSubclassOf (Type type, Type base_type)
- {
- TypeParameter tparam = LookupTypeParameter (type);
- TypeParameter pparam = LookupTypeParameter (base_type);
-
- if ((tparam != null) && (pparam != null)) {
- if (tparam == pparam)
- return true;
-
- return tparam.IsSubclassOf (base_type);
- }
-
-#if MS_COMPATIBLE
- if (tparam != pparam)
- return false;
-
- if (type.IsGenericType)
- type = type.GetGenericTypeDefinition ();
-#endif
-
- if (type.IsSubclassOf (base_type))
- return true;
-
- do {
- if (IsEqual (type, base_type))
- return true;
-
- type = type.BaseType;
- } while (type != null);
-
- return false;
- }
-
- public static bool IsPrivateAccessible (Type type, Type parent)
- {
- if (type == null)
- return false;
-
- if (type.Equals (parent))
- return true;
-
- return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
- }
-
- public static bool IsFamilyAccessible (Type type, Type parent)
- {
- TypeParameter tparam = LookupTypeParameter (type);
- TypeParameter pparam = LookupTypeParameter (parent);
-
- if ((tparam != null) && (pparam != null)) {
- if (tparam == pparam)
- return true;
-
- return tparam.IsSubclassOf (parent);
- }
-
- do {
- if (IsInstantiationOfSameGenericType (type, parent))
- return true;
-
- type = type.BaseType;
- } while (type != null);
-
- return false;
- }
-
- //
- // Checks whether `type' is a subclass or nested child of `base_type'.
- //
- public static bool IsNestedFamilyAccessible (Type type, Type base_type)
- {
- do {
- if (IsFamilyAccessible (type, base_type))
- return true;
-
- // Handle nested types.
- type = type.DeclaringType;
- } while (type != null);
-
- return false;
- }
-
- //
- // Checks whether `type' is a nested child of `parent'.
- //
- public static bool IsNestedChildOf (Type type, Type parent)
- {
- if (type == null)
- return false;
-
- type = DropGenericTypeArguments (type);
- parent = DropGenericTypeArguments (parent);
-
- if (IsEqual (type, parent))
- return false;
-
- type = type.DeclaringType;
- while (type != null) {
- if (IsEqual (type, parent))
- return true;
-
- type = type.DeclaringType;
- }
-
- return false;
- }
-
- public static bool IsSpecialType (Type t)
- {
- return t == arg_iterator_type || t == typed_reference_type;
- }
-
- //
- // Checks whether `invocationAssembly' is same or a friend of the assembly
- //
- public static bool IsThisOrFriendAssembly (Assembly invocationAssembly, Assembly assembly)
- {
- if (assembly == null)
- throw new ArgumentNullException ("assembly");
-
- // TODO: This can happen for constants used at assembly level and
- // predefined members
- // But there is no way to test for it for now, so it could be abused
- // elsewhere too.
- if (invocationAssembly == null)
- invocationAssembly = CodeGen.Assembly.Builder;
-
- if (invocationAssembly == assembly)
- return true;
-
- if (assembly_internals_vis_attrs.Contains (assembly))
- return (bool)(assembly_internals_vis_attrs [assembly]);
-
- PredefinedAttribute pa = PredefinedAttributes.Get.InternalsVisibleTo;
- // HACK: Do very early resolve of SRE type checking
- if (pa.Type == null)
- pa.Resolve (true);
-
- if (!pa.IsDefined)
- return false;
-
- object [] attrs = assembly.GetCustomAttributes (pa.Type, false);
- if (attrs.Length == 0) {
- assembly_internals_vis_attrs.Add (assembly, false);
- return false;
- }
-
- bool is_friend = false;
-
- AssemblyName this_name = CodeGen.Assembly.Name;
- byte [] this_token = this_name.GetPublicKeyToken ();
- foreach (InternalsVisibleToAttribute attr in attrs) {
- if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
- continue;
-
- AssemblyName aname = null;
- try {
- aname = new AssemblyName (attr.AssemblyName);
- } catch (FileLoadException) {
- } catch (ArgumentException) {
- }
-
- if (aname == null || aname.Name != this_name.Name)
- continue;
-
- byte [] key_token = aname.GetPublicKeyToken ();
- if (key_token != null) {
- if (this_token.Length == 0) {
- // Same name, but assembly is not strongnamed
- Error_FriendAccessNameNotMatching (aname.FullName, RootContext.ToplevelTypes.Compiler.Report);
- break;
- }
-
- if (!CompareKeyTokens (this_token, key_token))
- continue;
- }
-
- is_friend = true;
- break;
- }
-
- assembly_internals_vis_attrs.Add (assembly, is_friend);
- return is_friend;
- }
-
- static bool CompareKeyTokens (byte [] token1, byte [] token2)
- {
- for (int i = 0; i < token1.Length; i++)
- if (token1 [i] != token2 [i])
- return false;
-
- return true;
- }
-
- static void Error_FriendAccessNameNotMatching (string other_name, Report Report)
- {
- Report.Error (281,
- "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it",
- other_name, CodeGen.Assembly.Name.FullName);
- }
-
- //
- // Do the right thing when returning the element type of an
- // array type based on whether we are compiling corlib or not
- //
- public static Type GetElementType (Type t)
- {
- if (RootContext.StdLib)
- return t.GetElementType ();
- else
- return TypeToCoreType (t.GetElementType ());
- }
-
- /// <summary>
- /// This method is not implemented by MS runtime for dynamic types
- /// </summary>
- public static bool HasElementType (Type t)
- {
- return t.IsArray || t.IsPointer || t.IsByRef;
- }
-
- public static Type GetEnumUnderlyingType (Type t)
- {
- t = DropGenericTypeArguments (t);
- Enum e = LookupTypeContainer (t) as Enum;
- if (e != null)
- return e.UnderlyingType;
-
- // TODO: cache it ?
- FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes);
- if (fi == null)
- return TypeManager.int32_type;
-
- return TypeToCoreType (fi.FieldType);
- }
-
- /// <summary>
- /// Gigantic work around for missing features in System.Reflection.Emit follows.
- /// </summary>
- ///
- /// <remarks>
- /// Since System.Reflection.Emit can not return MethodBase.GetParameters
- /// for anything which is dynamic, and we need this in a number of places,
- /// we register this information here, and use it afterwards.
- /// </remarks>
- static public void RegisterMethod (MethodBase mb, AParametersCollection ip)
- {
- method_params.Add (mb, ip);
- }
-
- static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p)
- {
- method_params.Add (pb, p);
- }
-
- static public AParametersCollection GetParameterData (MethodBase mb)
- {
- AParametersCollection pd = (AParametersCollection) method_params [mb];
- if (pd == null) {
-#if MS_COMPATIBLE
- if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
- MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
- pd = GetParameterData (mi);
- /*
- if (mi.IsGenericMethod)
- pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
- else
- pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
- */
- method_params.Add (mb, pd);
- return pd;
- }
-
- if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
- throw new InternalErrorException ("Parameters are not registered for method `{0}'",
- TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
- }
-
- pd = ParametersImported.Create (mb);
-#else
- MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
- if (generic != mb) {
- pd = TypeManager.GetParameterData (generic);
- pd = ParametersImported.Create (pd, mb);
- } else {
- pd = ParametersImported.Create (mb);
- }
-#endif
- method_params.Add (mb, pd);
- }
- return pd;
- }
-
- public static AParametersCollection GetParameterData (PropertyInfo pi)
- {
- AParametersCollection pd = (AParametersCollection)method_params [pi];
- if (pd == null) {
- if (pi is PropertyBuilder)
- return ParametersCompiled.EmptyReadOnlyParameters;
-
- ParameterInfo [] p = pi.GetIndexParameters ();
- if (p == null)
- return ParametersCompiled.EmptyReadOnlyParameters;
-
- pd = ParametersImported.Create (p, null);
- method_params.Add (pi, pd);
- }
-
- return pd;
- }
-
- public static AParametersCollection GetDelegateParameters (ResolveContext ec, Type t)
- {
- Delegate d = builder_to_declspace [t] as Delegate;
- if (d != null)
- return d.Parameters;
-
- MethodInfo invoke_mb = Delegate.GetInvokeMethod (ec.Compiler, t, t);
- return GetParameterData (invoke_mb);
- }
-
- static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
- {
- if (!method_overrides.Contains (override_method))
- method_overrides [override_method] = base_method;
- if (method_overrides [override_method] != base_method)
- throw new InternalErrorException ("Override mismatch: " + override_method);
- }
-
- static public bool IsOverride (MethodBase m)
- {
- m = DropGenericMethodArguments (m);
-
- return m.IsVirtual &&
- (m.Attributes & MethodAttributes.NewSlot) == 0 &&
- (m is MethodBuilder || method_overrides.Contains (m));
- }
-
- static public MethodBase TryGetBaseDefinition (MethodBase m)
- {
- m = DropGenericMethodArguments (m);
-
- return (MethodBase) method_overrides [m];
- }
-
- public static void RegisterConstant (FieldInfo fb, IConstant ic)
- {
- fields.Add (fb, ic);
- }
-
- public static IConstant GetConstant (FieldInfo fb)
- {
- if (fb == null)
- return null;
-
- return (IConstant)fields [fb];
- }
-
- public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
- {
- propertybuilder_to_property.Add (pi, pb);
- }
-
- public static PropertyBase GetProperty (PropertyInfo pi)
- {
- return (PropertyBase)propertybuilder_to_property [pi];
- }
-
- static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
- {
- fieldbuilders_to_fields.Add (fb, f);
- }
-
- //
- // The return value can be null; This will be the case for
- // auxiliary FieldBuilders created by the compiler that have no
- // real field being declared on the source code
- //
- static public FieldBase GetField (FieldInfo fb)
- {
- fb = GetGenericFieldDefinition (fb);
- return (FieldBase) fieldbuilders_to_fields [fb];
- }
-
- static public MethodInfo GetAddMethod (EventInfo ei)
- {
- if (ei is MyEventBuilder) {
- return ((MyEventBuilder)ei).GetAddMethod (true);
- }
- return ei.GetAddMethod (true);
- }
-
- static public MethodInfo GetRemoveMethod (EventInfo ei)
- {
- if (ei is MyEventBuilder) {
- return ((MyEventBuilder)ei).GetRemoveMethod (true);
- }
- return ei.GetRemoveMethod (true);
- }
-
- static public void RegisterEventField (EventInfo einfo, EventField e)
- {
- if (events == null)
- events = new Hashtable ();
-
- events.Add (einfo, e);
- }
-
- static public EventField GetEventField (EventInfo ei)
- {
- if (events == null)
- return null;
-
- return (EventField) events [ei];
- }
-
- public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
- {
- Hashtable hash = new Hashtable ();
- return CheckStructCycles (tc, seen, hash);
- }
-
- public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
- Hashtable hash)
- {
- if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc.TypeBuilder))
- return true;
-
- //
- // `seen' contains all types we've already visited.
- //
- if (seen.Contains (tc))
- return true;
- seen.Add (tc, null);
-
- if (tc.Fields == null)
- return true;
-
- foreach (FieldBase field in tc.Fields) {
- if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
- continue;
-
- Type ftype = field.FieldBuilder.FieldType;
- TypeContainer ftc = LookupTypeContainer (ftype);
- if (ftc == null)
- continue;
-
- if (hash.Contains (ftc)) {
- RootContext.ToplevelTypes.Compiler.Report.Error (523, tc.Location,
- "Struct member `{0}.{1}' of type `{2}' " +
- "causes a cycle in the struct layout",
- tc.Name, field.Name, ftc.Name);
- return false;
- }
-
- //
- // `hash' contains all types in the current path.
- //
- hash.Add (tc, null);
-
- bool ok = CheckStructCycles (ftc, seen, hash);
-
- hash.Remove (tc);
-
- if (!ok)
- return false;
-
- if (!seen.Contains (ftc))
- seen.Add (ftc, null);
- }
-
- return true;
- }
-
- /// <summary>
- /// Given an array of interface types, expand and eliminate repeated ocurrences
- /// of an interface.
- /// </summary>
- ///
- /// <remarks>
- /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
- /// be IA, IB, IC.
- /// </remarks>
- public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
- {
- ArrayList new_ifaces = new ArrayList ();
-
- foreach (TypeExpr iface in base_interfaces){
- Type itype = iface.Type;
-
- if (new_ifaces.Contains (itype))
- continue;
-
- new_ifaces.Add (itype);
-
- Type [] implementing = GetInterfaces (itype);
-
- foreach (Type imp in implementing){
- if (!new_ifaces.Contains (imp))
- new_ifaces.Add (imp);
- }
- }
- Type [] ret = new Type [new_ifaces.Count];
- new_ifaces.CopyTo (ret, 0);
- return ret;
- }
-
- public static Type[] ExpandInterfaces (Type [] base_interfaces)
- {
- ArrayList new_ifaces = new ArrayList ();
-
- foreach (Type itype in base_interfaces){
- if (new_ifaces.Contains (itype))
- continue;
-
- new_ifaces.Add (itype);
-
- Type [] implementing = GetInterfaces (itype);
-
- foreach (Type imp in implementing){
- if (!new_ifaces.Contains (imp))
- new_ifaces.Add (imp);
- }
- }
- Type [] ret = new Type [new_ifaces.Count];
- new_ifaces.CopyTo (ret, 0);
- return ret;
- }
-
- static PtrHashtable iface_cache;
-
- /// <summary>
- /// This function returns the interfaces in the type `t'. Works with
- /// both types and TypeBuilders.
- /// </summary>
- public static Type [] GetInterfaces (Type t)
- {
- Type [] cached = iface_cache [t] as Type [];
- if (cached != null)
- return cached;
-
- //
- // The reason for catching the Array case is that Reflection.Emit
- // will not return a TypeBuilder for Array types of TypeBuilder types,
- // but will still throw an exception if we try to call GetInterfaces
- // on the type.
- //
- // Since the array interfaces are always constant, we return those for
- // the System.Array
- //
-
- if (t.IsArray)
- t = TypeManager.array_type;
-
- if ((t is TypeBuilder) || IsGenericType (t)) {
- Type [] base_ifaces;
-
- if (t.BaseType == null)
- base_ifaces = Type.EmptyTypes;
- else
- base_ifaces = GetInterfaces (t.BaseType);
- Type[] type_ifaces;
- if (IsGenericType (t))
-#if MS_COMPATIBLE
- type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
-#else
- type_ifaces = t.GetInterfaces ();
-#endif
- else
- type_ifaces = (Type []) builder_to_ifaces [t];
- if (type_ifaces == null || type_ifaces.Length == 0)
- type_ifaces = Type.EmptyTypes;
-
- int base_count = base_ifaces.Length;
- Type [] result = new Type [base_count + type_ifaces.Length];
- base_ifaces.CopyTo (result, 0);
- type_ifaces.CopyTo (result, base_count);
-
- iface_cache [t] = result;
- return result;
- } else if (t is GenericTypeParameterBuilder){
- Type[] type_ifaces = (Type []) builder_to_ifaces [t];
- if (type_ifaces == null || type_ifaces.Length == 0)
- type_ifaces = Type.EmptyTypes;
-
- iface_cache [t] = type_ifaces;
- return type_ifaces;
- } else {
- Type[] ifaces = t.GetInterfaces ();
- iface_cache [t] = ifaces;
- return ifaces;
- }
- }
-
- //
- // gets the interfaces that are declared explicitly on t
- //
- public static Type [] GetExplicitInterfaces (TypeBuilder t)
- {
- return (Type []) builder_to_ifaces [t];
- }
-
- /// <remarks>
- /// The following is used to check if a given type implements an interface.
- /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
- /// </remarks>
- public static bool ImplementsInterface (Type t, Type iface)
- {
- Type [] interfaces;
-
- //
- // FIXME OPTIMIZATION:
- // as soon as we hit a non-TypeBuiler in the interface
- // chain, we could return, as the `Type.GetInterfaces'
- // will return all the interfaces implement by the type
- // or its bases.
- //
- do {
- interfaces = GetInterfaces (t);
-
- if (interfaces != null){
- foreach (Type i in interfaces){
- if (i == iface || IsVariantOf (i, iface))
- return true;
- }
- }
-
- t = t.BaseType;
- } while (t != null);
-
- return false;
- }
-
- static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
-
- // This is a custom version of Convert.ChangeType() which works
- // with the TypeBuilder defined types when compiling corlib.
- public static object ChangeType (object value, Type conversionType, out bool error)
- {
- IConvertible convert_value = value as IConvertible;
-
- if (convert_value == null){
- error = true;
- return null;
- }
-
- //
- // NOTE 1:
- // We must use Type.Equals() here since `conversionType' is
- // the TypeBuilder created version of a system type and not
- // the system type itself. You cannot use Type.GetTypeCode()
- // on such a type - it'd always return TypeCode.Object.
- //
- // NOTE 2:
- // We cannot rely on build-in type conversions as they are
- // more limited than what C# supports.
- // See char -> float/decimal/double conversion
- //
-
- error = false;
- try {
- if (conversionType.Equals (typeof (Boolean)))
- return (object)(convert_value.ToBoolean (nf_provider));
- if (conversionType.Equals (typeof (Byte)))
- return (object)(convert_value.ToByte (nf_provider));
- if (conversionType.Equals (typeof (Char)))
- return (object)(convert_value.ToChar (nf_provider));
- if (conversionType.Equals (typeof (DateTime)))
- return (object)(convert_value.ToDateTime (nf_provider));
-
- if (conversionType.Equals (decimal_type)) {
- if (convert_value.GetType () == TypeManager.char_type)
- return (decimal)convert_value.ToInt32 (nf_provider);
- return convert_value.ToDecimal (nf_provider);
- }
-
- if (conversionType.Equals (typeof (Double))) {
- if (convert_value.GetType () == TypeManager.char_type)
- return (double)convert_value.ToInt32 (nf_provider);
- return convert_value.ToDouble (nf_provider);
- }
-
- if (conversionType.Equals (typeof (Int16)))
- return (object)(convert_value.ToInt16 (nf_provider));
- if (conversionType.Equals (int32_type))
- return (object)(convert_value.ToInt32 (nf_provider));
- if (conversionType.Equals (int64_type))
- return (object)(convert_value.ToInt64 (nf_provider));
- if (conversionType.Equals (typeof (SByte)))
- return (object)(convert_value.ToSByte (nf_provider));
-
- if (conversionType.Equals (typeof (Single))) {
- if (convert_value.GetType () == TypeManager.char_type)
- return (float)convert_value.ToInt32 (nf_provider);
- return convert_value.ToSingle (nf_provider);
- }
-
- if (conversionType.Equals (typeof (String)))
- return (object)(convert_value.ToString (nf_provider));
- if (conversionType.Equals (typeof (UInt16)))
- return (object)(convert_value.ToUInt16 (nf_provider));
- if (conversionType.Equals (typeof (UInt32)))
- return (object)(convert_value.ToUInt32 (nf_provider));
- if (conversionType.Equals (typeof (UInt64)))
- return (object)(convert_value.ToUInt64 (nf_provider));
- if (conversionType.Equals (typeof (Object)))
- return (object)(value);
- else
- error = true;
- } catch {
- error = true;
- }
- return null;
- }
-
- //
- // When compiling with -nostdlib and the type is imported from an external assembly
- // SRE uses "wrong" type and we have to convert it to the right compiler instance.
- //
- public static Type TypeToCoreType (Type t)
- {
- if (RootContext.StdLib || t.Module != typeof (object).Module)
- return t;
-
- // TODO: GetTypeCode returns underlying type for enums !!
- TypeCode tc = Type.GetTypeCode (t);
-
- switch (tc){
- case TypeCode.Boolean:
- return TypeManager.bool_type;
- case TypeCode.Byte:
- return TypeManager.byte_type;
- case TypeCode.SByte:
- return TypeManager.sbyte_type;
- case TypeCode.Char:
- return TypeManager.char_type;
- case TypeCode.Int16:
- return TypeManager.short_type;
- case TypeCode.UInt16:
- return TypeManager.ushort_type;
- case TypeCode.Int32:
- return TypeManager.int32_type;
- case TypeCode.UInt32:
- return TypeManager.uint32_type;
- case TypeCode.Int64:
- return TypeManager.int64_type;
- case TypeCode.UInt64:
- return TypeManager.uint64_type;
- case TypeCode.Single:
- return TypeManager.float_type;
- case TypeCode.Double:
- return TypeManager.double_type;
- case TypeCode.String:
- return TypeManager.string_type;
- case TypeCode.Decimal:
- return TypeManager.decimal_type;
- }
-
- if (t == typeof (void))
- return TypeManager.void_type;
- if (t == typeof (object))
- return TypeManager.object_type;
- if (t == typeof (System.Type))
- return TypeManager.type_type;
- if (t == typeof (System.IntPtr))
- return TypeManager.intptr_type;
- if (t == typeof (System.UIntPtr))
- return TypeManager.uintptr_type;
-
- if (t.IsArray) {
- int dim = t.GetArrayRank ();
- t = GetElementType (t);
- return t.MakeArrayType (dim);
- }
- if (t.IsByRef) {
- t = GetElementType (t);
- return t.MakeByRefType ();
- }
- if (t.IsPointer) {
- t = GetElementType (t);
- return t.MakePointerType ();
- }
-
- return t;
- }
-
- //
- // Converts any type to reflection supported type
- //
- public static Type TypeToReflectionType (Type type)
- {
- // TODO: Very lame and painful, GetReference () is enough for mcs-cecil
- return IsDynamicType (type) ? object_type : type;
- }
-
- /// <summary>
- /// Utility function that can be used to probe whether a type
- /// is managed or not.
- /// </summary>
- public static bool VerifyUnManaged (Type t, Location loc)
- {
- if (IsUnmanagedType (t))
- return true;
-
- while (t.IsPointer)
- t = GetElementType (t);
-
- RootContext.ToplevelTypes.Compiler.Report.SymbolRelatedToPreviousError (t);
- RootContext.ToplevelTypes.Compiler.Report.Error (208, loc,
- "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
- CSharpName (t));
-
- return false;
- }
-
- /// <summary>
- /// Returns the name of the indexer in a given type.
- /// </summary>
- /// <remarks>
- /// The default is not always `Item'. The user can change this behaviour by
- /// using the IndexerNameAttribute in the container.
- /// For example, the String class indexer is named `Chars' not `Item'
- /// </remarks>
- public static string IndexerPropertyName (Type t)
- {
- t = DropGenericTypeArguments (t);
- if (t is TypeBuilder) {
- TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
- return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
- }
-
- PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
- if (pa.IsDefined) {
- System.Attribute attr = System.Attribute.GetCustomAttribute (
- t, pa.Type);
- if (attr != null) {
- DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
- return dma.MemberName;
- }
- }
-
- return TypeContainer.DefaultIndexerName;
- }
-
- static MethodInfo declare_local_method = null;
-
- public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
- {
- if (declare_local_method == null){
- declare_local_method = typeof (ILGenerator).GetMethod (
- "DeclareLocal",
- BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
- null,
- new Type [] { typeof (Type), typeof (bool)},
- null);
- if (declare_local_method == null){
- RootContext.ToplevelTypes.Compiler.Report.RuntimeMissingSupport (Location.Null, "pinned local variables");
- return ig.DeclareLocal (t);
- }
- }
- return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
- }
-
- private static bool IsSignatureEqual (Type a, Type b)
- {
- ///
- /// Consider the following example (bug #77674):
- ///
- /// public abstract class A
- /// {
- /// public abstract T Foo<T> ();
- /// }
- ///
- /// public abstract class B : A
- /// {
- /// public override U Foo<T> ()
- /// { return default (U); }
- /// }
- ///
- /// Here, `T' and `U' are method type parameters from different methods
- /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
- ///
- /// However, since we're determining whether B.Foo() overrides A.Foo(),
- /// we need to do a signature based comparision and consider them equal.
-
- if (a == b)
- return true;
-
- if (a.IsGenericParameter && b.IsGenericParameter &&
- (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
- return a.GenericParameterPosition == b.GenericParameterPosition;
- }
-
- if (a.IsArray && b.IsArray) {
- if (a.GetArrayRank () != b.GetArrayRank ())
- return false;
-
- return IsSignatureEqual (GetElementType (a), GetElementType (b));
- }
-
- if (a.IsByRef && b.IsByRef)
- return IsSignatureEqual (GetElementType (a), GetElementType (b));
-
- if (IsGenericType (a) && IsGenericType (b)) {
- if (DropGenericTypeArguments (a) != DropGenericTypeArguments (b))
- return false;
-
- Type[] aargs = GetTypeArguments (a);
- Type[] bargs = GetTypeArguments (b);
-
- if (aargs.Length != bargs.Length)
- return false;
-
- for (int i = 0; i < aargs.Length; i++) {
- if (!IsSignatureEqual (aargs [i], bargs [i]))
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- //
- // Returns whether the array of memberinfos contains the given method
- //
- public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType)
- {
- Type [] new_args = TypeManager.GetParameterData (new_method).Types;
-
- foreach (MethodBase method in array) {
- if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
- continue;
-
- if (method.Name != new_method.Name)
- continue;
-
- if (method is MethodInfo && new_method is MethodInfo &&
- !IsSignatureEqual (
- TypeToCoreType (((MethodInfo) method).ReturnType),
- TypeToCoreType (((MethodInfo) new_method).ReturnType)))
- continue;
-
- Type [] old_args = TypeManager.GetParameterData (method).Types;
- int old_count = old_args.Length;
- int i;
-
- if (new_args.Length != old_count)
- continue;
-
- for (i = 0; i < old_count; i++){
- if (!IsSignatureEqual (old_args [i], new_args [i]))
- break;
- }
- if (i != old_count)
- continue;
-
- return true;
- }
-
- return false;
- }
-
- //
- // We copy methods from `new_members' into `target_list' if the signature
- // for the method from in the new list does not exist in the target_list
- //
- // The name is assumed to be the same.
- //
- public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
- {
- if (target_list == null){
- target_list = new ArrayList ();
-
- foreach (MemberInfo mi in new_members){
- if (mi is MethodBase)
- target_list.Add (mi);
- }
- return target_list;
- }
-
- MemberInfo [] target_array = new MemberInfo [target_list.Count];
- target_list.CopyTo (target_array, 0);
-
- foreach (MemberInfo mi in new_members){
- MethodBase new_method = (MethodBase) mi;
-
- if (!ArrayContainsMethod (target_array, new_method, true))
- target_list.Add (new_method);
- }
- return target_list;
- }
-
-#region Generics
- // <remarks>
- // Tracks the generic parameters.
- // </remarks>
- static PtrHashtable builder_to_type_param;
-
- public static void AddTypeParameter (Type t, TypeParameter tparam)
- {
- if (!builder_to_type_param.Contains (t))
- builder_to_type_param.Add (t, tparam);
- }
-
- public static TypeParameter LookupTypeParameter (Type t)
- {
- return (TypeParameter) builder_to_type_param [t];
- }
-
- // This method always return false for non-generic compiler,
- // while Type.IsGenericParameter is returned if it is supported.
- public static bool IsGenericParameter (Type type)
- {
- return type.IsGenericParameter;
- }
-
- public static int GenericParameterPosition (Type type)
- {
- return type.GenericParameterPosition;
- }
-
- public static bool IsGenericType (Type type)
- {
- return type.IsGenericType;
- }
-
- public static bool IsGenericTypeDefinition (Type type)
- {
- return type.IsGenericTypeDefinition;
- }
-
- public static bool ContainsGenericParameters (Type type)
- {
- return type.ContainsGenericParameters;
- }
-
- public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
- {
- if (fi.DeclaringType.IsGenericTypeDefinition ||
- !fi.DeclaringType.IsGenericType)
- return fi;
-
- Type t = fi.DeclaringType.GetGenericTypeDefinition ();
- BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
-
- // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
- foreach (FieldInfo f in t.GetFields (bf))
- if (f.MetadataToken == fi.MetadataToken)
- return f;
-
- return fi;
- }
-
- public static bool IsEqual (Type a, Type 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;
-
- // Some types are never equal
- if (a == TypeManager.null_type || a == InternalType.AnonymousMethod)
- return false;
-
- return true;
- }
-
- if (IsGenericParameter (a) && IsGenericParameter (b)) {
- // TODO: needs more testing before cleaning up
- //if (a.DeclaringMethod != b.DeclaringMethod &&
- // (a.DeclaringMethod == null || b.DeclaringMethod == null))
- // return false;
- return a.GenericParameterPosition == b.GenericParameterPosition;
- }
-
- if (a.IsArray && b.IsArray) {
- if (a.GetArrayRank () != b.GetArrayRank ())
- return false;
- return IsEqual (GetElementType (a), GetElementType (b));
- }
-
- if (a.IsByRef && b.IsByRef)
- return IsEqual (a.GetElementType (), b.GetElementType ());
-
- if (IsGenericType (a) && IsGenericType (b)) {
- Type adef = DropGenericTypeArguments (a);
- Type bdef = DropGenericTypeArguments (b);
-
- if (adef != bdef)
- return false;
-
- if (adef.IsEnum && bdef.IsEnum)
- return true;
-
- Type[] aargs = GetTypeArguments (a);
- Type[] bargs = GetTypeArguments (b);
-
- if (aargs.Length != bargs.Length)
- return false;
-
- for (int i = 0; i < aargs.Length; i++) {
- if (!IsEqual (aargs [i], bargs [i]))
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- public static bool IsEqual (Type[] a, Type[] b)
- {
- if (a == null || b == null || a.Length != b.Length)
- return false;
-
- for (int i = 0; i < a.Length; ++i) {
- if (a [i] == null || b [i] == null) {
- if (a [i] == b [i])
- continue;
-
- return false;
- }
-
- if (!IsEqual (a [i], b [i]))
- return false;
- }
-
- return true;
- }
-
- public static Type DropGenericTypeArguments (Type t)
- {
- if (!t.IsGenericType)
- return t;
- // Micro-optimization: a generic typebuilder is always a generic type definition
- if (t is TypeBuilder)
- return t;
- return t.GetGenericTypeDefinition ();
- }
-
- public static MethodBase DropGenericMethodArguments (MethodBase m)
- {
- if (m.IsGenericMethod)
- m = ((MethodInfo) m).GetGenericMethodDefinition ();
-
- Type t = m.DeclaringType;
- if (!t.IsGenericType || t.IsGenericTypeDefinition)
- return m;
-
- t = t.GetGenericTypeDefinition ();
- BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
-
-#if MS_COMPATIBLE
- // TODO: use CodeGen.Module.Builder.ResolveMethod ()
- return m;
-#endif
-
- if (m is ConstructorInfo) {
- foreach (ConstructorInfo c in t.GetConstructors (bf))
- if (c.MetadataToken == m.MetadataToken)
- return c;
- } else {
- foreach (MethodBase mb in t.GetMethods (bf))
- if (mb.MetadataToken == m.MetadataToken)
- return mb;
- }
-
- return m;
- }
-
- public static Type[] GetGenericArguments (MethodBase mi)
- {
- return mi.GetGenericArguments () ?? Type.EmptyTypes;
- }
-
- public static Type[] GetTypeArguments (Type t)
- {
- DeclSpace tc = LookupDeclSpace (t);
- if (tc != null) {
- if (!tc.IsGeneric)
- return Type.EmptyTypes;
-
- TypeParameter[] tparam = tc.TypeParameters;
- Type[] ret = new Type [tparam.Length];
- for (int i = 0; i < tparam.Length; i++) {
- ret [i] = tparam [i].Type;
- if (ret [i] == null)
- throw new InternalErrorException ();
- }
-
- return ret;
- } else
- return t.GetGenericArguments ();
- }
-
- public static GenericConstraints GetTypeParameterConstraints (Type t)
- {
- if (!t.IsGenericParameter)
- throw new InvalidOperationException ();
-
- TypeParameter tparam = LookupTypeParameter (t);
- if (tparam != null)
- return tparam.GenericConstraints;
-
- return ReflectionConstraints.GetConstraints (t);
- }
-
- public static bool HasGenericArguments (Type t)
- {
- return GetNumberOfTypeArguments (t) > 0;
- }
-
- public static int GetNumberOfTypeArguments (Type t)
- {
- if (t.IsGenericParameter)
- return 0;
- DeclSpace tc = LookupDeclSpace (t);
- if (tc != null)
- return tc.IsGeneric ? tc.CountTypeParameters : 0;
- else
- return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
- }
-
- /// <summary>
- /// Check whether `type' and `parent' are both instantiations of the same
- /// generic type. Note that we do not check the type parameters here.
- /// </summary>
- public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
- {
- int tcount = GetNumberOfTypeArguments (type);
- int pcount = GetNumberOfTypeArguments (parent);
-
- if (tcount != pcount)
- return false;
-
- type = DropGenericTypeArguments (type);
- parent = DropGenericTypeArguments (parent);
-
- return type.Equals (parent);
- }
-
- /// <summary>
- /// Whether `mb' is a generic method definition.
- /// </summary>
- public static bool IsGenericMethodDefinition (MethodBase mb)
- {
- if (mb.DeclaringType is TypeBuilder) {
- IMethodData method = (IMethodData) builder_to_method [mb];
- if (method == null)
- return false;
-
- return method.GenericMethod != null;
- }
-
- return mb.IsGenericMethodDefinition;
- }
-
- /// <summary>
- /// Whether `mb' is a generic method.
- /// </summary>
- public static bool IsGenericMethod (MethodBase mb)
- {
- return mb.IsGenericMethod;
- }
-
- public static bool IsNullableType (Type t)
- {
- return generic_nullable_type == DropGenericTypeArguments (t);
- }
-#endregion
-
-#region MemberLookup implementation
-
- //
- // Whether we allow private members in the result (since FindMembers
- // uses NonPublic for both protected and private), we need to distinguish.
- //
-
- internal class Closure {
- internal bool private_ok;
-
- // Who is invoking us and which type is being queried currently.
- internal Type invocation_type;
- internal Type qualifier_type;
-
- // The assembly that defines the type is that is calling us
- internal Assembly invocation_assembly;
- internal IList almost_match;
-
- private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
- {
- if (invocation_type == null)
- return false;
-
- if (is_static && qualifier_type == null)
- // It resolved from a simple name, so it should be visible.
- return true;
-
- if (IsNestedChildOf (invocation_type, m.DeclaringType))
- return true;
-
- for (Type t = invocation_type; t != null; t = t.DeclaringType) {
- if (!IsFamilyAccessible (t, m.DeclaringType))
- continue;
-
- // Although a derived class can access protected members of its base class
- // it cannot do so through an instance of the base class (CS1540).
- // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
- if (is_static || qualifier_type == null ||
- IsInstantiationOfSameGenericType (t, qualifier_type) ||
- IsFamilyAccessible (qualifier_type, t))
- return true;
- }
-
- if (almost_match != null)
- almost_match.Add (m);
-
- return false;
- }
-
- //
- // This filter filters by name + whether it is ok to include private
- // members in the search
- //
- internal bool Filter (MemberInfo m, object filter_criteria)
- {
- //
- // Hack: we know that the filter criteria will always be in the
- // `closure' // fields.
- //
-
- if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
- return false;
-
- if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
- (invocation_type != null) &&
- IsPrivateAccessible (m.DeclaringType, invocation_type))
- return true;
-
- //
- // Ugly: we need to find out the type of `m', and depending
- // on this, tell whether we accept or not
- //
- if (m is MethodBase){
- MethodBase mb = (MethodBase) m;
- MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
-
- if (ma == MethodAttributes.Public)
- return true;
-
- if (ma == MethodAttributes.PrivateScope)
- return false;
-
- if (ma == MethodAttributes.Private)
- return private_ok ||
- IsPrivateAccessible (invocation_type, m.DeclaringType) ||
- IsNestedChildOf (invocation_type, m.DeclaringType);
-
- if (TypeManager.IsThisOrFriendAssembly (invocation_assembly, mb.DeclaringType.Assembly)) {
- if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
- return true;
- } else {
- if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
- return false;
- }
-
- // Family, FamORAssem or FamANDAssem
- return CheckValidFamilyAccess (mb.IsStatic, m);
- }
-
- if (m is FieldInfo){
- FieldInfo fi = (FieldInfo) m;
- FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
-
- if (fa == FieldAttributes.Public)
- return true;
-
- if (fa == FieldAttributes.PrivateScope)
- return false;
-
- if (fa == FieldAttributes.Private)
- return private_ok ||
- IsPrivateAccessible (invocation_type, m.DeclaringType) ||
- IsNestedChildOf (invocation_type, m.DeclaringType);
-
- if (TypeManager.IsThisOrFriendAssembly (invocation_assembly, fi.DeclaringType.Assembly)) {
- if ((fa == FieldAttributes.Assembly) ||
- (fa == FieldAttributes.FamORAssem))
- return true;
- } else {
- if ((fa == FieldAttributes.Assembly) ||
- (fa == FieldAttributes.FamANDAssem))
- return false;
- }
-
- // Family, FamORAssem or FamANDAssem
- return CheckValidFamilyAccess (fi.IsStatic, m);
- }
-
- //
- // EventInfos and PropertyInfos, return true because they lack
- // permission information, so we need to check later on the methods.
- //
- return true;
- }
- }
-
- static Closure closure;
- static MemberFilter FilterWithClosure_delegate;
-
- //
- // Looks up a member called `name' in the `queried_type'. This lookup
- // is done by code that is contained in the definition for `invocation_type'
- // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
- //
- // `invocation_type' is used to check whether we're allowed to access the requested
- // member wrt its protection level.
- //
- // When called from MemberAccess, `qualifier_type' is the type which is used to access
- // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
- // is B and qualifier_type is A). This is used to do the CS1540 check.
- //
- // When resolving a SimpleName, `qualifier_type' is null.
- //
- // The `qualifier_type' is used for the CS1540 check; it's normally either null or
- // the same than `queried_type' - except when we're being called from BaseAccess;
- // in this case, `invocation_type' is the current type and `queried_type' the base
- // type, so this'd normally trigger a CS1540.
- //
- // The binding flags are `bf' and the kind of members being looked up are `mt'
- //
- // The return value always includes private members which code in `invocation_type'
- // is allowed to access (using the specified `qualifier_type' if given); only use
- // BindingFlags.NonPublic to bypass the permission check.
- //
- // The 'almost_match' argument is used for reporting error CS1540.
- //
- // Returns an array of a single element for everything but Methods/Constructors
- // that might return multiple matches.
- //
- public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
- Type queried_type, MemberTypes mt,
- BindingFlags original_bf, string name, IList almost_match)
- {
- Timer.StartTimer (TimerType.MemberLookup);
-
- MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
- queried_type, mt, original_bf, name, almost_match);
-
- Timer.StopTimer (TimerType.MemberLookup);
-
- return retval;
- }
-
- static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
- Type queried_type, MemberTypes mt,
- BindingFlags original_bf, string name, IList almost_match)
- {
- BindingFlags bf = original_bf;
-
- ArrayList method_list = null;
- Type current_type = queried_type;
- bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
- bool skip_iface_check = true, used_cache = false;
- bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
-
- closure.invocation_type = invocation_type;
- closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
- closure.qualifier_type = qualifier_type;
- closure.almost_match = almost_match;
-
- // This is from the first time we find a method
- // in most cases, we do not actually find a method in the base class
- // so we can just ignore it, and save the arraylist allocation
- MemberInfo [] first_members_list = null;
- bool use_first_members_list = false;
-
- do {
- MemberInfo [] list;
-
- //
- // `NonPublic' is lame, because it includes both protected and
- // private methods, so we need to control this behavior by
- // explicitly tracking if a private method is ok or not.
- //
- // The possible cases are:
- // public, private and protected (internal does not come into the
- // equation)
- //
- if ((invocation_type != null) &&
- ((invocation_type == current_type) ||
- IsNestedChildOf (invocation_type, current_type)) ||
- always_ok_flag)
- bf = original_bf | BindingFlags.NonPublic;
- else
- bf = original_bf;
-
- closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
-
- Timer.StopTimer (TimerType.MemberLookup);
-
- list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
-
- Timer.StartTimer (TimerType.MemberLookup);
-
- //
- // When queried for an interface type, the cache will automatically check all
- // inherited members, so we don't need to do this here. However, this only
- // works if we already used the cache in the first iteration of this loop.
- //
- // If we used the cache in any further iteration, we can still terminate the
- // loop since the cache always looks in all base classes.
- //
-
- if (used_cache)
- searching = false;
- else
- skip_iface_check = false;
-
- if (current_type == TypeManager.object_type)
- searching = false;
- else {
- current_type = current_type.BaseType;
-
- //
- // This happens with interfaces, they have a null
- // basetype. Look members up in the Object class.
- //
- if (current_type == null) {
- current_type = TypeManager.object_type;
- searching = true;
- }
- }
-
- if (list.Length == 0)
- continue;
-
- //
- // Events and types are returned by both `static' and `instance'
- // searches, which means that our above FindMembers will
- // return two copies of the same.
- //
- if (list.Length == 1 && !(list [0] is MethodBase)){
- return list;
- }
-
- //
- // Multiple properties: we query those just to find out the indexer
- // name
- //
- if (list [0] is PropertyInfo)
- return list;
-
- //
- // We found an event: the cache lookup returns both the event and
- // its private field.
- //
- if (list [0] is EventInfo) {
- if ((list.Length == 2) && (list [1] is FieldInfo))
- return new MemberInfo [] { list [0] };
-
- return list;
- }
-
- //
- // We found methods, turn the search into "method scan"
- // mode.
- //
-
- if (first_members_list != null) {
- if (use_first_members_list) {
- method_list = CopyNewMethods (method_list, first_members_list);
- use_first_members_list = false;
- }
-
- method_list = CopyNewMethods (method_list, list);
- } else {
- first_members_list = list;
- use_first_members_list = true;
- mt &= (MemberTypes.Method | MemberTypes.Constructor);
- }
- } while (searching);
-
- if (use_first_members_list)
- return first_members_list;
-
- if (method_list != null && method_list.Count > 0) {
- return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
- }
- //
- // This happens if we already used the cache in the first iteration, in this case
- // the cache already looked in all interfaces.
- //
- if (skip_iface_check)
- return null;
-
- //
- // Interfaces do not list members they inherit, so we have to
- // scan those.
- //
- if (!queried_type.IsInterface)
- return null;
-
- if (queried_type.IsArray)
- queried_type = TypeManager.array_type;
-
- Type [] ifaces = GetInterfaces (queried_type);
- if (ifaces == null)
- return null;
-
- foreach (Type itype in ifaces){
- MemberInfo [] x;
-
- x = MemberLookup (null, null, itype, mt, bf, name, null);
- if (x != null)
- return x;
- }
-
- return null;
- }
-
- public 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.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), AllMembers);
-
- if (name.StartsWith ("remove_"))
- 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_"))
- return Operator.GetName (name) != null;
-
- 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);
- int g_count = 0;
- int s_count = 0;
- if (get_method != null && set_method != null) {
- g_count = get_method.GetParameters ().Length;
- s_count = set_method.GetParameters ().Length;
- if (g_count + 1 != s_count)
- return false;
- } else if (get_method != null) {
- g_count = get_method.GetParameters ().Length;
- } else if (set_method != null) {
- s_count = set_method.GetParameters ().Length;
- }
-
- //
- // DefaultMemberName and indexer name has to match to identify valid C# indexer
- //
- PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
- if ((s_count > 1 || g_count > 0) && pa.IsDefined) {
- object[] o = pi.DeclaringType.GetCustomAttributes (pa.Type, false);
- if (o.Length == 0)
- return false;
-
- DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0];
- if (dma.MemberName != pi.Name)
- return false;
- if (get_method != null && "get_" + dma.MemberName != get_method.Name)
- return false;
- if (set_method != null && "set_" + dma.MemberName != set_method.Name)
- return false;
- }
-
- return true;
- }
-
-#endregion
-
-}
-
- class InternalType
- {
- public static readonly Type AnonymousMethod = typeof (AnonymousMethodBody);
- public static readonly Type Arglist = typeof (ArglistAccess);
- public static readonly Type Dynamic = new DynamicType ();
- public static readonly Type MethodGroup = typeof (MethodGroupExpr);
- }
-
-/// <summary>
-/// There is exactly one instance of this class per type.
-/// </summary>
-public sealed class TypeHandle : IMemberContainer {
- public readonly IMemberContainer BaseType;
-
- readonly int id = ++next_id;
- static int next_id = 0;
-
- static TypeHandle ()
- {
- Reset ();
- }
-
- /// <summary>
- /// Lookup a TypeHandle instance for the given type. If the type doesn't have
- /// a TypeHandle yet, a new instance of it is created. This static method
- /// ensures that we'll only have one TypeHandle instance per type.
- /// </summary>
- private static TypeHandle GetTypeHandle (Type t)
- {
- TypeHandle handle = (TypeHandle) type_hash [t];
- if (handle != null)
- return handle;
-
- handle = new TypeHandle (t);
- type_hash.Add (t, handle);
- return handle;
- }
-
- public static MemberCache GetMemberCache (Type t)
- {
- return GetTypeHandle (t).MemberCache;
- }
-
- public static void CleanUp ()
- {
- type_hash = null;
- }
-
- public static void Reset ()
- {
- type_hash = new PtrHashtable ();
- }
-
- /// <summary>
- /// Returns the TypeHandle for TypeManager.object_type.
- /// </summary>
- public static IMemberContainer ObjectType {
- get {
- if (object_type != null)
- return object_type;
-
- object_type = GetTypeHandle (TypeManager.object_type);
-
- return object_type;
- }
- }
-
- /// <summary>
- /// Returns the TypeHandle for TypeManager.array_type.
- /// </summary>
- public static TypeHandle ArrayType {
- get {
- if (array_type != null)
- return array_type;
-
- array_type = GetTypeHandle (TypeManager.array_type);
-
- return array_type;
- }
- }
-
- private static PtrHashtable type_hash;
-
- private static TypeHandle object_type = null;
- private static TypeHandle array_type = null;
-
- private Type type;
- private string full_name;
- private bool is_interface;
- private MemberCache member_cache;
- private MemberCache base_cache;
-
- private TypeHandle (Type type)
- {
- this.type = type;
- full_name = type.FullName != null ? type.FullName : type.Name;
- if (type.BaseType != null) {
- base_cache = TypeManager.LookupMemberCache (type.BaseType);
- BaseType = base_cache.Container;
- } else if (type.IsInterface)
- base_cache = TypeManager.LookupBaseInterfacesCache (type);
- this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
- this.member_cache = new MemberCache (this);
- }
-
- // IMemberContainer methods
-
- public string Name {
- get {
- return full_name;
- }
- }
-
- public Type Type {
- get {
- return type;
- }
- }
-
- public MemberCache BaseCache {
- get {
- return base_cache;
- }
- }
-
- public bool IsInterface {
- get {
- return is_interface;
- }
- }
-
- public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
- {
- MemberInfo [] members;
-
- if (type is GenericTypeParameterBuilder)
- return MemberList.Empty;
-
-#if MS_COMPATIBLE
- type = TypeManager.DropGenericTypeArguments (type);
-#endif
- if (mt == MemberTypes.Event)
- members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
- else
- members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
- null, null);
-
- if (members.Length == 0)
- return MemberList.Empty;
-
- Array.Reverse (members);
- return new MemberList (members);
- }
-
- // IMemberFinder methods
-
- public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
- MemberFilter filter, object criteria)
- {
- return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
- }
-
- public MemberCache MemberCache {
- get {
- return member_cache;
- }
- }
-
- public override string ToString ()
- {
- if (BaseType != null)
- return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
- else
- return "TypeHandle (" + id + "," + Name + ")";
- }
-}