//
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 static class Import
+ public abstract class MetadataImporter
{
- static Dictionary<Type, TypeSpec> import_cache;
- static Dictionary<Type, PredefinedTypeSpec> type_2_predefined;
+ //
+ // 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<CustomAttributeData> 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;
- public static void Initialize ()
+ 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<CustomAttributeTypedArgument>) 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;
+ }
+ }
+
+ protected readonly Dictionary<MetaType, TypeSpec> import_cache;
+ protected readonly Dictionary<MetaType, BuildinTypeSpec> buildin_types;
+ readonly Dictionary<Assembly, ImportedAssemblyDefinition> assembly_2_definition;
+
+ public static readonly string CompilerServicesNamespace = "System.Runtime.CompilerServices";
+
+ protected MetadataImporter ()
{
- import_cache = new Dictionary<Type, TypeSpec> (1024, ReferenceEquality<Type>.Default);
-
- // Setup mapping for predefined types
- type_2_predefined = new Dictionary<Type, PredefinedTypeSpec> () {
- { 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 }
- };
- }
-
- public static FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
+ import_cache = new Dictionary<MetaType, TypeSpec> (1024, ReferenceEquality<MetaType>.Default);
+ buildin_types = new Dictionary<MetaType, BuildinTypeSpec> (40, ReferenceEquality<MetaType>.Default);
+ assembly_2_definition = new Dictionary<Assembly, ImportedAssemblyDefinition> (ReferenceEquality<Assembly>.Default);
+ IgnorePrivateMembers = true;
+ }
+
+ #region Properties
+
+ public ICollection<ImportedAssemblyDefinition> Assemblies {
+ get {
+ return assembly_2_definition.Values;
+ }
+ }
+
+ public bool IgnorePrivateMembers { get; set; }
+
+ #endregion
+
+ 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)
{
Modifiers mod = 0;
var fa = fi.Attributes;
mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
break;
default:
+ // Ignore private fields (even for error reporting) to not require extra dependencies
+ if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
+ return null;
+
mod = Modifiers.PRIVATE;
break;
}
- // Ignore private fields (even for error reporting) to not require extra dependencies
- if (mod == Modifiers.PRIVATE)
- return null;
+ var definition = new ImportedMemberDefinition (fi, this);
+ TypeSpec field_type;
- var definition = new ImportedMemberDefinition (fi);
+ try {
+ 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
+ throw new InternalErrorException (e, "Cannot import field `{0}.{1}' referenced in assembly `{2}'",
+ declaringType.GetSignatureForError (), fi.Name, declaringType.MemberDefinition.DeclaringAssembly);
+ }
if ((fa & FieldAttributes.Literal) != 0) {
- var c = Constant.CreateConstantFromValue (ImportType (fi.FieldType), fi.GetValue (fi), Location.Null);
- return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, c);
+ 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 (fi.FieldType == typeof (decimal)) {
- var dc = ReadDecimalConstant (fi);
+ if (field_type == TypeManager.decimal_type) {
+ var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi));
if (dc != null)
- return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, dc);
+ 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 (fi.FieldType.IsValueType) {
- 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);
}
}
- return new FieldSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod);
+ return new FieldSpec (declaringType, definition, field_type, fi, mod);
}
- public static EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
+ public EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
{
add.IsAccessor = true;
remove.IsAccessor = true;
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), 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);
}
- static T[] CreateGenericParameters<T> (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) {
if (tparams.Length - parent_owned_count == 0)
return null;
- return CreateGenericParameters<T> (parent_owned_count, tparams);
+ return CreateGenericParameters (parent_owned_count, tparams);
}
- static T[] CreateGenericParameters<T> (int first, Type[] tparams) 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 = CreateType (element);
+ ++dtype.Position;
+ spec = ImportType (element, dtype);
- if (type.IsArray) {
- tspec[pos - first] = (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<T> {
+ // IFoo<A<T>> foo; // A<T> 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 [pos - first] = (T) CreateType (type);
+ ++dtype.Position;
+ tspec[index] = spec;
}
return tspec;
}
- public static MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
+ public MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
{
Modifiers mod = ReadMethodModifiers (mb, declaringType);
- //if (declaringType.IsInterface) {
- // mod = (mod & ~Modifiers.ABSTRACT) | Modifiers.VIRTUAL;
- //}
-
TypeParameterSpec[] tparams;
ImportedMethodDefinition definition;
- var parameters = ParametersImported.Create (declaringType, mb);
+ var parameters = CreateParameters (declaringType, mb.GetParameters (), mb);
if (mb.IsGenericMethod) {
if (!mb.IsGenericMethodDefinition)
throw new NotSupportedException ("assert");
- tparams = CreateGenericParameters<TypeParameterSpec>(0, mb.GetGenericArguments ());
- 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;
}
}
}
- returnType = ImportType (((MethodInfo)mb).ReturnType);
+ var mi = (MethodInfo) mb;
+ 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
}
//
- // Returns null when the property is not valid C# property
+ // Imports System.Reflection parameters
//
- public static PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
+ AParametersCollection CreateParameters (TypeSpec parent, ParameterInfo[] pi, MethodBase method)
{
- var definition = new ImportedMemberDefinition (pi);
+ int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
+
+ if (pi.Length == 0 && varargs == 0)
+ return ParametersCompiled.EmptyReadOnlyParameters;
+
+ TypeSpec[] types = new TypeSpec[pi.Length + varargs];
+ IParameterData[] par = new IParameterData[pi.Length + varargs];
+ bool is_params = false;
+ for (int i = 0; i < pi.Length; i++) {
+ ParameterInfo p = pi[i];
+ Parameter.Modifier mod = 0;
+ Expression default_value = null;
+ if (p.ParameterType.IsByRef) {
+ if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
+ mod = Parameter.Modifier.OUT;
+ else
+ mod = Parameter.Modifier.REF;
+ //
+ // Strip reference wrapping
+ //
+ var el = p.ParameterType.GetElementType ();
+ 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 &&
+ HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
+ mod = Parameter.Modifier.This;
+ types[i] = ImportType (p.ParameterType);
+ } else {
+ types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p));
+
+ if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
+ if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
+ mod = Parameter.Modifier.PARAMS;
+ is_params = true;
+ }
+ }
+
+ if (!is_params && p.IsOptional) {
+ object value = p.RawDefaultValue;
+ var ptype = types[i];
+ 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 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);
+ }
+ }
+ }
+
+ par[i] = new ParameterData (p.Name, mod, default_value);
+ }
+
+ if (varargs != 0) {
+ par[par.Length - 1] = new ArglistParameter (Location.Null);
+ types[types.Length - 1] = InternalType.Arglist;
+ }
+
+ return method != null ?
+ new ParametersImported (par, types, varargs != 0, is_params) :
+ new ParametersImported (par, types, is_params);
+ }
+
+ //
+ // Returns null when the property is not valid C# property
+ //
+ public PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
+ {
Modifiers mod = 0;
AParametersCollection param = null;
TypeSpec type = null;
}
if (is_valid_property)
- spec = new IndexerSpec (declaringType, definition, 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, definition, type, pi, mod);
+ spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi, this), type, pi, mod);
if (!is_valid_property) {
spec.IsNotRealProperty = true;
return spec;
}
- public static 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, declaringType, new DynamicTypeReader (type), false);
+ }
+
+ TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType)
{
TypeSpec declaring_type;
if (type.IsNested && !type.IsGenericParameter)
- declaring_type = CreateType (type.DeclaringType);
+ declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true);
else
declaring_type = null;
- return CreateType (type, declaring_type);
+ return CreateType (type, declaring_type, dtype, canImportBaseType);
}
- public static TypeSpec CreateType (Type type, TypeSpec declaringType)
+ TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType)
{
TypeSpec spec;
- if (import_cache.TryGetValue (type, out spec))
- return spec;
+ if (import_cache.TryGetValue (type, out spec)) {
+ if (spec == TypeManager.object_type) {
+ if (dtype.IsDynamicObject)
+ return InternalType.Dynamic;
- if (type.IsGenericType && !type.IsGenericTypeDefinition) {
- var type_def = type.GetGenericTypeDefinition ();
- spec = CreateType (type_def, declaringType);
+ return spec;
+ }
+
+ if (!spec.IsGeneric || type.IsGenericTypeDefinition)
+ return spec;
- var targs = CreateGenericParameters<TypeSpec> (type, null);
+ 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<object> agains IFoo<dynamic>
+ // Do type resolve process again in that case
+
+ // TODO: Handle cases where they still unify
+ }
- InflatedTypeSpec inflated;
- if (targs == null) {
- // Inflating nested non-generic type, same in TypeSpec::InflateMember
- inflated = new InflatedTypeSpec (spec, declaringType, TypeSpec.EmptyTypes);
+ if (type.IsGenericType && !type.IsGenericTypeDefinition) {
+ var type_def = type.GetGenericTypeDefinition ();
+ var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype);
+ if (declaringType == null) {
+ // Simple case, no nesting
+ spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
+ spec = spec.MakeGenericType (targs);
} else {
- // CreateGenericParameters constraint could inflate type
- if (import_cache.ContainsKey (type))
- return import_cache[type];
+ //
+ // Nested type case, converting .NET types like
+ // A`1.B`1.C`1<int, long, string> to typespec like
+ // A<int>.B<long>.C<string>
+ //
+ var nested_hierarchy = new List<TypeSpec> ();
+ while (declaringType.IsNested) {
+ nested_hierarchy.Add (declaringType);
+ declaringType = declaringType.DeclaringType;
+ }
- inflated = spec.MakeGenericType (targs);
+ int targs_pos = 0;
+ if (declaringType.Arity > 0) {
+ spec = declaringType.MakeGenericType (targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ());
+ targs_pos = spec.Arity;
+ } else {
+ spec = declaringType;
+ }
- // Use of reading cache to speed up reading only
- import_cache.Add (type, inflated);
+ for (int i = nested_hierarchy.Count; i != 0; --i) {
+ var t = nested_hierarchy [i - 1];
+ spec = MemberCache.FindNestedType (spec, t.Name, t.Arity);
+ if (t.Arity > 0) {
+ spec = spec.MakeGenericType (targs.Skip (targs_pos).Take (spec.Arity).ToArray ());
+ targs_pos += t.Arity;
+ }
+ }
+
+ string name = type.Name;
+ int index = name.IndexOf ('`');
+ if (index > 0)
+ name = name.Substring (0, index);
+
+ spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
+ if (spec.Arity > 0) {
+ spec = spec.MakeGenericType (targs.Skip (targs_pos).ToArray ());
+ }
}
- return inflated;
+ // Don't add generic type with dynamic arguments, they can interfere with same type
+ // using object type arguments
+ if (!spec.HasDynamicElement) {
+
+ // Add to reading cache to speed up reading
+ if (!import_cache.ContainsKey (type))
+ import_cache.Add (type, spec);
+ }
+
+ return spec;
}
Modifiers mod;
kind = MemberKind.Interface;
} else if (type.IsGenericParameter) {
kind = MemberKind.TypeParameter;
- } else if (type.IsClass || type.IsAbstract) { // SRE: System.Enum returns false for IsClass
- if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) {
- kind = MemberKind.Delegate;
- } else {
+ } else {
+ var base_type = type.BaseType;
+ if (base_type == null || (ma & TypeAttributes.Abstract) != 0) {
kind = MemberKind.Class;
-
- if (type == typeof (object)) {
-#if NET_4_0
- var pa = PredefinedAttributes.Get.Dynamic.Type;
- if (pa != null && type.IsDefined (typeof (DynamicAttribute), false))
- return InternalType.Dynamic;
-#endif
+ } 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)
mod |= Modifiers.ABSTRACT;
}
}
- } else if (type.IsEnum) {
- kind = MemberKind.Enum;
- } else {
- kind = MemberKind.Struct;
- mod |= Modifiers.SEALED;
}
- var definition = new ImportedTypeDefinition (type);
- PredefinedTypeSpec pt;
+ var definition = new ImportedTypeDefinition (type, this);
+ BuildinTypeSpec pt;
if (kind == MemberKind.Enum) {
const BindingFlags underlying_member = BindingFlags.DeclaredOnly |
var type_members = type.GetFields (underlying_member);
foreach (var type_member in type_members) {
- spec = new EnumSpec (declaringType, definition, Import.CreateType (type_member.FieldType), type, mod);
+ spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod);
break;
}
// Return as type_cache was updated
return CreateTypeParameter (type, declaringType);
} else if (type.IsGenericTypeDefinition) {
- definition.TypeParameters = CreateGenericParameters<TypeParameterSpec>(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);
}
import_cache.Add (type, spec);
- if (kind == MemberKind.Interface)
+ //
+ // Two stage setup as the base type can be inflated declaring type or
+ // another nested type inside same declaring type which has not been
+ // loaded, therefore we can import a base type of nested types once
+ // the types have been imported
+ //
+ if (canImportBaseType)
+ ImportTypeBase (spec, type);
+
+ return spec;
+ }
+
+ public ImportedAssemblyDefinition GetAssemblyDefinition (Assembly assembly)
+ {
+ ImportedAssemblyDefinition def;
+ if (!assembly_2_definition.TryGetValue (assembly, out def)) {
+
+ // This can happen in dynamic context only
+ def = new ImportedAssemblyDefinition (assembly, this);
+ assembly_2_definition.Add (assembly, def);
+ def.ReadAttributes ();
+ }
+
+ return def;
+ }
+
+ public void ImportTypeBase (MetaType type)
+ {
+ TypeSpec spec = import_cache[type];
+ if (spec != null)
+ ImportTypeBase (spec, type);
+ }
+
+ void ImportTypeBase (TypeSpec spec, MetaType type)
+ {
+ if (spec.Kind == MemberKind.Interface)
spec.BaseType = TypeManager.object_type;
- else if (type.BaseType != null)
- spec.BaseType = CreateType (type.BaseType);
+ else if (type.BaseType != null) {
+ TypeSpec base_type;
+ if (type.BaseType.IsGenericType)
+ base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true);
+ else
+ base_type = CreateType (type.BaseType);
+
+ spec.BaseType = base_type;
+ }
var ifaces = type.GetInterfaces ();
if (ifaces.Length > 0) {
- foreach (Type iface in ifaces) {
- spec.AddInterface (Import.CreateType (iface));
+ foreach (var iface in ifaces) {
+ spec.AddInterface (CreateType (iface));
}
}
-
- return spec;
}
- static TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType)
+ TypeParameterSpec CreateTypeParameter (MetaType type, TypeSpec declaringType)
{
Variance variance;
switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
}
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
import_cache.Add (type, spec);
var constraints = type.GetGenericParameterConstraints ();
+ List<TypeSpec> tparams = null;
foreach (var ct in constraints) {
- // TODO MemberCache: What to do ??
if (ct.IsGenericParameter) {
+ if (tparams == null)
+ tparams = new List<TypeSpec> ();
+
+ tparams.Add (CreateType (ct));
continue;
}
if (ct.IsClass) {
- if (ct == typeof (ValueType)) {
- spec.BaseType = TypeManager.value_type;
- } else {
- spec.BaseType = CreateType (ct);
- }
-
+ spec.BaseType = CreateType (ct);
continue;
}
if (spec.BaseType == null)
spec.BaseType = TypeManager.object_type;
+ if (tparams != null)
+ spec.TypeArguments = tparams.ToArray ();
+
return spec;
}
- public static TypeSpec ImportType (Type type)
+ //
+ // 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<CustomAttributeData> attributesData, string attrName, string attrNamespace)
+ {
+ if (attributesData.Count == 0)
+ return false;
+
+ string ns, name;
+ foreach (var attr in attributesData) {
+ GetCustomAttributeTypeName (attr, out ns, out name);
+ if (name == attrName && ns == attrNamespace)
+ return true;
+ }
+
+ return false;
+ }
+
+ protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool hasExtensionTypes)
+ {
+ Namespace ns = targetNamespace;
+ string prev_namespace = null;
+ foreach (var t in types) {
+ if (t == null)
+ continue;
+
+ // Be careful not to trigger full parent type loading
+ if (t.MemberType == MemberTypes.NestedType)
+ continue;
+
+ if (t.Name[0] == '<')
+ continue;
+
+ var it = CreateType (t, null, new DynamicTypeReader (t), true);
+ if (it == null)
+ continue;
+
+ if (prev_namespace != t.Namespace) {
+ ns = t.Namespace == null ? targetNamespace : targetNamespace.GetNamespace (t.Namespace, true);
+ prev_namespace = t.Namespace;
+ }
+
+ ns.AddType (it);
+
+ if (it.IsStatic && hasExtensionTypes &&
+ HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) {
+ it.SetExtensionMethodContainer ();
+ }
+ }
+ }
+
+ static Constant ImportParameterConstant (object value)
+ {
+ //
+ // 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));
+ }
+
+ TypeSpec ImportType (MetaType type, DynamicTypeReader dtype)
{
if (type.HasElementType) {
var element = type.GetElementType ();
- var spec = ImportType (element);
+ ++dtype.Position;
+ var spec = ImportType (element, dtype);
if (type.IsArray)
return ArrayContainer.MakeType (spec, type.GetArrayRank ());
throw new NotImplementedException ("Unknown element type " + type.ToString ());
}
- TypeSpec dtype;
- if (type.IsNested)
- dtype = ImportType (type.DeclaringType);
- else
- dtype = null;
-
- return CreateType (type, dtype);
+ return CreateType (type, dtype, true);
}
//
// as IsInitOnly ('readonly' in C# parlance). We get its value from the
// DecimalConstantAttribute metadata.
//
- static Constant ReadDecimalConstant (FieldInfo fi)
+ Constant ReadDecimalConstant (IList<CustomAttributeData> 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)
public string[] Conditionals;
public string DefaultIndexerName;
public bool IsNotCLSCompliant;
-
- public static AttributesBag Read (MemberInfo mi)
+ public TypeSpec CoClass;
+
+ public static AttributesBag Read (MemberInfo mi, MetadataImporter importer)
{
AttributesBag bag = null;
List<string> conditionals = null;
// It should not throw any loading exception
IList<CustomAttributeData> 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 ();
continue;
}
- if (type == typeof (ConditionalAttribute)) {
+ if (name == "ConditionalAttribute") {
+ if (ns != "System.Diagnostics")
+ continue;
+
if (bag == null)
bag = new AttributesBag ();
continue;
}
- if (type == typeof (CLSCompliantAttribute)) {
+ if (name == "CLSCompliantAttribute") {
+ if (ns != "System")
+ continue;
+
if (bag == null)
bag = new AttributesBag ();
}
// Type only attributes
- if (type == typeof (DefaultMemberAttribute)) {
- if (bag == null)
- bag = new AttributesBag ();
+ if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) {
+ if (name == "DefaultMemberAttribute") {
+ if (ns != "System.Reflection")
+ continue;
- bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value;
- continue;
- }
+ if (bag == null)
+ bag = new AttributesBag ();
- if (type == typeof (AttributeUsageAttribute)) {
- if (bag == null)
- bag = new AttributesBag ();
+ bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value;
+ continue;
+ }
- bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value);
- foreach (var named in a.NamedArguments) {
- if (named.MemberInfo.Name == "AllowMultiple")
- bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value;
- else if (named.MemberInfo.Name == "Inherited")
- bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value;
+ if (name == "AttributeUsageAttribute") {
+ if (ns != "System")
+ continue;
+
+ if (bag == null)
+ bag = new AttributesBag ();
+
+ bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value);
+ foreach (var named in a.NamedArguments) {
+ if (named.MemberInfo.Name == "AllowMultiple")
+ bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value;
+ else if (named.MemberInfo.Name == "Inherited")
+ bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value;
+ }
+ 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;
}
- continue;
}
}
if (conditionals != null)
bag.Conditionals = conditionals.ToArray ();
-
+
return bag;
}
}
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
- public Assembly Assembly {
- get {
- return provider.Module.Assembly;
- }
- }
-
public bool IsImported {
get {
return true;
protected void ReadAttributes ()
{
- cattrs = AttributesBag.Read (provider);
+ cattrs = AttributesBag.Read (provider, importer);
}
public void SetIsAssigned ()
}
}
+ public class ImportedModuleDefinition
+ {
+ readonly Module module;
+ bool cls_compliant;
+ readonly MetadataImporter importer;
+
+ public ImportedModuleDefinition (Module module, MetadataImporter importer)
+ {
+ this.module = module;
+ this.importer = importer;
+ }
+
+ #region Properties
+
+ public bool IsCLSCompliant {
+ get {
+ return cls_compliant;
+ }
+ }
+
+ public string Name {
+ get {
+ return module.Name;
+ }
+ }
+
+ #endregion
+
+ public void ReadAttributes ()
+ {
+ IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (module);
+
+ string ns, name;
+ foreach (var a in attrs) {
+ importer.GetCustomAttributeTypeName (a, out ns, out name);
+ if (name == "CLSCompliantAttribute") {
+ if (ns != "System")
+ continue;
+
+ cls_compliant = (bool) a.ConstructorArguments[0].Value;
+ continue;
+ }
+ }
+ }
+
+ //
+ // Reads assembly attributes which where attached to a special type because
+ // module does have assembly manifest
+ //
+ public List<Attribute> ReadAssemblyAttributes ()
+ {
+ var t = module.GetType (AssemblyAttributesPlaceholder.GetGeneratedName (Name));
+ if (t == null)
+ return null;
+
+ var field = t.GetField (AssemblyAttributesPlaceholder.AssemblyFieldName, BindingFlags.NonPublic | BindingFlags.Static);
+ if (field == null)
+ return null;
+
+ // TODO: implement, the idea is to fabricate specil Attribute class and
+ // add it to OptAttributes before resolving the source code attributes
+ // Need to build module location as well for correct error reporting
+
+ //var assembly_attributes = CustomAttributeData.GetCustomAttributes (field);
+ //var attrs = new List<Attribute> (assembly_attributes.Count);
+ //foreach (var a in assembly_attributes)
+ //{
+ // var type = metaImporter.ImportType (a.Constructor.DeclaringType);
+ // var ctor = metaImporter.CreateMethod (a.Constructor, type);
+
+ // foreach (var carg in a.ConstructorArguments) {
+ // carg.Value
+ // }
+
+ // attrs.Add (new Attribute ("assembly", ctor, null, Location.Null, true));
+ //}
+
+ return null;
+ }
+ }
+
+ public class ImportedAssemblyDefinition : IAssemblyDefinition
+ {
+ readonly Assembly assembly;
+ readonly AssemblyName aname;
+ readonly MetadataImporter importer;
+ bool cls_compliant;
+ bool contains_extension_methods;
+
+ List<AssemblyName> internals_visible_to;
+ Dictionary<IAssemblyDefinition, AssemblyName> internals_visible_to_cache;
+
+ public ImportedAssemblyDefinition (Assembly assembly, MetadataImporter importer)
+ {
+ this.assembly = assembly;
+ this.aname = assembly.GetName ();
+ this.importer = importer;
+ }
+
+ #region Properties
+
+ public Assembly Assembly {
+ get {
+ return assembly;
+ }
+ }
+
+ public string FullName {
+ get {
+ return aname.FullName;
+ }
+ }
+
+ public bool HasExtensionMethod {
+ get {
+ return contains_extension_methods;
+ }
+ }
+
+ public bool HasStrongName {
+ get {
+ return aname.GetPublicKey ().Length != 0;
+ }
+ }
+
+ public bool IsCLSCompliant {
+ get {
+ return cls_compliant;
+ }
+ }
+
+ public string Location {
+ get {
+ return assembly.Location;
+ }
+ }
+
+ public string Name {
+ get {
+ return aname.Name;
+ }
+ }
+
+ #endregion
+
+ public byte[] GetPublicKeyToken ()
+ {
+ return aname.GetPublicKeyToken ();
+ }
+
+ public AssemblyName GetAssemblyVisibleToName (IAssemblyDefinition assembly)
+ {
+ return internals_visible_to_cache [assembly];
+ }
+
+ public bool IsFriendAssemblyTo (IAssemblyDefinition assembly)
+ {
+ if (internals_visible_to == null)
+ return false;
+
+ AssemblyName is_visible = null;
+ if (internals_visible_to_cache == null) {
+ internals_visible_to_cache = new Dictionary<IAssemblyDefinition, AssemblyName> ();
+ } else {
+ if (internals_visible_to_cache.TryGetValue (assembly, out is_visible))
+ return is_visible != null;
+ }
+
+ var token = assembly.GetPublicKeyToken ();
+ if (token != null && token.Length == 0)
+ token = null;
+
+ foreach (var internals in internals_visible_to) {
+ if (internals.Name != assembly.Name)
+ continue;
+
+ if (token == null && assembly is AssemblyDefinition) {
+ is_visible = internals;
+ break;
+ }
+
+ if (!ArrayComparer.IsEqual (token, internals.GetPublicKeyToken ()))
+ continue;
+
+ is_visible = internals;
+ break;
+ }
+
+ internals_visible_to_cache.Add (assembly, is_visible);
+ return is_visible != null;
+ }
+
+ public void ReadAttributes ()
+ {
+ IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (assembly);
+
+ string ns, name;
+ foreach (var a in attrs) {
+ importer.GetCustomAttributeTypeName (a, out ns, out name);
+
+ if (name == "CLSCompliantAttribute") {
+ if (ns == "System")
+ cls_compliant = (bool) a.ConstructorArguments[0].Value;
+ continue;
+ }
+
+ if (name == "InternalsVisibleToAttribute") {
+ if (ns != MetadataImporter.CompilerServicesNamespace)
+ continue;
+
+ string s = a.ConstructorArguments[0].Value as string;
+ if (s == null)
+ continue;
+
+ var an = new AssemblyName (s);
+ if (internals_visible_to == null)
+ internals_visible_to = new List<AssemblyName> ();
+
+ internals_visible_to.Add (an);
+ continue;
+ }
+
+ if (name == "ExtensionAttribute") {
+ if (ns == MetadataImporter.CompilerServicesNamespace)
+ contains_extension_methods = true;
+
+ continue;
+ }
+ }
+ }
+
+ public override string ToString ()
+ {
+ return FullName;
+ }
+ }
+
class ImportedMethodDefinition : ImportedMemberDefinition, IParametersMember
{
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;
+ }
+
+ #region Properties
+
+ public AParametersCollection Parameters {
+ get {
+ return parameters;
+ }
+ }
+
+ public TypeSpec MemberType {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ #endregion
+ }
+
+ class ImportedIndexerDefinition : ImportedMemberDefinition, IParametersMember
+ {
+ readonly AParametersCollection parameters;
+
+ public ImportedIndexerDefinition (PropertyInfo provider, AParametersCollection parameters, MetadataImporter importer)
+ : base (provider, importer)
{
this.parameters = parameters;
}
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;
}
TypeParameterSpec[] tparams;
string name;
- public ImportedTypeDefinition (Type type)
- : base (type)
+ public ImportedTypeDefinition (MetaType type, MetadataImporter importer)
+ : base (type, importer)
{
}
#region Properties
+ public IAssemblyDefinition DeclaringAssembly {
+ get {
+ return importer.GetAssemblyDefinition (provider.Module.Assembly);
+ }
+ }
+
public override string Name {
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;
public string Namespace {
get {
- return ((Type) provider).Namespace;
+ return ((MetaType) provider).Namespace;
}
}
public TypeSpec GetAttributeCoClass ()
{
- // TODO: Use ReadAttributes
- var attr = provider.GetCustomAttributes (typeof (CoClassAttribute), false);
- if (attr.Length < 1)
- return null;
+ if (cattrs == null)
+ ReadAttributes ();
- return Import.CreateType (((CoClassAttribute) attr[0]).CoClass);
+ return cattrs.CoClass;
}
public string GetAttributeDefaultMember ()
return cattrs.AttributeUsage;
}
- public MemberCache LoadMembers (TypeSpec declaringType)
+ 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 loading_type = (Type) provider;
+ var a = importer.GetAssemblyDefinition (provider.Module.Assembly);
+ return a == assembly || a.IsFriendAssemblyTo (assembly);
+ }
+
+ public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
+ {
+ //
+ // Not interested in members of nested private types unless the importer needs them
+ //
+ if (declaringType.IsPrivate && importer.IgnorePrivateMembers) {
+ cache = MemberCache.Empty;
+ return;
+ }
+
+ var loading_type = (MetaType) provider;
const BindingFlags all_members = BindingFlags.DeclaredOnly |
BindingFlags.Static | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic;
MethodAttributes.Final;
Dictionary<MethodBase, MethodSpec> possible_accessors = null;
+ List<EventSpec> imported_events = null;
+ EventSpec event_spec;
MemberSpec imported;
MethodInfo m;
-
- //
- // This requires methods to be returned first which seems to work for both Mono and .NET
- //
MemberInfo[] all;
try {
all = loading_type.GetMembers (all_members);
} catch (Exception e) {
throw new InternalErrorException (e, "Could not import type `{0}' from `{1}'",
- declaringType.GetSignatureForError (), declaringType.Assembly.Location);
+ declaringType.GetSignatureForError (), declaringType.MemberDefinition.DeclaringAssembly.FullName);
}
- var cache = new MemberCache (all.Length);
- foreach (var member in all) {
- switch (member.MemberType) {
- case MemberTypes.Constructor:
- case MemberTypes.Method:
- MethodBase mb = (MethodBase) member;
+ if (cache == null) {
+ cache = new MemberCache (all.Length);
- // Ignore explicitly implemented members
- if ((mb.Attributes & explicit_impl) == explicit_impl && (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
+ //
+ // Do the types first as they can be referenced by the members before
+ // they are found or inflated
+ //
+ foreach (var member in all) {
+ if (member.MemberType != MemberTypes.NestedType)
continue;
- // Ignore compiler generated methods
- if (mb.IsPrivate && mb.IsDefined (typeof (CompilerGeneratedAttribute), false))
+ var t = (MetaType) member;
+
+ // Ignore compiler generated types, mostly lambda containers
+ if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate)
continue;
- imported = Import.CreateMethod (mb, declaringType);
- if (imported.Kind == MemberKind.Method && !imported.IsGeneric) {
- if (possible_accessors == null)
- possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
+ imported = importer.CreateNestedType (t, declaringType);
+ cache.AddMember (imported);
+ }
- // There are no metadata rules for accessors, we have to consider any method as possible candidate
- possible_accessors.Add (mb, (MethodSpec) imported);
- }
+ foreach (var member in all) {
+ if (member.MemberType != MemberTypes.NestedType)
+ continue;
- break;
- case MemberTypes.Property:
- if (possible_accessors == null)
+ var t = (MetaType) member;
+
+ if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate)
continue;
- var p = (PropertyInfo) member;
- //
- // Links possible accessors with property
- //
- MethodSpec get, set;
- m = p.GetGetMethod (true);
- if (m == null || !possible_accessors.TryGetValue (m, out get))
- get = null;
+ importer.ImportTypeBase (t);
+ }
+ }
- m = p.GetSetMethod (true);
- if (m == null || !possible_accessors.TryGetValue (m, out set))
- set = null;
+ if (!onlyTypes) {
+ //
+ // The logic here requires methods to be returned first which seems to work for both Mono and .NET
+ //
+ foreach (var member in all) {
+ switch (member.MemberType) {
+ case MemberTypes.Constructor:
+ case MemberTypes.Method:
+ MethodBase mb = (MethodBase) member;
+ var attrs = mb.Attributes;
+
+ if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
+ if (importer.IgnorePrivateMembers)
+ continue;
+
+ // Ignore explicitly implemented members
+ if ((attrs & explicit_impl) == explicit_impl)
+ continue;
+
+ // Ignore compiler generated methods
+ if (importer.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", MetadataImporter.CompilerServicesNamespace))
+ continue;
+ }
- // No accessors registered (e.g. explicit implementation)
- if (get == null && set == null)
- continue;
+ imported = importer.CreateMethod (mb, declaringType);
+ if (imported.Kind == MemberKind.Method && !imported.IsGeneric) {
+ if (possible_accessors == null)
+ possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
- imported = Import.CreateProperty (p, declaringType, get, set);
- if (imported == null)
- continue;
+ // There are no metadata rules for accessors, we have to consider any method as possible candidate
+ possible_accessors.Add (mb, (MethodSpec) imported);
+ }
- break;
- case MemberTypes.Event:
- if (possible_accessors == null)
- continue;
+ break;
+ case MemberTypes.Property:
+ if (possible_accessors == null)
+ continue;
- var e = (EventInfo) member;
- //
- // Links accessors with event
- //
- MethodSpec add, remove;
- m = e.GetAddMethod (true);
- if (m == null || !possible_accessors.TryGetValue (m, out add))
- add = null;
+ var p = (PropertyInfo) member;
+ //
+ // Links possible accessors with property
+ //
+ MethodSpec get, set;
+ m = p.GetGetMethod (true);
+ if (m == null || !possible_accessors.TryGetValue (m, out get))
+ get = null;
- m = e.GetRemoveMethod (true);
- if (m == null || !possible_accessors.TryGetValue (m, out remove))
- remove = null;
+ m = p.GetSetMethod (true);
+ if (m == null || !possible_accessors.TryGetValue (m, out set))
+ set = null;
- // Both accessors are required
- if (add == null || remove == null)
- continue;
+ // No accessors registered (e.g. explicit implementation)
+ if (get == null && set == null)
+ continue;
- imported = Import.CreateEvent (e, declaringType, add, remove);
- break;
- case MemberTypes.Field:
- var fi = (FieldInfo) member;
+ imported = importer.CreateProperty (p, declaringType, get, set);
+ if (imported == null)
+ continue;
- // Ignore compiler generated fields
- if (fi.IsPrivate && fi.IsDefined (typeof (CompilerGeneratedAttribute), false))
- continue;
+ break;
+ case MemberTypes.Event:
+ if (possible_accessors == null)
+ continue;
- imported = Import.CreateField (fi, declaringType);
- if (imported == null)
- continue;
+ var e = (EventInfo) member;
+ //
+ // Links accessors with event
+ //
+ MethodSpec add, remove;
+ m = e.GetAddMethod (true);
+ if (m == null || !possible_accessors.TryGetValue (m, out add))
+ add = null;
- break;
- case MemberTypes.NestedType:
- Type t = (Type) member;
+ m = e.GetRemoveMethod (true);
+ if (m == null || !possible_accessors.TryGetValue (m, out remove))
+ remove = null;
- // Ignore compiler generated types, mostly lambda containers
- if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false))
+ // Both accessors are required
+ if (add == null || remove == null)
+ continue;
+
+ event_spec = importer.CreateEvent (e, declaringType, add, remove);
+ if (!importer.IgnorePrivateMembers) {
+ if (imported_events == null)
+ imported_events = new List<EventSpec> ();
+
+ imported_events.Add (event_spec);
+ }
+
+ imported = event_spec;
+ break;
+ case MemberTypes.Field:
+ var fi = (FieldInfo) member;
+
+ imported = importer.CreateField (fi, declaringType);
+ if (imported == null)
+ continue;
+
+ //
+ // For dynamic binder event has to be fully restored to allow operations
+ // within the type container to work correctly
+ //
+ if (imported_events != null) {
+ // The backing event field should be private but it may not
+ int index = imported_events.FindIndex (l => l.Name == fi.Name);
+ if (index >= 0) {
+ event_spec = imported_events[index];
+ event_spec.BackingField = (FieldSpec) imported;
+ imported_events.RemoveAt (index);
+ continue;
+ }
+ }
+
+ break;
+ case MemberTypes.NestedType:
+ // Already in the cache from the first pass
continue;
+ default:
+ throw new NotImplementedException (member.ToString ());
+ }
- imported = Import.CreateType (t, declaringType);
- break;
- default:
- throw new NotImplementedException (member.ToString ());
+ cache.AddMember (imported);
}
-
- cache.AddMember (imported);
}
if (declaringType.IsInterface && declaringType.Interfaces != null) {
cache.AddInterface (iface);
}
}
-
- return cache;
}
}
class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition
{
- public ImportedTypeParameterDefinition (Type type)
- : base (type)
+ public ImportedTypeParameterDefinition (MetaType type, MetadataImporter importer)
+ : base (type, importer)
{
}
#region Properties
+ public IAssemblyDefinition DeclaringAssembly {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
public string Namespace {
get {
return null;
throw new NotSupportedException ();
}
- public MemberCache LoadMembers (TypeSpec declaringType)
+ bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
{
throw new NotImplementedException ();
}