X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fimport.cs;h=578b06f416c503d0cd4f7b6826ca1924934f77bd;hb=86e618a14a7ae2d8be1a6eb01cb3db09283f0eaf;hp=46eea885e195c10d44cbdcd1149c6e5dc79e6a7f;hpb=58fdac7b8a191881c721c1e04592fc4a8b4b6ab1;p=mono.git diff --git a/mcs/mcs/import.cs b/mcs/mcs/import.cs index 46eea885e19..578b06f416c 100644 --- a/mcs/mcs/import.cs +++ b/mcs/mcs/import.cs @@ -9,24 +9,123 @@ // using System; -using System.Reflection; using System.Runtime.CompilerServices; using System.Linq; using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.InteropServices; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +#else +using MetaType = System.Type; +using System.Reflection; +#endif namespace Mono.CSharp { - public class ReflectionMetaImporter + public abstract class MetadataImporter { - Dictionary import_cache; - Dictionary type_2_predefined; - Dictionary assembly_2_definition; + // + // Dynamic types reader with additional logic to reconstruct a dynamic + // type using DynamicAttribute values + // + struct DynamicTypeReader + { + static readonly bool[] single_attribute = { true }; + + public int Position; + bool[] flags; + + // There is no common type for CustomAttributeData and we cannot + // use ICustomAttributeProvider + object provider; + + // + // A member provider which can be used to get CustomAttributeData + // + public DynamicTypeReader (object provider) + { + Position = 0; + flags = null; + this.provider = provider; + } + + // + // Returns true when object at local position has dynamic attribute flag + // + public bool IsDynamicObject { + get { + if (provider != null) + ReadAttribute (); + + return flags != null && Position < flags.Length && flags[Position]; + } + } + + // + // Returns true when DynamicAttribute exists + // + public bool HasDynamicAttribute { + get { + if (provider != null) + ReadAttribute (); + + return flags != null; + } + } + + void ReadAttribute () + { + IList cad; + if (provider is MemberInfo) { + cad = CustomAttributeData.GetCustomAttributes ((MemberInfo) provider); + } else if (provider is ParameterInfo) { + cad = CustomAttributeData.GetCustomAttributes ((ParameterInfo) provider); + } else { + provider = null; + return; + } + + if (cad.Count > 0) { + foreach (var ca in cad) { + var type = ca.Constructor.DeclaringType; + if (type.Name != "DynamicAttribute" && type.Namespace != CompilerServicesNamespace) + continue; + + if (ca.ConstructorArguments.Count == 0) { + flags = single_attribute; + break; + } + + var arg_type = ca.ConstructorArguments[0].ArgumentType; + + if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) { + var carg = (IList) ca.ConstructorArguments[0].Value; + flags = new bool[carg.Count]; + for (int i = 0; i < flags.Length; ++i) { + if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean) + flags[i] = (bool) carg[i].Value; + } + + break; + } + } + } + + provider = null; + } + } - public ReflectionMetaImporter () + protected readonly Dictionary import_cache; + protected readonly Dictionary buildin_types; + readonly Dictionary assembly_2_definition; + + public static readonly string CompilerServicesNamespace = "System.Runtime.CompilerServices"; + + protected MetadataImporter () { - import_cache = new Dictionary (1024, ReferenceEquality.Default); + import_cache = new Dictionary (1024, ReferenceEquality.Default); + buildin_types = new Dictionary (40, ReferenceEquality.Default); assembly_2_definition = new Dictionary (ReferenceEquality.Default); IgnorePrivateMembers = true; } @@ -43,47 +142,9 @@ namespace Mono.CSharp #endregion - public void Initialize () - { - // Setup mapping for predefined types - type_2_predefined = new Dictionary () { - { typeof (object), TypeManager.object_type }, - { typeof (System.ValueType), TypeManager.value_type }, - { typeof (System.Attribute), TypeManager.attribute_type }, - - { typeof (int), TypeManager.int32_type }, - { typeof (long), TypeManager.int64_type }, - { typeof (uint), TypeManager.uint32_type }, - { typeof (ulong), TypeManager.uint64_type }, - { typeof (byte), TypeManager.byte_type }, - { typeof (sbyte), TypeManager.sbyte_type }, - { typeof (short), TypeManager.short_type }, - { typeof (ushort), TypeManager.ushort_type }, - - { typeof (System.Collections.IEnumerator), TypeManager.ienumerator_type }, - { typeof (System.Collections.IEnumerable), TypeManager.ienumerable_type }, - { typeof (System.IDisposable), TypeManager.idisposable_type }, - - { typeof (char), TypeManager.char_type }, - { typeof (string), TypeManager.string_type }, - { typeof (float), TypeManager.float_type }, - { typeof (double), TypeManager.double_type }, - { typeof (decimal), TypeManager.decimal_type }, - { typeof (bool), TypeManager.bool_type }, - { typeof (System.IntPtr), TypeManager.intptr_type }, - { typeof (System.UIntPtr), TypeManager.uintptr_type }, - - { typeof (System.MulticastDelegate), TypeManager.multicast_delegate_type }, - { typeof (System.Delegate), TypeManager.delegate_type }, - { typeof (System.Enum), TypeManager.enum_type }, - { typeof (System.Array), TypeManager.array_type }, - { typeof (void), TypeManager.void_type }, - { typeof (System.Type), TypeManager.type_type }, - { typeof (System.Exception), TypeManager.exception_type }, - { typeof (System.RuntimeFieldHandle), TypeManager.runtime_field_handle_type }, - { typeof (System.RuntimeTypeHandle), TypeManager.runtime_handle_type } - }; - } + protected abstract MemberKind DetermineKindFromBaseType (MetaType baseType); + protected abstract bool HasVolatileModifier (MetaType[] modifiers); + public abstract void GetCustomAttributeTypeName (CustomAttributeData cad, out string typeNamespace, out string typeName); public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType) { @@ -104,18 +165,18 @@ namespace Mono.CSharp break; default: // Ignore private fields (even for error reporting) to not require extra dependencies - if (IgnorePrivateMembers || fi.IsDefined (typeof (CompilerGeneratedAttribute), false)) + if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace)) return null; mod = Modifiers.PRIVATE; break; } - var definition = new ImportedMemberDefinition (fi); + var definition = new ImportedMemberDefinition (fi, this); TypeSpec field_type; try { - field_type = ImportType (fi.FieldType, fi, 0); + field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi)); } catch (Exception e) { // TODO: I should construct fake TypeSpec based on TypeRef signature // but there is no way to do it with System.Reflection @@ -124,35 +185,32 @@ namespace Mono.CSharp } if ((fa & FieldAttributes.Literal) != 0) { - var c = Constant.CreateConstantFromValue (field_type, fi.GetValue (fi), Location.Null); + var c = Constant.CreateConstantFromValue (field_type, fi.GetRawConstantValue (), Location.Null); return new ConstSpec (declaringType, definition, field_type, fi, mod, c); } if ((fa & FieldAttributes.InitOnly) != 0) { if (field_type == TypeManager.decimal_type) { - var dc = ReadDecimalConstant (fi); + var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi)); if (dc != null) return new ConstSpec (declaringType, definition, field_type, fi, mod, dc); } mod |= Modifiers.READONLY; } else { - var reqs = fi.GetRequiredCustomModifiers (); - if (reqs.Length > 0) { - foreach (Type t in reqs) { - if (t == typeof (System.Runtime.CompilerServices.IsVolatile)) { - mod |= Modifiers.VOLATILE; - break; - } - } - } + var req_mod = fi.GetRequiredCustomModifiers (); + if (req_mod.Length > 0 && HasVolatileModifier (req_mod)) + mod |= Modifiers.VOLATILE; } - if ((fa & FieldAttributes.Static) != 0) + if ((fa & FieldAttributes.Static) != 0) { mod |= Modifiers.STATIC; + } else { + // Fixed buffers cannot be static + if (declaringType.IsStruct && field_type.IsStruct && field_type.IsNested && + HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "FixedBufferAttribute", CompilerServicesNamespace)) { - if (field_type.IsStruct) { - if (fi.IsDefined (typeof (FixedBufferAttribute), false)) { + // TODO: Sanity check on field_type (only few type are allowed) var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType); return new FixedFieldSpec (declaringType, definition, fi, element_field, mod); } @@ -169,13 +227,13 @@ namespace Mono.CSharp if (add.Modifiers != remove.Modifiers) throw new NotImplementedException ("Different accessor modifiers " + ei.Name); - var definition = new ImportedMemberDefinition (ei); - return new EventSpec (declaringType, definition, ImportType (ei.EventHandlerType, ei, 0), add.Modifiers, add, remove); + var definition = new ImportedMemberDefinition (ei, this); + return new EventSpec (declaringType, definition, ImportType (ei.EventHandlerType, new DynamicTypeReader (ei)), add.Modifiers, add, remove); } - T[] CreateGenericParameters (Type type, TypeSpec declaringType) where T : TypeSpec + TypeParameterSpec[] CreateGenericParameters (MetaType type, TypeSpec declaringType) { - Type[] tparams = type.GetGenericArguments (); + var tparams = type.GetGenericArguments (); int parent_owned_count; if (type.IsNested) { @@ -210,29 +268,63 @@ namespace Mono.CSharp if (tparams.Length - parent_owned_count == 0) return null; - return CreateGenericParameters (parent_owned_count, tparams, null, 0); + return CreateGenericParameters (parent_owned_count, tparams); } - T[] CreateGenericParameters (int first, Type[] tparams, ICustomAttributeProvider ca, int dynamicCursor) where T : TypeSpec + TypeParameterSpec[] CreateGenericParameters (int first, MetaType[] tparams) { - var tspec = new T [tparams.Length - first]; + var tspec = new TypeParameterSpec[tparams.Length - first]; for (int pos = first; pos < tparams.Length; ++pos) { var type = tparams[pos]; int index = pos - first; + tspec [index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false); + } + + return tspec; + } + + TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype) + { + ++dtype.Position; + + var tspec = new TypeSpec [tparams.Length - first]; + for (int pos = first; pos < tparams.Length; ++pos) { + var type = tparams[pos]; + int index = pos - first; + + TypeSpec spec; if (type.HasElementType) { var element = type.GetElementType (); - var spec = ImportType (element); + ++dtype.Position; + spec = ImportType (element, dtype); - if (type.IsArray) { - tspec[index] = (T) (TypeSpec) ArrayContainer.MakeType (spec, type.GetArrayRank ()); - continue; + if (!type.IsArray) { + throw new NotImplementedException ("Unknown element type " + type.ToString ()); } - throw new NotImplementedException ("Unknown element type " + type.ToString ()); + spec = ArrayContainer.MakeType (spec, type.GetArrayRank ()); + } else { + spec = CreateType (type, dtype, true); + + // + // We treat nested generic types as inflated internally where + // reflection uses type definition + // + // class A { + // IFoo> foo; // A is definition in this case + // } + // + // TODO: Is full logic from CreateType needed here as well? + // + if (type.IsGenericTypeDefinition) { + var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); + spec = spec.MakeGenericType (targs); + } } - tspec [index] = (T) CreateType (type, ca, dynamicCursor + index + 1, true); + ++dtype.Position; + tspec[index] = spec; } return tspec; @@ -250,10 +342,10 @@ namespace Mono.CSharp if (!mb.IsGenericMethodDefinition) throw new NotSupportedException ("assert"); - tparams = CreateGenericParameters(0, mb.GetGenericArguments (), null, 0); - definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams); + tparams = CreateGenericParameters (0, mb.GetGenericArguments ()); + definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams, this); } else { - definition = new ImportedMethodDefinition (mb, parameters); + definition = new ImportedMethodDefinition (mb, parameters, this); tparams = null; } @@ -286,7 +378,7 @@ namespace Mono.CSharp } var mi = (MethodInfo) mb; - returnType = ImportType (mi.ReturnType, mi.ReturnTypeCustomAttributes, 0); + returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter)); // Cannot set to OVERRIDE without full hierarchy checks // this flag indicates that the method could be override @@ -342,32 +434,40 @@ namespace Mono.CSharp // Strip reference wrapping // var el = p.ParameterType.GetElementType (); - types[i] = ImportType (el, p, 0); // TODO: 1 to be csc compatible + types[i] = ImportType (el, new DynamicTypeReader (p)); // TODO: 1-based positio to be csc compatible } else if (i == 0 && method.IsStatic && parent.IsStatic && parent.MemberDefinition.DeclaringAssembly.HasExtensionMethod && - HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (method)) != null) { + HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) { mod = Parameter.Modifier.This; types[i] = ImportType (p.ParameterType); } else { - types[i] = ImportType (p.ParameterType, p, 0); + types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p)); if (i >= pi.Length - 2 && types[i] is ArrayContainer) { - var cattrs = CustomAttributeData.GetCustomAttributes (p); - if (cattrs != null && cattrs.Any (l => l.Constructor.DeclaringType == typeof (ParamArrayAttribute))) { + if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) { mod = Parameter.Modifier.PARAMS; is_params = true; } } if (!is_params && p.IsOptional) { - object value = p.DefaultValue; + object value = p.RawDefaultValue; var ptype = types[i]; - if (((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter) || p.IsDefined (typeof (DecimalConstantAttribute), false)) { - var dtype = value == null ? ptype : ImportType (value.GetType ()); - default_value = Constant.CreateConstant (null, dtype, value, Location.Null); + if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeManager.IsReferenceType (ptype))) { + if (value == null) { + default_value = Constant.CreateConstant (null, ptype, null, Location.Null); + } else { + default_value = ImportParameterConstant (value).Resolve (null); + + if (ptype.IsEnum) { + default_value = new EnumConstant ((Constant) default_value, ptype).Resolve (null); + } + } } else if (value == Missing.Value) { default_value = EmptyExpression.MissingValue; - } else { + } else if (value == null) { default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null); + } else if (ptype == TypeManager.decimal_type) { + default_value = ImportParameterConstant (value).Resolve (null); } } } @@ -385,7 +485,6 @@ namespace Mono.CSharp new ParametersImported (par, types, is_params); } - // // Returns null when the property is not valid C# property // @@ -484,11 +583,11 @@ namespace Mono.CSharp } if (is_valid_property) - spec = new IndexerSpec (declaringType, new ImportedIndexerDefinition (pi, param), type, param, pi, mod); + spec = new IndexerSpec (declaringType, new ImportedIndexerDefinition (pi, param, this), type, param, pi, mod); } if (spec == null) - spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi), type, pi, mod); + spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi, this), type, pi, mod); if (!is_valid_property) { spec.IsNotRealProperty = true; @@ -503,55 +602,57 @@ namespace Mono.CSharp return spec; } - public TypeSpec CreateType (Type type) + public TypeSpec CreateType (MetaType type) + { + return CreateType (type, new DynamicTypeReader (), true); + } + + public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType) { - return CreateType (type, null, 0, true); + return CreateType (type, declaringType, new DynamicTypeReader (type), false); } - TypeSpec CreateType (Type type, ICustomAttributeProvider ca, int dynamicCursor, bool canImportBaseType) + TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType) { TypeSpec declaring_type; if (type.IsNested && !type.IsGenericParameter) - declaring_type = CreateType (type.DeclaringType, type.DeclaringType, 0, true); + declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true); else declaring_type = null; - return CreateType (type, declaring_type, ca, dynamicCursor, canImportBaseType); + return CreateType (type, declaring_type, dtype, canImportBaseType); } - public TypeSpec CreateType (Type type, TypeSpec declaringType, ICustomAttributeProvider ca, int dynamicCursor, bool canImportBaseType) + TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType) { TypeSpec spec; if (import_cache.TryGetValue (type, out spec)) { - if (ca == null) - return spec; - - if (type == typeof (object)) { - if (IsDynamicType (ca, dynamicCursor)) + if (spec == TypeManager.object_type) { + if (dtype.IsDynamicObject) return InternalType.Dynamic; return spec; } - if (!spec.IsGeneric) + if (!spec.IsGeneric || type.IsGenericTypeDefinition) return spec; -#if NET_4_0 - if (!ca.IsDefined (typeof (DynamicAttribute), false)) -#endif + if (!dtype.HasDynamicAttribute) return spec; // We've found same object in the cache but this one has a dynamic custom attribute // and it's most likely dynamic version of same type IFoo agains IFoo - // Do resolve the type process again in that case + // Do type resolve process again in that case + + // TODO: Handle cases where they still unify } - if (type.IsGenericType && !type.IsGenericTypeDefinition) { + if (type.IsGenericType && !type.IsGenericTypeDefinition) { var type_def = type.GetGenericTypeDefinition (); - var targs = CreateGenericParameters (0, type.GetGenericArguments (), ca, dynamicCursor); + var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); if (declaringType == null) { // Simple case, no nesting - spec = CreateType (type_def, null, null, 0, canImportBaseType); + spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType); spec = spec.MakeGenericType (targs); } else { // @@ -632,12 +733,18 @@ namespace Mono.CSharp kind = MemberKind.Interface; } else if (type.IsGenericParameter) { kind = MemberKind.TypeParameter; - } else if (type.IsClass || type.IsAbstract) { // System.Reflection: System.Enum returns false for IsClass - if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) { - kind = MemberKind.Delegate; - mod |= Modifiers.SEALED; - } else { + } else { + var base_type = type.BaseType; + if (base_type == null || (ma & TypeAttributes.Abstract) != 0) { kind = MemberKind.Class; + } else { + kind = DetermineKindFromBaseType (base_type); + if (kind == MemberKind.Struct || kind == MemberKind.Delegate) { + mod |= Modifiers.SEALED; + } + } + + if (kind == MemberKind.Class) { if ((ma & TypeAttributes.Sealed) != 0) { mod |= Modifiers.SEALED; if ((ma & TypeAttributes.Abstract) != 0) @@ -646,15 +753,10 @@ namespace Mono.CSharp mod |= Modifiers.ABSTRACT; } } - } else if (type.IsEnum) { - kind = MemberKind.Enum; - } else { - kind = MemberKind.Struct; - mod |= Modifiers.SEALED; } - var definition = new ImportedTypeDefinition (this, type); - PredefinedTypeSpec pt; + var definition = new ImportedTypeDefinition (type, this); + BuildinTypeSpec pt; if (kind == MemberKind.Enum) { const BindingFlags underlying_member = BindingFlags.DeclaredOnly | @@ -674,13 +776,13 @@ namespace Mono.CSharp // Return as type_cache was updated return CreateTypeParameter (type, declaringType); } else if (type.IsGenericTypeDefinition) { - definition.TypeParameters = CreateGenericParameters(type, declaringType); + definition.TypeParameters = CreateGenericParameters (type, declaringType); // Constraints are not loaded on demand and can reference this type if (import_cache.TryGetValue (type, out spec)) return spec; - } else if (type_2_predefined.TryGetValue (type, out pt)) { + } else if (buildin_types.TryGetValue (type, out pt)) { spec = pt; pt.SetDefinition (definition, type); } @@ -708,7 +810,7 @@ namespace Mono.CSharp if (!assembly_2_definition.TryGetValue (assembly, out def)) { // This can happen in dynamic context only - def = new ImportedAssemblyDefinition (assembly); + def = new ImportedAssemblyDefinition (assembly, this); assembly_2_definition.Add (assembly, def); def.ReadAttributes (); } @@ -716,33 +818,36 @@ namespace Mono.CSharp return def; } - public void ImportTypeBase (Type type) + public void ImportTypeBase (MetaType type) { TypeSpec spec = import_cache[type]; if (spec != null) ImportTypeBase (spec, type); } - void ImportTypeBase (TypeSpec spec, Type type) + void ImportTypeBase (TypeSpec spec, MetaType type) { if (spec.Kind == MemberKind.Interface) spec.BaseType = TypeManager.object_type; else if (type.BaseType != null) { + TypeSpec base_type; if (type.BaseType.IsGenericType) - spec.BaseType = CreateType (type.BaseType, type, 0, true); + base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true); else - spec.BaseType = CreateType (type.BaseType); + base_type = CreateType (type.BaseType); + + spec.BaseType = base_type; } var ifaces = type.GetInterfaces (); if (ifaces.Length > 0) { - foreach (Type iface in ifaces) { + foreach (var iface in ifaces) { spec.AddInterface (CreateType (iface)); } } } - TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType) + TypeParameterSpec CreateTypeParameter (MetaType type, TypeSpec declaringType) { Variance variance; switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) { @@ -771,7 +876,7 @@ namespace Mono.CSharp } TypeParameterSpec spec; - var def = new ImportedTypeParameterDefinition (type); + var def = new ImportedTypeParameterDefinition (type, this); if (type.DeclaringMethod != null) spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type); else @@ -792,12 +897,7 @@ namespace Mono.CSharp } if (ct.IsClass) { - if (ct == typeof (ValueType)) { - spec.BaseType = TypeManager.value_type; - } else { - spec.BaseType = CreateType (ct); - } - + spec.BaseType = CreateType (ct); continue; } @@ -813,68 +913,26 @@ namespace Mono.CSharp return spec; } - static Type HasExtensionAttribute (IList attributes) - { - foreach (var attr in attributes) { - var dt = attr.Constructor.DeclaringType; - if (dt.Name == "ExtensionAttribute" && dt.Namespace == "System.Runtime.CompilerServices") { - return dt; - } - } - - return null; - } - - public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace) - { - // It can be used more than once when importing same assembly - // into 2 or more global aliases - ImportedAssemblyDefinition definition; - if (!assembly_2_definition.TryGetValue (assembly, out definition)) { - definition = new ImportedAssemblyDefinition (assembly); - assembly_2_definition.Add (assembly, definition); - - definition.ReadAttributes (); - } - - Type extension_type = definition.HasExtensionMethod ? HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (assembly)) : null; - - // - // This part tries to simulate loading of top-level - // types only, any missing dependencies are ignores here. - // Full error report is reported later when the type is - // actually used - // - Type[] all_types; - try { - all_types = assembly.GetTypes (); - } catch (ReflectionTypeLoadException e) { - all_types = e.Types; - } - - ImportTypes (all_types, targetNamespace, extension_type); - } - - public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace) + // + // Test for a custom attribute type match. Custom attributes are not really predefined globaly + // they can be assembly specific therefore we do check based on names only + // + public bool HasAttribute (IList attributesData, string attrName, string attrNamespace) { - var module_definition = new ImportedModuleDefinition (module, this); - module_definition.ReadAttributes (); - - Type extension_type = HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (module)); + if (attributesData.Count == 0) + return false; - Type[] all_types; - try { - all_types = module.GetTypes (); - } catch (ReflectionTypeLoadException e) { - all_types = e.Types; + string ns, name; + foreach (var attr in attributesData) { + GetCustomAttributeTypeName (attr, out ns, out name); + if (name == attrName && ns == attrNamespace) + return true; } - ImportTypes (all_types, targetNamespace, extension_type); - - return module_definition; + return false; } - void ImportTypes (Type[] types, Namespace targetNamespace, Type extension_type) + protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool hasExtensionTypes) { Namespace ns = targetNamespace; string prev_namespace = null; @@ -889,7 +947,7 @@ namespace Mono.CSharp if (t.Name[0] == '<') continue; - var it = CreateType (t, null, t, 0, true); + var it = CreateType (t, null, new DynamicTypeReader (t), true); if (it == null) continue; @@ -900,22 +958,64 @@ namespace Mono.CSharp ns.AddType (it); - if (it.IsStatic && extension_type != null && t.IsDefined (extension_type, false)) { + if (it.IsStatic && hasExtensionTypes && + HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) { it.SetExtensionMethodContainer (); } } } - public TypeSpec ImportType (Type type) + static Constant ImportParameterConstant (object value) { - return ImportType (type, null, 0); + // + // Get type of underlying value as int constant can be used for object + // parameter type. This is not allowed in C# but other languages can do that + // + switch (System.Type.GetTypeCode (value.GetType ())) { + case TypeCode.Boolean: + return new BoolConstant ((bool) value, Location.Null); + case TypeCode.Byte: + return new ByteConstant ((byte) value, Location.Null); + case TypeCode.Char: + return new CharConstant ((char) value, Location.Null); + case TypeCode.Decimal: + return new DecimalConstant ((decimal) value, Location.Null); + case TypeCode.Double: + return new DoubleConstant ((double) value, Location.Null); + case TypeCode.Int16: + return new ShortConstant ((short) value, Location.Null); + case TypeCode.Int32: + return new IntConstant ((int) value, Location.Null); + case TypeCode.Int64: + return new LongConstant ((long) value, Location.Null); + case TypeCode.SByte: + return new SByteConstant ((sbyte) value, Location.Null); + case TypeCode.Single: + return new FloatConstant ((float) value, Location.Null); + case TypeCode.String: + return new StringConstant ((string) value, Location.Null); + case TypeCode.UInt16: + return new UShortConstant ((ushort) value, Location.Null); + case TypeCode.UInt32: + return new UIntConstant ((uint) value, Location.Null); + case TypeCode.UInt64: + return new ULongConstant ((ulong) value, Location.Null); + } + + throw new NotImplementedException (value.GetType ().ToString ()); + } + + public TypeSpec ImportType (MetaType type) + { + return ImportType (type, new DynamicTypeReader (type)); } - public TypeSpec ImportType (Type type, ICustomAttributeProvider ca, int dynamicCursor) + TypeSpec ImportType (MetaType type, DynamicTypeReader dtype) { if (type.HasElementType) { var element = type.GetElementType (); - var spec = ImportType (element, ca, dynamicCursor + 1); + ++dtype.Position; + var spec = ImportType (element, dtype); if (type.IsArray) return ArrayContainer.MakeType (spec, type.GetArrayRank ()); @@ -927,21 +1027,7 @@ namespace Mono.CSharp throw new NotImplementedException ("Unknown element type " + type.ToString ()); } - return CreateType (type, ca, dynamicCursor, true); - } - - static bool IsDynamicType (ICustomAttributeProvider ca, int index) - { -#if NET_4_0 - if (ca.IsDefined (typeof (DynamicAttribute), false)) { - if (index == 0) - return true; - - var v = (DynamicAttribute) ca.GetCustomAttributes (typeof (DynamicAttribute), false)[0]; - return v.TransformFlags[index]; - } -#endif - return false; + return CreateType (type, dtype, true); } // @@ -949,13 +1035,28 @@ namespace Mono.CSharp // as IsInitOnly ('readonly' in C# parlance). We get its value from the // DecimalConstantAttribute metadata. // - static Constant ReadDecimalConstant (ICustomAttributeProvider fi) + Constant ReadDecimalConstant (IList attrs) { - object[] attrs = fi.GetCustomAttributes (typeof (DecimalConstantAttribute), false); - if (attrs.Length != 1) + if (attrs.Count == 0) return null; - return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null); + string name, ns; + foreach (var ca in attrs) { + GetCustomAttributeTypeName (ca, out ns, out name); + if (name != "DecimalConstantAttribute" || ns != CompilerServicesNamespace) + continue; + + var value = new decimal ( + (int) (uint) ca.ConstructorArguments[4].Value, + (int) (uint) ca.ConstructorArguments[3].Value, + (int) (uint) ca.ConstructorArguments[2].Value, + (byte) ca.ConstructorArguments[1].Value != 0, + (byte) ca.ConstructorArguments[0].Value); + + return new DecimalConstant (value, Location.Null).Resolve (null); + } + + return null; } static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType) @@ -1018,8 +1119,9 @@ namespace Mono.CSharp public string[] Conditionals; public string DefaultIndexerName; public bool IsNotCLSCompliant; + public TypeSpec CoClass; - public static AttributesBag Read (MemberInfo mi) + public static AttributesBag Read (MemberInfo mi, MetadataImporter importer) { AttributesBag bag = null; List conditionals = null; @@ -1027,9 +1129,13 @@ namespace Mono.CSharp // It should not throw any loading exception IList attrs = CustomAttributeData.GetCustomAttributes (mi); + string ns, name; foreach (var a in attrs) { - var type = a.Constructor.DeclaringType; - if (type == typeof (ObsoleteAttribute)) { + importer.GetCustomAttributeTypeName (a, out ns, out name); + if (name == "ObsoleteAttribute") { + if (ns != "System") + continue; + if (bag == null) bag = new AttributesBag (); @@ -1046,7 +1152,10 @@ namespace Mono.CSharp continue; } - if (type == typeof (ConditionalAttribute)) { + if (name == "ConditionalAttribute") { + if (ns != "System.Diagnostics") + continue; + if (bag == null) bag = new AttributesBag (); @@ -1057,7 +1166,10 @@ namespace Mono.CSharp continue; } - if (type == typeof (CLSCompliantAttribute)) { + if (name == "CLSCompliantAttribute") { + if (ns != "System") + continue; + if (bag == null) bag = new AttributesBag (); @@ -1067,7 +1179,10 @@ namespace Mono.CSharp // Type only attributes if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) { - if (type == typeof (DefaultMemberAttribute)) { + if (name == "DefaultMemberAttribute") { + if (ns != "System.Reflection") + continue; + if (bag == null) bag = new AttributesBag (); @@ -1075,7 +1190,10 @@ namespace Mono.CSharp continue; } - if (type == typeof (AttributeUsageAttribute)) { + if (name == "AttributeUsageAttribute") { + if (ns != "System") + continue; + if (bag == null) bag = new AttributesBag (); @@ -1088,6 +1206,18 @@ namespace Mono.CSharp } continue; } + + // Interface only attribute + if (name == "CoClassAttribute") { + if (ns != "System.Runtime.InteropServices") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.CoClass = importer.ImportType ((MetaType) a.ConstructorArguments[0].Value); + continue; + } } } @@ -1103,10 +1233,12 @@ namespace Mono.CSharp protected readonly MemberInfo provider; protected AttributesBag cattrs; + protected readonly MetadataImporter importer; - public ImportedMemberDefinition (MemberInfo provider) + public ImportedMemberDefinition (MemberInfo provider, MetadataImporter importer) { this.provider = provider; + this.importer = importer; } #region Properties @@ -1151,7 +1283,7 @@ namespace Mono.CSharp protected void ReadAttributes () { - cattrs = AttributesBag.Read (provider); + cattrs = AttributesBag.Read (provider, importer); } public void SetIsAssigned () @@ -1169,12 +1301,12 @@ namespace Mono.CSharp { readonly Module module; bool cls_compliant; - //ReflectionMetaImporter metaImporter; + readonly MetadataImporter importer; - public ImportedModuleDefinition (Module module, ReflectionMetaImporter metaImporter) + public ImportedModuleDefinition (Module module, MetadataImporter importer) { this.module = module; - //this.metaImporter = metaImporter; + this.importer = importer; } #region Properties @@ -1196,9 +1328,14 @@ namespace Mono.CSharp public void ReadAttributes () { IList attrs = CustomAttributeData.GetCustomAttributes (module); + + string ns, name; foreach (var a in attrs) { - var type = a.Constructor.DeclaringType; - if (type == typeof (CLSCompliantAttribute)) { + importer.GetCustomAttributeTypeName (a, out ns, out name); + if (name == "CLSCompliantAttribute") { + if (ns != "System") + continue; + cls_compliant = (bool) a.ConstructorArguments[0].Value; continue; } @@ -1245,16 +1382,18 @@ namespace Mono.CSharp { readonly Assembly assembly; readonly AssemblyName aname; + readonly MetadataImporter importer; bool cls_compliant; bool contains_extension_methods; List internals_visible_to; Dictionary internals_visible_to_cache; - public ImportedAssemblyDefinition (Assembly assembly) + public ImportedAssemblyDefinition (Assembly assembly, MetadataImporter importer) { this.assembly = assembly; this.aname = assembly.GetName (); + this.importer = importer; } #region Properties @@ -1354,14 +1493,20 @@ namespace Mono.CSharp { IList attrs = CustomAttributeData.GetCustomAttributes (assembly); + string ns, name; foreach (var a in attrs) { - var type = a.Constructor.DeclaringType; - if (type == typeof (CLSCompliantAttribute)) { - cls_compliant = (bool) a.ConstructorArguments[0].Value; + importer.GetCustomAttributeTypeName (a, out ns, out name); + + if (name == "CLSCompliantAttribute") { + if (ns == "System") + cls_compliant = (bool) a.ConstructorArguments[0].Value; continue; } - if (type == typeof (InternalsVisibleToAttribute)) { + if (name == "InternalsVisibleToAttribute") { + if (ns != MetadataImporter.CompilerServicesNamespace) + continue; + string s = a.ConstructorArguments[0].Value as string; if (s == null) continue; @@ -1374,8 +1519,10 @@ namespace Mono.CSharp continue; } - if (type.Name == "ExtensionAttribute" && type.Namespace == "System.Runtime.CompilerServices") { - contains_extension_methods = true; + if (name == "ExtensionAttribute") { + if (ns == MetadataImporter.CompilerServicesNamespace) + contains_extension_methods = true; + continue; } } @@ -1391,8 +1538,8 @@ namespace Mono.CSharp { readonly AParametersCollection parameters; - public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters) - : base (provider) + public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters, MetadataImporter importer) + : base (provider, importer) { this.parameters = parameters; } @@ -1418,8 +1565,8 @@ namespace Mono.CSharp { readonly AParametersCollection parameters; - public ImportedIndexerDefinition (PropertyInfo provider, AParametersCollection parameters) - : base (provider) + public ImportedIndexerDefinition (PropertyInfo provider, AParametersCollection parameters, MetadataImporter importer) + : base (provider, importer) { this.parameters = parameters; } @@ -1443,10 +1590,10 @@ namespace Mono.CSharp class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition { - TypeParameterSpec[] tparams; + readonly TypeParameterSpec[] tparams; - public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams) - : base (provider, parameters) + public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams, MetadataImporter importer) + : base (provider, parameters, importer) { this.tparams = tparams; } @@ -1472,19 +1619,17 @@ namespace Mono.CSharp { TypeParameterSpec[] tparams; string name; - ReflectionMetaImporter meta_import; - public ImportedTypeDefinition (ReflectionMetaImporter metaImport, Type type) - : base (type) + public ImportedTypeDefinition (MetaType type, MetadataImporter importer) + : base (type, importer) { - this.meta_import = metaImport; } #region Properties public IAssemblyDefinition DeclaringAssembly { get { - return meta_import.GetAssemblyDefinition (provider.Module.Assembly); + return importer.GetAssemblyDefinition (provider.Module.Assembly); } } @@ -1492,8 +1637,11 @@ namespace Mono.CSharp get { if (name == null) { name = base.Name; - if (tparams != null) - name = name.Substring (0, name.IndexOf ('`')); + if (tparams != null) { + int arity_start = name.IndexOf ('`'); + if (arity_start > 0) + name = name.Substring (0, arity_start); + } } return name; @@ -1502,7 +1650,7 @@ namespace Mono.CSharp public string Namespace { get { - return ((Type) provider).Namespace; + return ((MetaType) provider).Namespace; } } @@ -1525,12 +1673,10 @@ namespace Mono.CSharp public TypeSpec GetAttributeCoClass () { - // TODO: Use ReadAttributes - var attr = provider.GetCustomAttributes (typeof (CoClassAttribute), false); - if (attr.Length < 1) - return null; + if (cattrs == null) + ReadAttributes (); - return meta_import.CreateType (((CoClassAttribute) attr[0]).CoClass); + return cattrs.CoClass; } public string GetAttributeDefaultMember () @@ -1549,9 +1695,26 @@ namespace Mono.CSharp return cattrs.AttributeUsage; } + public MetaType GetMissingBaseType () + { +#if STATIC + MetaType mt = (MetaType) provider; + do { + if (mt is MissingType) + break; + + mt = mt.BaseType; + } while (mt != null); + + return mt; +#else + return null; +#endif + } + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) { - var a = meta_import.GetAssemblyDefinition (provider.Module.Assembly); + var a = importer.GetAssemblyDefinition (provider.Module.Assembly); return a == assembly || a.IsFriendAssemblyTo (assembly); } @@ -1560,12 +1723,12 @@ namespace Mono.CSharp // // Not interested in members of nested private types unless the importer needs them // - if (declaringType.IsPrivate && meta_import.IgnorePrivateMembers) { + if (declaringType.IsPrivate && importer.IgnorePrivateMembers) { cache = MemberCache.Empty; return; } - var loading_type = (Type) provider; + var loading_type = (MetaType) provider; const BindingFlags all_members = BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; @@ -1598,13 +1761,13 @@ namespace Mono.CSharp if (member.MemberType != MemberTypes.NestedType) continue; - Type t = (Type) member; + var t = (MetaType) member; // Ignore compiler generated types, mostly lambda containers - if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false)) + if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate) continue; - imported = meta_import.CreateType (t, declaringType, t, 0, false); + imported = importer.CreateNestedType (t, declaringType); cache.AddMember (imported); } @@ -1612,7 +1775,12 @@ namespace Mono.CSharp if (member.MemberType != MemberTypes.NestedType) continue; - meta_import.ImportTypeBase ((Type) member); + var t = (MetaType) member; + + if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate) + continue; + + importer.ImportTypeBase (t); } } @@ -1628,7 +1796,7 @@ namespace Mono.CSharp var attrs = mb.Attributes; if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) { - if (meta_import.IgnorePrivateMembers) + if (importer.IgnorePrivateMembers) continue; // Ignore explicitly implemented members @@ -1636,11 +1804,11 @@ namespace Mono.CSharp continue; // Ignore compiler generated methods - if (mb.IsDefined (typeof (CompilerGeneratedAttribute), false)) + if (importer.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", MetadataImporter.CompilerServicesNamespace)) continue; } - imported = meta_import.CreateMethod (mb, declaringType); + imported = importer.CreateMethod (mb, declaringType); if (imported.Kind == MemberKind.Method && !imported.IsGeneric) { if (possible_accessors == null) possible_accessors = new Dictionary (ReferenceEquality.Default); @@ -1671,7 +1839,7 @@ namespace Mono.CSharp if (get == null && set == null) continue; - imported = meta_import.CreateProperty (p, declaringType, get, set); + imported = importer.CreateProperty (p, declaringType, get, set); if (imported == null) continue; @@ -1697,8 +1865,8 @@ namespace Mono.CSharp if (add == null || remove == null) continue; - event_spec = meta_import.CreateEvent (e, declaringType, add, remove); - if (!meta_import.IgnorePrivateMembers) { + event_spec = importer.CreateEvent (e, declaringType, add, remove); + if (!importer.IgnorePrivateMembers) { if (imported_events == null) imported_events = new List (); @@ -1710,7 +1878,7 @@ namespace Mono.CSharp case MemberTypes.Field: var fi = (FieldInfo) member; - imported = meta_import.CreateField (fi, declaringType); + imported = importer.CreateField (fi, declaringType); if (imported == null) continue; @@ -1751,8 +1919,8 @@ namespace Mono.CSharp class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition { - public ImportedTypeParameterDefinition (Type type) - : base (type) + public ImportedTypeParameterDefinition (MetaType type, MetadataImporter importer) + : base (type, importer) { }