//
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
-// Copyright 2009, 2010 Novell, Inc
+// Copyright 2009-2011 Novell, Inc
+// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
//
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;
+using IKVM.Reflection.Emit;
+#else
+using MetaType = System.Type;
+using System.Reflection;
+using System.Reflection.Emit;
+#endif
namespace Mono.CSharp
{
- public class ReflectionMetaImporter
+ public abstract class MetadataImporter
{
- Dictionary<Type, TypeSpec> import_cache;
- Dictionary<Type, PredefinedTypeSpec> type_2_predefined;
- Dictionary<Assembly, ImportedAssemblyDefinition> 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 (MetadataImporter importer)
+ {
+ if (provider != null)
+ ReadAttribute (importer);
+
+ return flags != null && Position < flags.Length && flags[Position];
+ }
+
+ //
+ // Returns true when DynamicAttribute exists
+ //
+ public bool HasDynamicAttribute (MetadataImporter importer)
+ {
+ if (provider != null)
+ ReadAttribute (importer);
+
+ return flags != null;
+ }
+
+ void ReadAttribute (MetadataImporter importer)
+ {
+ 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 dt = ca.Constructor.DeclaringType;
+ if (dt.Name != "DynamicAttribute" && dt.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<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, TypeSpec> compiled_types;
+ protected readonly Dictionary<Assembly, IAssemblyDefinition> assembly_2_definition;
+ readonly ModuleContainer module;
public static readonly string CompilerServicesNamespace = "System.Runtime.CompilerServices";
- public ReflectionMetaImporter ()
+ protected MetadataImporter (ModuleContainer module)
{
- import_cache = new Dictionary<Type, TypeSpec> (1024, ReferenceEquality<Type>.Default);
- assembly_2_definition = new Dictionary<Assembly, ImportedAssemblyDefinition> (ReferenceEquality<Assembly>.Default);
+ this.module = module;
+
+ import_cache = new Dictionary<MetaType, TypeSpec> (1024, ReferenceEquality<MetaType>.Default);
+ compiled_types = new Dictionary<MetaType, TypeSpec> (40, ReferenceEquality<MetaType>.Default);
+ assembly_2_definition = new Dictionary<Assembly, IAssemblyDefinition> (ReferenceEquality<Assembly>.Default);
IgnorePrivateMembers = true;
}
#region Properties
- public ICollection<ImportedAssemblyDefinition> Assemblies {
+ public ICollection<IAssemblyDefinition> Assemblies {
get {
return assembly_2_definition.Values;
}
#endregion
- public void Initialize ()
- {
- // 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 abstract void AddCompiledType (TypeBuilder builder, TypeSpec spec);
+ protected abstract MemberKind DetermineKindFromBaseType (MetaType baseType);
+ protected abstract bool HasVolatileModifier (MetaType[] modifiers);
public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
{
break;
default:
// Ignore private fields (even for error reporting) to not require extra dependencies
- if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
+ if ((IgnorePrivateMembers && !declaringType.IsStruct) ||
+ HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
return null;
mod = Modifiers.PRIVATE;
break;
}
- var definition = new ImportedMemberDefinition (fi);
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
declaringType.GetSignatureForError (), fi.Name, declaringType.MemberDefinition.DeclaringAssembly);
}
+ var definition = new ImportedMemberDefinition (fi, field_type, this);
+
if ((fa & FieldAttributes.Literal) != 0) {
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) {
+ if (field_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi));
if (dc != null)
return new ConstSpec (declaringType, definition, field_type, fi, mod, dc);
mod |= Modifiers.READONLY;
} else {
- if (TypeManager.isvolatile_type != null) {
- var reqs = fi.GetRequiredCustomModifiers ();
- if (reqs.Length > 0) {
- foreach (var t in reqs) {
- if (t == TypeManager.isvolatile_type.GetMetaInfo ()) {
- 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 (declaringType.IsStruct && field_type.IsStruct && field_type.IsNested &&
HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "FixedBufferAttribute", CompilerServicesNamespace)) {
- // TODO: Sanity check on field_type (only few type are allowed)
+ // TODO: Sanity check on field_type (only few types are allowed)
var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType);
return new FixedFieldSpec (declaringType, definition, fi, element_field, mod);
}
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 event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei));
+ var definition = new ImportedMemberDefinition (ei, event_type, this);
+ return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove);
}
- TypeParameterSpec[] CreateGenericParameters (Type type, TypeSpec declaringType)
+ TypeParameterSpec[] CreateGenericParameters (MetaType type, TypeSpec declaringType)
{
- Type[] tparams = type.GetGenericArguments ();
+ var tparams = type.GetGenericArguments ();
int parent_owned_count;
if (type.IsNested) {
return CreateGenericParameters (parent_owned_count, tparams);
}
- TypeParameterSpec[] CreateGenericParameters (int first, Type[] tparams)
+ TypeParameterSpec[] CreateGenericParameters (int first, MetaType[] tparams)
{
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, null, 0, false);
+ tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false);
}
return tspec;
}
- TypeSpec[] CreateGenericArguments (int first, Type[] tparams, ICustomAttributeProvider ca, int dynamicCursor)
+ 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];
TypeSpec spec;
if (type.HasElementType) {
var element = type.GetElementType ();
- spec = ImportType (element, ca, dynamicCursor + 1);
+ ++dtype.Position;
+ spec = ImportType (element, dtype);
if (!type.IsArray) {
throw new NotImplementedException ("Unknown element type " + type.ToString ());
}
- spec = ArrayContainer.MakeType (spec, type.GetArrayRank ());
+ spec = ArrayContainer.MakeType (module, spec, type.GetArrayRank ());
} else {
- spec = CreateType (type, ca, dynamicCursor, true);
+ spec = CreateType (type, dtype, true);
//
// We treat nested generic types as inflated internally where
//
// TODO: Is full logic from CreateType needed here as well?
//
- if (type.IsGenericTypeDefinition) {
- var targs = CreateGenericArguments (0, type.GetGenericArguments (), ca, dynamicCursor + 1);
- spec = spec.MakeGenericType (targs);
+ if (!IsMissingType (type) && type.IsGenericTypeDefinition) {
+ var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype);
+ spec = spec.MakeGenericType (module, targs);
}
}
- ++dynamicCursor;
+ ++dtype.Position;
tspec[index] = spec;
}
{
Modifiers mod = ReadMethodModifiers (mb, declaringType);
TypeParameterSpec[] tparams;
- ImportedMethodDefinition definition;
var parameters = CreateParameters (declaringType, mb.GetParameters (), mb);
throw new NotSupportedException ("assert");
tparams = CreateGenericParameters (0, mb.GetGenericArguments ());
- definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams);
} else {
- definition = new ImportedMethodDefinition (mb, parameters);
tparams = null;
}
TypeSpec returnType;
if (mb.MemberType == MemberTypes.Constructor) {
kind = MemberKind.Constructor;
- returnType = TypeManager.void_type;
+ returnType = module.Compiler.BuiltinTypes.Void;
} else {
//
// Detect operators and destructors
}
} else if (parameters.IsEmpty && name == Destructor.MetadataName) {
kind = MemberKind.Destructor;
- if (declaringType == TypeManager.object_type) {
+ if (declaringType.BuiltinType == BuiltinTypeSpec.Type.Object) {
mod &= ~Modifiers.OVERRIDE;
mod |= Modifiers.VIRTUAL;
}
}
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
// but further validation is needed
- if ((mod & Modifiers.OVERRIDE) != 0 && kind == MemberKind.Method && declaringType.BaseType != null) {
- var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
- var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
+ if ((mod & Modifiers.OVERRIDE) != 0) {
+ bool is_real_override = false;
+ if (kind == MemberKind.Method && declaringType.BaseType != null) {
+ var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
+ var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
- //
- // For imported class method do additional validation to be sure that metadata
- // override flag was correct
- //
- // Difference between protected internal and protected is ok
- //
- const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
- if (candidate == null || (candidate.Modifiers & conflict_mask) != (mod & conflict_mask) || candidate.IsStatic) {
+ //
+ // For imported class method do additional validation to be sure that metadata
+ // override flag was correct
+ //
+ // Difference between protected internal and protected is ok
+ //
+ const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
+ if (candidate != null && (candidate.Modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) {
+ is_real_override = true;
+ }
+ }
+
+ if (!is_real_override) {
mod &= ~Modifiers.OVERRIDE;
+ if ((mod & Modifiers.SEALED) != 0)
+ mod &= ~Modifiers.SEALED;
+ else
+ mod |= Modifiers.VIRTUAL;
}
}
}
+ IMemberDefinition definition;
+ if (tparams != null) {
+ var gmd = new ImportedGenericMethodDefinition ((MethodInfo) mb, returnType, parameters, tparams, this);
+ foreach (var tp in gmd.TypeParameters) {
+ ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ());
+ }
+
+ definition = gmd;
+ } else {
+ definition = new ImportedParameterMemberDefinition (mb, returnType, parameters, this);
+ }
+
MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod);
if (tparams != null)
ms.IsGeneric = true;
// 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 &&
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) {
if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
if (!is_params && p.IsOptional) {
object value = p.RawDefaultValue;
var ptype = types[i];
- if (((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter)) {
- //
- // Use value type as int constant can be used for object parameter type
- //
- 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 || TypeSpec.IsReferenceType (ptype))) {
+ if (value == null) {
+ default_value = Constant.CreateConstant (ptype, null, Location.Null);
+ } else {
+ default_value = ImportParameterConstant (value);
+
+ if (ptype.IsEnum) {
+ default_value = new EnumConstant ((Constant) default_value, ptype);
+ }
+ }
} else if (value == Missing.Value) {
default_value = EmptyExpression.MissingValue;
- } else {
- if (ptype == TypeManager.decimal_type)
- default_value = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (p));
-
- if (default_value == null)
- default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null);
+ } else if (value == null) {
+ default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null);
+ } else if (ptype.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
+ default_value = ImportParameterConstant (value);
}
}
}
new ParametersImported (par, types, is_params);
}
-
//
// Returns null when the property is not valid C# property
//
bool is_valid_property = true;
if (set != null) {
- if (set.ReturnType != TypeManager.void_type)
+ if (set.ReturnType.Kind != MemberKind.Void)
is_valid_property = false;
var set_param_count = set.Parameters.Count - 1;
}
if (is_valid_property)
- spec = new IndexerSpec (declaringType, new ImportedIndexerDefinition (pi, param), type, param, pi, mod);
+ spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, 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, type, this), type, pi, mod);
if (!is_valid_property) {
- spec.IsNotRealProperty = true;
+ spec.IsNotCSharpCompatible = true;
return spec;
}
return spec;
}
- public TypeSpec CreateType (Type type)
+ public TypeSpec CreateType (MetaType type)
{
- return CreateType (type, null, 0, true);
+ return CreateType (type, new DynamicTypeReader (), true);
}
- TypeSpec CreateType (Type type, ICustomAttributeProvider ca, int dynamicCursor, bool canImportBaseType)
+ 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, 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 (spec == TypeManager.object_type) {
- if (IsDynamicType (ca, dynamicCursor))
- return InternalType.Dynamic;
+ if (spec.BuiltinType == BuiltinTypeSpec.Type.Object) {
+ if (dtype.IsDynamicObject (this))
+ return module.Compiler.BuiltinTypes.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 (this))
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 resolve the type process again in that case
+ // Do type resolve process again in that case
+
+ // TODO: Handle cases where they still unify
+ }
+
+ if (IsMissingType (type)) {
+ spec = new TypeSpec (MemberKind.MissingType, declaringType, new ImportedTypeDefinition (type, this), type, Modifiers.PUBLIC);
+ spec.MemberCache = MemberCache.Empty;
+ import_cache.Add (type, spec);
+ return spec;
}
if (type.IsGenericType && !type.IsGenericTypeDefinition) {
var type_def = type.GetGenericTypeDefinition ();
- var targs = CreateGenericArguments (0, type.GetGenericArguments (), ca, dynamicCursor + 1);
+
+ // Generic type definition can also be forwarded
+ if (compiled_types.TryGetValue (type_def, out spec))
+ return spec;
+
+ var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype);
if (declaringType == null) {
// Simple case, no nesting
- spec = CreateType (type_def, null, null, 0, canImportBaseType);
- spec = spec.MakeGenericType (targs);
+ spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
+ spec = spec.MakeGenericType (module, targs);
} else {
//
// Nested type case, converting .NET types like
int targs_pos = 0;
if (declaringType.Arity > 0) {
- spec = declaringType.MakeGenericType (targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ());
+ spec = declaringType.MakeGenericType (module, targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ());
targs_pos = spec.Arity;
} else {
spec = declaringType;
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 ());
+ spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ());
targs_pos += t.Arity;
}
}
name = name.Substring (0, index);
spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
+ if (spec == null)
+ return null;
+
if (spec.Arity > 0) {
- spec = spec.MakeGenericType (targs.Skip (targs_pos).ToArray ());
+ spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ());
}
}
}
}
- var definition = new ImportedTypeDefinition (this, type);
- PredefinedTypeSpec pt;
+ var definition = new ImportedTypeDefinition (type, this);
+ TypeSpec pt;
if (kind == MemberKind.Enum) {
const BindingFlags underlying_member = BindingFlags.DeclaredOnly |
kind = MemberKind.Class;
} else if (kind == MemberKind.TypeParameter) {
- // Return as type_cache was updated
- return CreateTypeParameter (type, declaringType);
+ spec = CreateTypeParameter (type, declaringType);
} else if (type.IsGenericTypeDefinition) {
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 (compiled_types.TryGetValue (type, out pt)) {
+ //
+ // Same type was found in inside compiled types. It's
+ // either build-in type or forward referenced typed
+ // which point into just compiled assembly.
+ //
spec = pt;
- pt.SetDefinition (definition, type);
+ BuiltinTypeSpec bts = pt as BuiltinTypeSpec;
+ if (bts != null)
+ bts.SetDefinition (definition, type, mod);
}
if (spec == null)
return spec;
}
- MemberKind DetermineKindFromBaseType (Type baseType)
+ public IAssemblyDefinition GetAssemblyDefinition (Assembly assembly)
{
- if (baseType == typeof (ValueType))
- return MemberKind.Struct;
-
- if (baseType == typeof (System.Enum))
- return MemberKind.Enum;
-
- if (baseType == typeof (MulticastDelegate))
- return MemberKind.Delegate;
-
- return MemberKind.Class;
- }
-
- public ImportedAssemblyDefinition GetAssemblyDefinition (Assembly assembly)
- {
- ImportedAssemblyDefinition def;
- if (!assembly_2_definition.TryGetValue (assembly, out def)) {
+ IAssemblyDefinition found;
+ if (!assembly_2_definition.TryGetValue (assembly, out found)) {
// This can happen in dynamic context only
- def = new ImportedAssemblyDefinition (assembly);
+ var def = new ImportedAssemblyDefinition (assembly);
assembly_2_definition.Add (assembly, def);
def.ReadAttributes ();
+ found = def;
}
- return def;
+ return found;
}
- 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)
- {
- if (spec.Kind == MemberKind.Interface)
- spec.BaseType = TypeManager.object_type;
- else if (type.BaseType != null) {
- if (type.BaseType.IsGenericType)
- spec.BaseType = CreateType (type.BaseType, type, 0, true);
- else
- spec.BaseType = CreateType (type.BaseType);
- }
-
- var ifaces = type.GetInterfaces ();
- if (ifaces.Length > 0) {
- foreach (Type 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) {
}
TypeParameterSpec spec;
- var def = new ImportedTypeParameterDefinition (type);
- if (type.DeclaringMethod != null)
+ var def = new ImportedTypeParameterDefinition (type, this);
+ if (type.DeclaringMethod != null) {
spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type);
- else
+ } else {
spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type);
-
- // Add it now, so any constraint can reference it and get same instance
- import_cache.Add (type, spec);
-
- var constraints = type.GetGenericParameterConstraints ();
- List<TypeSpec> tparams = null;
- foreach (var ct in constraints) {
- if (ct.IsGenericParameter) {
- if (tparams == null)
- tparams = new List<TypeSpec> ();
-
- tparams.Add (CreateType (ct));
- continue;
- }
-
- if (ct.IsClass) {
- spec.BaseType = CreateType (ct);
- continue;
- }
-
- spec.AddInterface (CreateType (ct));
}
- if (spec.BaseType == null)
- spec.BaseType = TypeManager.object_type;
-
- if (tparams != null)
- spec.TypeArguments = tparams.ToArray ();
-
return spec;
}
// 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 static bool HasAttribute (IList<CustomAttributeData> attributesData, string name, string ns)
+ public bool HasAttribute (IList<CustomAttributeData> attributesData, string attrName, string attrNamespace)
{
if (attributesData.Count == 0)
return false;
foreach (var attr in attributesData) {
- var type = attr.Constructor.DeclaringType;
- if (type.Name == name && type.Namespace == ns)
+ var dt = attr.Constructor.DeclaringType;
+ if (dt.Name == attrName && dt.Namespace == attrNamespace)
return true;
}
return false;
}
- public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
+ void ImportTypeBase (TypeSpec spec, MetaType type)
{
- // 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);
+ if (spec.Kind == MemberKind.Interface)
+ spec.BaseType = module.Compiler.BuiltinTypes.Object;
+ else if (type.BaseType != null) {
+ TypeSpec base_type;
+ if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType)
+ base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true);
+ else
+ base_type = CreateType (type.BaseType);
- definition.ReadAttributes ();
+ spec.BaseType = base_type;
}
- //
- // 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;
+ MetaType[] ifaces;
+#if STATIC
+ ifaces = type.__GetDeclaredInterfaces ();
+ if (ifaces.Length != 0) {
+ foreach (var iface in ifaces) {
+ var it = CreateType (iface);
+ if (it == null)
+ continue;
+
+ spec.AddInterface (it);
+
+ // Unfortunately not all languages expand inherited interfaces
+ var bifaces = it.Interfaces;
+ if (bifaces != null) {
+ foreach (var biface in bifaces) {
+ spec.AddInterface (biface);
+ }
+ }
+ }
}
- ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod);
- }
+ if (spec.BaseType != null) {
+ var bifaces = spec.BaseType.Interfaces;
+ if (bifaces != null) {
+ //
+ // Before adding base class interfaces close defined interfaces
+ // on type parameter
+ //
+ var tp = spec as TypeParameterSpec;
+ if (tp != null && tp.InterfacesDefined == null) {
+ tp.InterfacesDefined = TypeSpec.EmptyTypes;
+ }
- public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
- {
- var module_definition = new ImportedModuleDefinition (module, this);
- module_definition.ReadAttributes ();
+ foreach (var iface in bifaces)
+ spec.AddInterface (iface);
+ }
+ }
+#else
+ ifaces = type.GetInterfaces ();
- Type[] all_types;
- try {
- all_types = module.GetTypes ();
- } catch (ReflectionTypeLoadException e) {
- all_types = e.Types;
+ if (ifaces.Length > 0) {
+ foreach (var iface in ifaces) {
+ spec.AddInterface (CreateType (iface));
+ }
}
+#endif
- ImportTypes (all_types, targetNamespace, false);
+ if (spec.MemberDefinition.TypeParametersCount > 0) {
+ foreach (var tp in spec.MemberDefinition.TypeParameters) {
+ ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ());
+ }
+ }
- return module_definition;
}
- void ImportTypes (Type[] types, Namespace targetNamespace, bool hasExtensionTypes)
+ protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool hasExtensionTypes)
{
Namespace ns = targetNamespace;
string prev_namespace = null;
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;
prev_namespace = t.Namespace;
}
- ns.AddType (it);
+ ns.AddType (module, it);
if (it.IsStatic && hasExtensionTypes &&
HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) {
}
}
- public TypeSpec ImportType (Type type)
+ void ImportTypeParameterTypeConstraints (TypeParameterSpec spec, MetaType type)
{
- return ImportType (type, null, 0);
+ var constraints = type.GetGenericParameterConstraints ();
+ List<TypeSpec> tparams = null;
+ foreach (var ct in constraints) {
+ if (ct.IsGenericParameter) {
+ if (tparams == null)
+ tparams = new List<TypeSpec> ();
+
+ tparams.Add (CreateType (ct));
+ continue;
+ }
+
+ if (!IsMissingType (ct) && ct.IsClass) {
+ spec.BaseType = CreateType (ct);
+ continue;
+ }
+
+ spec.AddInterface (CreateType (ct));
+ }
+
+ if (spec.BaseType == null)
+ spec.BaseType = module.Compiler.BuiltinTypes.Object;
+
+ if (tparams != null)
+ spec.TypeArguments = tparams.ToArray ();
}
- public TypeSpec ImportType (Type type, ICustomAttributeProvider ca, int dynamicCursor)
+ 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
+ //
+ var types = module.Compiler.BuiltinTypes;
+ switch (System.Type.GetTypeCode (value.GetType ())) {
+ case TypeCode.Boolean:
+ return new BoolConstant (types, (bool) value, Location.Null);
+ case TypeCode.Byte:
+ return new ByteConstant (types, (byte) value, Location.Null);
+ case TypeCode.Char:
+ return new CharConstant (types, (char) value, Location.Null);
+ case TypeCode.Decimal:
+ return new DecimalConstant (types, (decimal) value, Location.Null);
+ case TypeCode.Double:
+ return new DoubleConstant (types, (double) value, Location.Null);
+ case TypeCode.Int16:
+ return new ShortConstant (types, (short) value, Location.Null);
+ case TypeCode.Int32:
+ return new IntConstant (types, (int) value, Location.Null);
+ case TypeCode.Int64:
+ return new LongConstant (types, (long) value, Location.Null);
+ case TypeCode.SByte:
+ return new SByteConstant (types, (sbyte) value, Location.Null);
+ case TypeCode.Single:
+ return new FloatConstant (types, (float) value, Location.Null);
+ case TypeCode.String:
+ return new StringConstant (types, (string) value, Location.Null);
+ case TypeCode.UInt16:
+ return new UShortConstant (types, (ushort) value, Location.Null);
+ case TypeCode.UInt32:
+ return new UIntConstant (types, (uint) value, Location.Null);
+ case TypeCode.UInt64:
+ return new ULongConstant (types, (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, ca, dynamicCursor + 1);
+ ++dtype.Position;
+ var spec = ImportType (element, dtype);
if (type.IsArray)
- return ArrayContainer.MakeType (spec, type.GetArrayRank ());
+ return ArrayContainer.MakeType (module, spec, type.GetArrayRank ());
if (type.IsByRef)
- return ReferenceContainer.MakeType (spec);
+ return ReferenceContainer.MakeType (module, spec);
if (type.IsPointer)
- return PointerContainer.MakeType (spec);
+ return PointerContainer.MakeType (module, spec);
throw new NotImplementedException ("Unknown element type " + type.ToString ());
}
- return CreateType (type, ca, dynamicCursor, true);
+ return CreateType (type, dtype, true);
}
- static bool IsDynamicType (ICustomAttributeProvider ca, int index)
+ static bool IsMissingType (MetaType type)
{
-#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
+#if STATIC
+ return type.__IsMissing;
+#else
return false;
+#endif
}
//
// as IsInitOnly ('readonly' in C# parlance). We get its value from the
// DecimalConstantAttribute metadata.
//
- static Constant ReadDecimalConstant (IList<CustomAttributeData> attrs)
+ Constant ReadDecimalConstant (IList<CustomAttributeData> attrs)
{
if (attrs.Count == 0)
return null;
foreach (var ca in attrs) {
- var type = ca.Constructor.DeclaringType;
- if (type.Name != "DecimalConstantAttribute" || type.Namespace != CompilerServicesNamespace)
+ var dt = ca.Constructor.DeclaringType;
+ if (dt.Name != "DecimalConstantAttribute" || dt.Namespace != CompilerServicesNamespace)
continue;
var value = new decimal (
(byte) ca.ConstructorArguments[1].Value != 0,
(byte) ca.ConstructorArguments[0].Value);
- return new DecimalConstant (value, Location.Null).Resolve (null);
+ return new DecimalConstant (module.Compiler.BuiltinTypes, value, Location.Null);
}
return null;
return mod;
}
+ // It can be sealed and override
if ((ma & MethodAttributes.Final) != 0)
mod |= Modifiers.SEALED;
- // It can be sealed and override
if ((ma & MethodAttributes.Virtual) != 0) {
- if ((ma & MethodAttributes.NewSlot) != 0 || !declaringType.IsClass) {
- // No private virtual or sealed virtual
- if ((mod & (Modifiers.PRIVATE | Modifiers.SEALED)) == 0)
+ // Not every member can be detected based on MethodAttribute, we
+ // set virtual or non-virtual only when we are certain. Further checks
+ // to really find out what `virtual' means for this member are done
+ // later
+ if ((ma & MethodAttributes.NewSlot) != 0) {
+ if ((mod & Modifiers.SEALED) != 0) {
+ mod &= ~Modifiers.SEALED;
+ } else {
mod |= Modifiers.VIRTUAL;
+ }
} else {
mod |= Modifiers.OVERRIDE;
}
}
}
- class ImportedMemberDefinition : IMemberDefinition
+ abstract class ImportedDefinition : IMemberDefinition
{
protected class AttributesBag
{
public ObsoleteAttribute Obsolete;
public string[] Conditionals;
public string DefaultIndexerName;
- public bool IsNotCLSCompliant;
+ public bool? CLSAttributeValue;
public TypeSpec CoClass;
- public static AttributesBag Read (MemberInfo mi, ReflectionMetaImporter typeImporter)
+ public static AttributesBag Read (MemberInfo mi, MetadataImporter importer)
{
AttributesBag bag = null;
List<string> conditionals = null;
IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (mi);
foreach (var a in attrs) {
- var type = a.Constructor.DeclaringType;
- var name = type.Name;
+ var dt = a.Constructor.DeclaringType;
+ string name = dt.Name;
if (name == "ObsoleteAttribute") {
- if (type.Namespace != "System")
+ if (dt.Namespace != "System")
continue;
if (bag == null)
}
if (name == "ConditionalAttribute") {
- if (type.Namespace != "System.Diagnostics")
+ if (dt.Namespace != "System.Diagnostics")
continue;
if (bag == null)
}
if (name == "CLSCompliantAttribute") {
- if (type.Namespace != "System")
+ if (dt.Namespace != "System")
continue;
if (bag == null)
bag = new AttributesBag ();
- bag.IsNotCLSCompliant = !(bool) a.ConstructorArguments[0].Value;
+ bag.CLSAttributeValue = (bool) a.ConstructorArguments[0].Value;
continue;
}
// Type only attributes
if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) {
if (name == "DefaultMemberAttribute") {
- if (type.Namespace != "System.Reflection")
+ if (dt.Namespace != "System.Reflection")
continue;
if (bag == null)
}
if (name == "AttributeUsageAttribute") {
- if (type.Namespace != "System")
+ if (dt.Namespace != "System")
continue;
if (bag == null)
}
// Interface only attribute
- if (typeImporter != null && name == "CoClassAttribute") {
- if (type.Namespace != "System.Runtime.InteropServices")
+ if (name == "CoClassAttribute") {
+ if (dt.Namespace != "System.Runtime.InteropServices")
continue;
if (bag == null)
bag = new AttributesBag ();
- bag.CoClass = typeImporter.ImportType ((Type) a.ConstructorArguments[0].Value);
+ bag.CoClass = importer.ImportType ((MetaType) a.ConstructorArguments[0].Value);
continue;
}
}
protected readonly MemberInfo provider;
protected AttributesBag cattrs;
+ protected readonly MetadataImporter importer;
- public ImportedMemberDefinition (MemberInfo provider)
+ public ImportedDefinition (MemberInfo provider, MetadataImporter importer)
{
this.provider = provider;
+ this.importer = importer;
}
#region Properties
return cattrs.Obsolete;
}
- public bool IsNotCLSCompliant ()
- {
- if (cattrs == null)
- ReadAttributes ();
+ public bool? CLSAttributeValue {
+ get {
+ if (cattrs == null)
+ ReadAttributes ();
- return cattrs.IsNotCLSCompliant;
+ return cattrs.CLSAttributeValue;
+ }
}
- protected virtual void ReadAttributes ()
+ protected void ReadAttributes ()
{
- cattrs = AttributesBag.Read (provider, null);
+ cattrs = AttributesBag.Read (provider, importer);
}
public void SetIsAssigned ()
{
readonly Module module;
bool cls_compliant;
- //ReflectionMetaImporter metaImporter;
- public ImportedModuleDefinition (Module module, ReflectionMetaImporter metaImporter)
+ public ImportedModuleDefinition (Module module)
{
this.module = module;
- //this.metaImporter = metaImporter;
}
#region Properties
public void ReadAttributes ()
{
IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (module);
+
foreach (var a in attrs) {
- var type = a.Constructor.DeclaringType;
- if (type.Name == "CLSCompliantAttribute") {
- if (type.Namespace != "System")
+ var dt = a.Constructor.DeclaringType;
+ if (dt.Name == "CLSCompliantAttribute") {
+ if (dt.Namespace != "System")
continue;
cls_compliant = (bool) a.ConstructorArguments[0].Value;
}
}
+ public bool IsMissing {
+ get {
+#if STATIC
+ return assembly.__IsMissing;
+#else
+ return false;
+#endif
+ }
+ }
+
public bool IsCLSCompliant {
get {
return cls_compliant;
public void ReadAttributes ()
{
+#if STATIC
+ if (assembly.__IsMissing)
+ return;
+#endif
+
IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (assembly);
foreach (var a in attrs) {
- var type = a.Constructor.DeclaringType;
- var name = type.Name;
-
+ var dt = a.Constructor.DeclaringType;
+ var name = dt.Name;
if (name == "CLSCompliantAttribute") {
- if (type.Namespace == "System")
+ if (dt.Namespace == "System") {
cls_compliant = (bool) a.ConstructorArguments[0].Value;
+ }
continue;
}
if (name == "InternalsVisibleToAttribute") {
- if (type.Namespace != ReflectionMetaImporter.CompilerServicesNamespace)
+ if (dt.Namespace != MetadataImporter.CompilerServicesNamespace)
continue;
string s = a.ConstructorArguments[0].Value as string;
}
if (name == "ExtensionAttribute") {
- if (type.Namespace == ReflectionMetaImporter.CompilerServicesNamespace)
+ if (dt.Namespace == MetadataImporter.CompilerServicesNamespace)
contains_extension_methods = true;
continue;
}
}
- class ImportedMethodDefinition : ImportedMemberDefinition, IParametersMember
+ class ImportedMemberDefinition : ImportedDefinition
{
- readonly AParametersCollection parameters;
+ readonly TypeSpec type;
- public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters)
- : base (provider)
+ public ImportedMemberDefinition (MemberInfo member, TypeSpec type, MetadataImporter importer)
+ : base (member, importer)
{
- this.parameters = parameters;
+ this.type = type;
}
#region Properties
- public AParametersCollection Parameters {
- get {
- return parameters;
- }
- }
-
public TypeSpec MemberType {
get {
- throw new NotImplementedException ();
+ return type;
}
}
#endregion
}
- class ImportedIndexerDefinition : ImportedMemberDefinition, IParametersMember
+ class ImportedParameterMemberDefinition : ImportedMemberDefinition, IParametersMember
{
readonly AParametersCollection parameters;
- public ImportedIndexerDefinition (PropertyInfo provider, AParametersCollection parameters)
- : base (provider)
+ public ImportedParameterMemberDefinition (MethodBase provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer)
+ : base (provider, type, importer)
+ {
+ this.parameters = parameters;
+ }
+
+ public ImportedParameterMemberDefinition (PropertyInfo provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer)
+ : base (provider, type, importer)
{
this.parameters = parameters;
}
}
}
- public TypeSpec MemberType {
- get {
- throw new NotImplementedException ();
- }
- }
-
#endregion
}
- class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition
+ class ImportedGenericMethodDefinition : ImportedParameterMemberDefinition, IGenericMethodDefinition
{
- TypeParameterSpec[] tparams;
+ readonly TypeParameterSpec[] tparams;
- public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams)
- : base (provider, parameters)
+ public ImportedGenericMethodDefinition (MethodInfo provider, TypeSpec type, AParametersCollection parameters, TypeParameterSpec[] tparams, MetadataImporter importer)
+ : base (provider, type, parameters, importer)
{
this.tparams = tparams;
}
#endregion
}
- class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition
+ class ImportedTypeDefinition : ImportedDefinition, ITypeDefinition
{
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);
}
}
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;
}
}
#endregion
+ public static void Error_MissingDependency (IMemberContext ctx, List<TypeSpec> types, Location loc)
+ {
+ //
+ // Report details about missing type and most likely cause of the problem.
+ // csc reports 1683, 1684 as warnings but we report them only when used
+ // or referenced from the user core in which case compilation error has to
+ // be reported because compiler cannot continue anyway
+ //
+ foreach (var t in types) {
+ string name = t.GetSignatureForError ();
+
+ if (t.MemberDefinition.DeclaringAssembly == ctx.Module.DeclaringAssembly) {
+ ctx.Module.Compiler.Report.Error (1683, loc,
+ "Reference to type `{0}' claims it is defined in this assembly, but it is not defined in source or any added modules",
+ name);
+ } else if (t.MemberDefinition.DeclaringAssembly.IsMissing) {
+ ctx.Module.Compiler.Report.Error (12, loc,
+ "The type `{0}' is defined in an assembly that is not referenced. Consider adding a reference to assembly `{1}'",
+ name, t.MemberDefinition.DeclaringAssembly.FullName);
+ } else {
+ ctx.Module.Compiler.Report.Error (1684, loc,
+ "Reference to type `{0}' claims it is defined assembly `{1}', but it could not be found",
+ name, t.MemberDefinition.DeclaringAssembly.FullName);
+ }
+ }
+ }
+
public TypeSpec GetAttributeCoClass ()
{
if (cattrs == null)
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);
}
//
// 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;
if (member.MemberType != MemberTypes.NestedType)
continue;
- Type t = (Type) member;
+ var t = (MetaType) member;
// Ignore compiler generated types, mostly lambda containers
- if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate)
+ if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers)
continue;
- imported = meta_import.CreateType (t, declaringType, t, 0, false);
- cache.AddMember (imported);
+ try {
+ imported = importer.CreateNestedType (t, declaringType);
+ } catch (Exception e) {
+ throw new InternalErrorException (e, "Could not import nested type `{0}' from `{1}'",
+ t.FullName, declaringType.MemberDefinition.DeclaringAssembly.FullName);
+ }
+
+ cache.AddMemberImported (imported);
}
foreach (var member in all) {
if (member.MemberType != MemberTypes.NestedType)
continue;
- Type t = (Type) member;
+ var t = (MetaType) member;
- if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate)
+ if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers)
continue;
- meta_import.ImportTypeBase (t);
+ importer.ImportTypeBase (t);
+ }
+ }
+
+ //
+ // Load base interfaces first to minic behaviour of compiled members
+ //
+ if (declaringType.IsInterface && declaringType.Interfaces != null) {
+ foreach (var iface in declaringType.Interfaces) {
+ cache.AddInterface (iface);
}
}
var attrs = mb.Attributes;
if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
- if (meta_import.IgnorePrivateMembers)
+ if (importer.IgnorePrivateMembers)
continue;
// Ignore explicitly implemented members
continue;
// Ignore compiler generated methods
- if (ReflectionMetaImporter.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", ReflectionMetaImporter.CompilerServicesNamespace))
+ 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<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
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;
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<EventSpec> ();
case MemberTypes.Field:
var fi = (FieldInfo) member;
- imported = meta_import.CreateField (fi, declaringType);
+ imported = importer.CreateField (fi, declaringType);
if (imported == null)
continue;
//
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;
+ int i;
+ for (i = 0; i < imported_events.Count; ++i) {
+ var ev = imported_events[i];
+ if (ev.Name == fi.Name) {
+ ev.BackingField = (FieldSpec) imported;
+ imported_events.RemoveAt (i);
+ i = -1;
+ break;
+ }
}
+
+ if (i < 0)
+ continue;
}
break;
throw new NotImplementedException (member.ToString ());
}
- cache.AddMember (imported);
- }
- }
-
- if (declaringType.IsInterface && declaringType.Interfaces != null) {
- foreach (var iface in declaringType.Interfaces) {
- cache.AddInterface (iface);
+ cache.AddMemberImported (imported);
}
}
}
-
- protected override void ReadAttributes ()
- {
- cattrs = AttributesBag.Read (provider, meta_import);
- }
}
- class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition
+ class ImportedTypeParameterDefinition : ImportedDefinition, ITypeDefinition
{
- public ImportedTypeParameterDefinition (Type type)
- : base (type)
+ public ImportedTypeParameterDefinition (MetaType type, MetadataImporter importer)
+ : base (type, importer)
{
}