Add sanity check for imported static fixed buffer
[mono.git] / mcs / mcs / import.cs
1 //
2 // import.cs: System.Reflection conversions
3 //
4 // Authors: Marek Safar (marek.safar@gmail.com)
5 //
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
7 //
8 // Copyright 2009, 2010 Novell, Inc
9 //
10
11 using System;
12 using System.Reflection;
13 using System.Runtime.CompilerServices;
14 using System.Linq;
15 using System.Collections.Generic;
16 using System.Diagnostics;
17 using System.Runtime.InteropServices;
18
19 namespace Mono.CSharp
20 {
21         public class ReflectionMetaImporter
22         {
23                 Dictionary<Type, TypeSpec> import_cache;
24                 Dictionary<Type, PredefinedTypeSpec> type_2_predefined;
25                 Dictionary<Assembly, ImportedAssemblyDefinition> assembly_2_definition;
26
27                 public ReflectionMetaImporter ()
28                 {
29                         import_cache = new Dictionary<Type, TypeSpec> (1024, ReferenceEquality<Type>.Default);
30                         assembly_2_definition = new Dictionary<Assembly, ImportedAssemblyDefinition> (ReferenceEquality<Assembly>.Default);
31                         IgnorePrivateMembers = true;
32                 }
33
34                 #region Properties
35
36                 public ICollection<ImportedAssemblyDefinition> Assemblies {
37                         get {
38                                 return assembly_2_definition.Values;
39                         }
40                 }
41
42                 public bool IgnorePrivateMembers { get; set; }
43
44                 #endregion
45
46                 public void Initialize ()
47                 {
48                         // Setup mapping for predefined types
49                         type_2_predefined = new Dictionary<Type, PredefinedTypeSpec> () {
50                                 { typeof (object), TypeManager.object_type },
51                                 { typeof (System.ValueType), TypeManager.value_type },
52                                 { typeof (System.Attribute), TypeManager.attribute_type },
53
54                                 { typeof (int), TypeManager.int32_type },
55                                 { typeof (long), TypeManager.int64_type },
56                                 { typeof (uint), TypeManager.uint32_type },
57                                 { typeof (ulong), TypeManager.uint64_type },
58                                 { typeof (byte), TypeManager.byte_type },
59                                 { typeof (sbyte), TypeManager.sbyte_type },
60                                 { typeof (short), TypeManager.short_type },
61                                 { typeof (ushort), TypeManager.ushort_type },
62
63                                 { typeof (System.Collections.IEnumerator), TypeManager.ienumerator_type },
64                                 { typeof (System.Collections.IEnumerable), TypeManager.ienumerable_type },
65                                 { typeof (System.IDisposable), TypeManager.idisposable_type },
66
67                                 { typeof (char), TypeManager.char_type },
68                                 { typeof (string), TypeManager.string_type },
69                                 { typeof (float), TypeManager.float_type },
70                                 { typeof (double), TypeManager.double_type },
71                                 { typeof (decimal), TypeManager.decimal_type },
72                                 { typeof (bool), TypeManager.bool_type },
73                                 { typeof (System.IntPtr), TypeManager.intptr_type },
74                                 { typeof (System.UIntPtr), TypeManager.uintptr_type },
75
76                                 { typeof (System.MulticastDelegate), TypeManager.multicast_delegate_type },
77                                 { typeof (System.Delegate), TypeManager.delegate_type },
78                                 { typeof (System.Enum), TypeManager.enum_type },
79                                 { typeof (System.Array), TypeManager.array_type },
80                                 { typeof (void), TypeManager.void_type },
81                                 { typeof (System.Type), TypeManager.type_type },
82                                 { typeof (System.Exception), TypeManager.exception_type },
83                                 { typeof (System.RuntimeFieldHandle), TypeManager.runtime_field_handle_type },
84                                 { typeof (System.RuntimeTypeHandle), TypeManager.runtime_handle_type }
85                         };
86                 }
87
88                 public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
89                 {
90                         Modifiers mod = 0;
91                         var fa = fi.Attributes;
92                         switch (fa & FieldAttributes.FieldAccessMask) {
93                                 case FieldAttributes.Public:
94                                         mod = Modifiers.PUBLIC;
95                                         break;
96                                 case FieldAttributes.Assembly:
97                                         mod = Modifiers.INTERNAL;
98                                         break;
99                                 case FieldAttributes.Family:
100                                         mod = Modifiers.PROTECTED;
101                                         break;
102                                 case FieldAttributes.FamORAssem:
103                                         mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
104                                         break;
105                                 default:
106                                         // Ignore private fields (even for error reporting) to not require extra dependencies
107                                         if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), typeof (CompilerGeneratedAttribute)))
108                                                 return null;
109
110                                         mod = Modifiers.PRIVATE;
111                                         break;
112                         }
113
114                         var definition = new ImportedMemberDefinition (fi);
115                         TypeSpec field_type;
116
117                         try {
118                                 field_type = ImportType (fi.FieldType, fi, 0);
119                         } catch (Exception e) {
120                                 // TODO: I should construct fake TypeSpec based on TypeRef signature
121                                 // but there is no way to do it with System.Reflection
122                                 throw new InternalErrorException (e, "Cannot import field `{0}.{1}' referenced in assembly `{2}'",
123                                         declaringType.GetSignatureForError (), fi.Name, declaringType.MemberDefinition.DeclaringAssembly);
124                         }
125
126                         if ((fa & FieldAttributes.Literal) != 0) {
127                                 var c = Constant.CreateConstantFromValue (field_type, fi.GetRawConstantValue (), Location.Null);
128                                 return new ConstSpec (declaringType, definition, field_type, fi, mod, c);
129                         }
130
131                         if ((fa & FieldAttributes.InitOnly) != 0) {
132                                 if (field_type == TypeManager.decimal_type) {
133                                         var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi));
134                                         if (dc != null)
135                                                 return new ConstSpec (declaringType, definition, field_type, fi, mod, dc);
136                                 }
137
138                                 mod |= Modifiers.READONLY;
139                         } else {
140                                 var reqs = fi.GetRequiredCustomModifiers ();
141                                 if (reqs.Length > 0) {
142                                         foreach (var t in reqs) {
143                                                 if (t == typeof (IsVolatile)) {
144                                                         mod |= Modifiers.VOLATILE;
145                                                         break;
146                                                 }
147                                         }
148                                 }
149                         }
150
151                         if ((fa & FieldAttributes.Static) != 0) {
152                                 mod |= Modifiers.STATIC;
153                         } else {
154                                 // Fixed buffers cannot be static
155                                 if (declaringType.IsStruct && field_type.IsStruct && field_type.IsNested &&
156                                         HasAttribute (CustomAttributeData.GetCustomAttributes (fi), typeof (FixedBufferAttribute))) {
157
158                                         // TODO: Sanity check on field_type (only few type are allowed)
159                                         var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType);
160                                         return new FixedFieldSpec (declaringType, definition, fi, element_field, mod);
161                                 }
162                         }
163
164                         return new FieldSpec (declaringType, definition, field_type, fi, mod);
165                 }
166
167                 public EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
168                 {
169                         add.IsAccessor = true;
170                         remove.IsAccessor = true;
171
172                         if (add.Modifiers != remove.Modifiers)
173                                 throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
174
175                         var definition = new ImportedMemberDefinition (ei);
176                         return new EventSpec (declaringType, definition, ImportType (ei.EventHandlerType, ei, 0), add.Modifiers, add, remove);
177                 }
178
179                 TypeParameterSpec[] CreateGenericParameters (Type type, TypeSpec declaringType)
180                 {
181                         Type[] tparams = type.GetGenericArguments ();
182
183                         int parent_owned_count;
184                         if (type.IsNested) {
185                                 parent_owned_count = type.DeclaringType.GetGenericArguments ().Length;
186
187                                 //
188                                 // System.Reflection duplicates parent type parameters for each
189                                 // nested type with slightly modified properties (eg. different owner)
190                                 // This just makes things more complicated (think of cloned constraints)
191                                 // therefore we remap any nested type owned by parent using `type_cache'
192                                 // to the single TypeParameterSpec
193                                 //
194                                 if (declaringType != null && parent_owned_count > 0) {
195                                         int read_count = 0;
196                                         while (read_count != parent_owned_count) {
197                                                 var tparams_count = declaringType.Arity;
198                                                 if (tparams_count != 0) {
199                                                         var parent_tp = declaringType.MemberDefinition.TypeParameters;
200                                                         read_count += tparams_count;
201                                                         for (int i = 0; i < tparams_count; i++) {
202                                                                 import_cache.Add (tparams[parent_owned_count - read_count + i], parent_tp[i]);
203                                                         }
204                                                 }
205
206                                                 declaringType = declaringType.DeclaringType;
207                                         }
208                                 }                       
209                         } else {
210                                 parent_owned_count = 0;
211                         }
212
213                         if (tparams.Length - parent_owned_count == 0)
214                                 return null;
215
216                         return CreateGenericParameters (parent_owned_count, tparams);
217                 }
218
219                 TypeParameterSpec[] CreateGenericParameters (int first, Type[] tparams)
220                 {
221                         var tspec = new TypeParameterSpec[tparams.Length - first];
222                         for (int pos = first; pos < tparams.Length; ++pos) {
223                                 var type = tparams[pos];
224                                 int index = pos - first;
225
226                                 tspec [index] = (TypeParameterSpec) CreateType (type, null, 0, false);
227                         }
228
229                         return tspec;
230                 }
231
232                 TypeSpec[] CreateGenericArguments (int first, Type[] tparams, ICustomAttributeProvider ca, int dynamicCursor)
233                 {
234                         var tspec = new TypeSpec [tparams.Length - first];
235                         for (int pos = first; pos < tparams.Length; ++pos) {
236                                 var type = tparams[pos];
237                                 int index = pos - first;
238
239                                 TypeSpec spec;
240                                 if (type.HasElementType) {
241                                         var element = type.GetElementType ();
242                                         spec = ImportType (element, ca, dynamicCursor + 1);
243
244                                         if (!type.IsArray) {
245                                                 throw new NotImplementedException ("Unknown element type " + type.ToString ());
246                                         }
247
248                                         spec = ArrayContainer.MakeType (spec, type.GetArrayRank ());
249                                 } else {
250                                         spec = CreateType (type, ca, dynamicCursor, true);
251
252                                         //
253                                         // We treat nested generic types as inflated internally where
254                                         // reflection uses type definition
255                                         //
256                                         // class A<T> {
257                                         //    IFoo<A<T>> foo;   // A<T> is definition in this case
258                                         // }
259                                         //
260                                         // TODO: Is full logic from CreateType needed here as well?
261                                         //
262                                         if (type.IsGenericTypeDefinition) {
263                                                 var targs = CreateGenericArguments (0, type.GetGenericArguments (), ca, dynamicCursor + 1);
264                                                 spec = spec.MakeGenericType (targs);
265                                         }
266                                 }
267
268                                 ++dynamicCursor;
269                                 tspec[index] = spec;
270                         }
271
272                         return tspec;
273                 }
274
275                 public MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
276                 {
277                         Modifiers mod = ReadMethodModifiers (mb, declaringType);
278                         TypeParameterSpec[] tparams;
279                         ImportedMethodDefinition definition;
280
281                         var parameters = CreateParameters (declaringType, mb.GetParameters (), mb);
282
283                         if (mb.IsGenericMethod) {
284                                 if (!mb.IsGenericMethodDefinition)
285                                         throw new NotSupportedException ("assert");
286
287                                 tparams = CreateGenericParameters (0, mb.GetGenericArguments ());
288                                 definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams);
289                         } else {
290                                 definition = new ImportedMethodDefinition (mb, parameters);
291                                 tparams = null;
292                         }
293
294                         MemberKind kind;
295                         TypeSpec returnType;
296                         if (mb.MemberType == MemberTypes.Constructor) {
297                                 kind = MemberKind.Constructor;
298                                 returnType = TypeManager.void_type;
299                         } else {
300                                 //
301                                 // Detect operators and destructors
302                                 //
303                                 string name = mb.Name;
304                                 kind = MemberKind.Method;
305                                 if (tparams == null && !mb.DeclaringType.IsInterface && name.Length > 6) {
306                                         if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) {
307                                                 if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') {
308                                                         var op_type = Operator.GetType (name);
309                                                         if (op_type.HasValue && parameters.Count > 0 && parameters.Count < 3) {
310                                                                 kind = MemberKind.Operator;
311                                                         }
312                                                 }
313                                         } else if (parameters.IsEmpty && name == Destructor.MetadataName) {
314                                                 kind = MemberKind.Destructor;
315                                                 if (declaringType == TypeManager.object_type) {
316                                                         mod &= ~Modifiers.OVERRIDE;
317                                                         mod |= Modifiers.VIRTUAL;
318                                                 }
319                                         }
320                                 }
321
322                                 var mi = (MethodInfo) mb;
323                                 returnType = ImportType (mi.ReturnType, mi.ReturnTypeCustomAttributes, 0);
324
325                                 // Cannot set to OVERRIDE without full hierarchy checks
326                                 // this flag indicates that the method could be override
327                                 // but further validation is needed
328                                 if ((mod & Modifiers.OVERRIDE) != 0 && kind == MemberKind.Method && declaringType.BaseType != null) {
329                                         var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
330                                         var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
331
332                                         //
333                                         // For imported class method do additional validation to be sure that metadata
334                                         // override flag was correct
335                                         // 
336                                         // Difference between protected internal and protected is ok
337                                         //
338                                         const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
339                                         if (candidate == null || (candidate.Modifiers & conflict_mask) != (mod & conflict_mask) || candidate.IsStatic) {
340                                                 mod &= ~Modifiers.OVERRIDE;
341                                         }
342                                 }
343                         }
344
345                         MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod);
346                         if (tparams != null)
347                                 ms.IsGeneric = true;
348
349                         return ms;
350                 }
351
352                 //
353                 // Imports System.Reflection parameters
354                 //
355                 AParametersCollection CreateParameters (TypeSpec parent, ParameterInfo[] pi, MethodBase method)
356                 {
357                         int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
358
359                         if (pi.Length == 0 && varargs == 0)
360                                 return ParametersCompiled.EmptyReadOnlyParameters;
361
362                         TypeSpec[] types = new TypeSpec[pi.Length + varargs];
363                         IParameterData[] par = new IParameterData[pi.Length + varargs];
364                         bool is_params = false;
365                         for (int i = 0; i < pi.Length; i++) {
366                                 ParameterInfo p = pi[i];
367                                 Parameter.Modifier mod = 0;
368                                 Expression default_value = null;
369                                 if (p.ParameterType.IsByRef) {
370                                         if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
371                                                 mod = Parameter.Modifier.OUT;
372                                         else
373                                                 mod = Parameter.Modifier.REF;
374
375                                         //
376                                         // Strip reference wrapping
377                                         //
378                                         var el = p.ParameterType.GetElementType ();
379                                         types[i] = ImportType (el, p, 0);       // TODO: 1 to be csc compatible
380                                 } else if (i == 0 && method.IsStatic && parent.IsStatic && parent.MemberDefinition.DeclaringAssembly.HasExtensionMethod &&
381                                         HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (method)) != null) {
382                                         mod = Parameter.Modifier.This;
383                                         types[i] = ImportType (p.ParameterType);
384                                 } else {
385                                         types[i] = ImportType (p.ParameterType, p, 0);
386
387                                         if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
388                                                 if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), typeof (ParamArrayAttribute))) {
389                                                         mod = Parameter.Modifier.PARAMS;
390                                                         is_params = true;
391                                                 }
392                                         }
393
394                                         if (!is_params && p.IsOptional) {
395                                                 object value = p.RawDefaultValue;
396                                                 var ptype = types[i];
397                                                 if (((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter)) {
398                                                         //
399                                                         // Use value type as int constant can be used for object parameter type
400                                                         //
401                                                         var dtype = value == null ? ptype : ImportType (value.GetType ());
402                                                         default_value = Constant.CreateConstant (null, dtype, value, Location.Null);
403                                                 } else if (value == Missing.Value) {
404                                                         default_value = EmptyExpression.MissingValue;
405                                                 } else {
406                                                         if (ptype == TypeManager.decimal_type)
407                                                                 default_value = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (p));
408
409                                                         if (default_value == null)
410                                                                 default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null);
411                                                 }
412                                         }
413                                 }
414
415                                 par[i] = new ParameterData (p.Name, mod, default_value);
416                         }
417
418                         if (varargs != 0) {
419                                 par[par.Length - 1] = new ArglistParameter (Location.Null);
420                                 types[types.Length - 1] = InternalType.Arglist;
421                         }
422
423                         return method != null ?
424                                 new ParametersImported (par, types, varargs != 0, is_params) :
425                                 new ParametersImported (par, types, is_params);
426                 }
427
428
429                 //
430                 // Returns null when the property is not valid C# property
431                 //
432                 public PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
433                 {
434                         Modifiers mod = 0;
435                         AParametersCollection param = null;
436                         TypeSpec type = null;
437                         if (get != null) {
438                                 mod = get.Modifiers;
439                                 param = get.Parameters;
440                                 type = get.ReturnType;
441                         }
442
443                         bool is_valid_property = true;
444                         if (set != null) {
445                                 if (set.ReturnType != TypeManager.void_type)
446                                         is_valid_property = false;
447
448                                 var set_param_count = set.Parameters.Count - 1;
449
450                                 if (set_param_count < 0) {
451                                         set_param_count = 0;
452                                         is_valid_property = false;
453                                 }
454
455                                 var set_type = set.Parameters.Types[set_param_count];
456
457                                 if (mod == 0) {
458                                         AParametersCollection set_based_param;
459
460                                         if (set_param_count == 0) {
461                                                 set_based_param = ParametersCompiled.EmptyReadOnlyParameters;
462                                         } else {
463                                                 //
464                                                 // Create indexer parameters based on setter method parameters (the last parameter has to be removed)
465                                                 //
466                                                 var data = new IParameterData[set_param_count];
467                                                 var types = new TypeSpec[set_param_count];
468                                                 Array.Copy (set.Parameters.FixedParameters, data, set_param_count);
469                                                 Array.Copy (set.Parameters.Types, types, set_param_count);
470                                                 set_based_param = new ParametersImported (data, types, set.Parameters.HasParams);
471                                         }
472
473                                         mod = set.Modifiers;
474                                         param = set_based_param;
475                                         type = set_type;
476                                 } else {
477                                         if (set_param_count != get.Parameters.Count)
478                                                 is_valid_property = false;
479
480                                         if (get.ReturnType != set_type)
481                                                 is_valid_property = false;
482
483                                         // Possible custom accessor modifiers
484                                         if ((mod & Modifiers.AccessibilityMask) != (set.Modifiers & Modifiers.AccessibilityMask)) {
485                                                 var get_acc = mod & Modifiers.AccessibilityMask;
486                                                 if (get_acc != Modifiers.PUBLIC) {
487                                                         var set_acc = set.Modifiers & Modifiers.AccessibilityMask;
488                                                         // If the accessor modifiers are not same, do extra restriction checks
489                                                         if (get_acc != set_acc) {
490                                                                 var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc);
491                                                                 var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc);
492                                                                 if (get_restr && set_restr) {
493                                                                         is_valid_property = false; // Neither is more restrictive
494                                                                 }
495
496                                                                 if (get_restr) {
497                                                                         mod &= ~Modifiers.AccessibilityMask;
498                                                                         mod |= set_acc;
499                                                                 }
500                                                         }
501                                                 }
502                                         }
503                                 }
504                         }
505
506                         PropertySpec spec = null;
507                         if (!param.IsEmpty) {
508                                 var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
509                                 if (index_name == null) {
510                                         is_valid_property = false;
511                                 } else {
512                                         if (get != null) {
513                                                 if (get.IsStatic)
514                                                         is_valid_property = false;
515                                                 if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
516                                                         is_valid_property = false;
517                                         }
518                                         if (set != null) {
519                                                 if (set.IsStatic)
520                                                         is_valid_property = false;
521                                                 if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
522                                                         is_valid_property = false;
523                                         }
524                                 }
525
526                                 if (is_valid_property)
527                                         spec = new IndexerSpec (declaringType, new ImportedIndexerDefinition (pi, param), type, param, pi, mod);
528                         }
529
530                         if (spec == null)
531                                 spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi), type, pi, mod);
532
533                         if (!is_valid_property) {
534                                 spec.IsNotRealProperty = true;
535                                 return spec;
536                         }
537
538                         if (set != null)
539                                 spec.Set = set;
540                         if (get != null)
541                                 spec.Get = get;
542
543                         return spec;
544                 }
545
546                 public TypeSpec CreateType (Type type)
547                 {
548                         return CreateType (type, null, 0, true);
549                 }
550
551                 TypeSpec CreateType (Type type, ICustomAttributeProvider ca, int dynamicCursor, bool canImportBaseType)
552                 {
553                         TypeSpec declaring_type;
554                         if (type.IsNested && !type.IsGenericParameter)
555                                 declaring_type = CreateType (type.DeclaringType, type.DeclaringType, 0, true);
556                         else
557                                 declaring_type = null;
558
559                         return CreateType (type, declaring_type, ca, dynamicCursor, canImportBaseType);
560                 }
561
562                 public TypeSpec CreateType (Type type, TypeSpec declaringType, ICustomAttributeProvider ca, int dynamicCursor, bool canImportBaseType)
563                 {
564                         TypeSpec spec;
565                         if (import_cache.TryGetValue (type, out spec)) {
566                                 if (ca == null)
567                                         return spec;
568
569                                 if (type == typeof (object)) {
570                                         if (IsDynamicType (ca, dynamicCursor))
571                                                 return InternalType.Dynamic;
572
573                                         return spec;
574                                 }
575
576                                 if (!spec.IsGeneric)
577                                         return spec;
578
579 #if NET_4_0
580                                 if (!ca.IsDefined (typeof (DynamicAttribute), false))
581 #endif
582                                         return spec;
583
584                                 // We've found same object in the cache but this one has a dynamic custom attribute
585                                 // and it's most likely dynamic version of same type IFoo<object> agains IFoo<dynamic>
586                                 // Do resolve the type process again in that case
587                         }
588
589                         if (type.IsGenericType && !type.IsGenericTypeDefinition) {
590                                 var type_def = type.GetGenericTypeDefinition ();
591                                 var targs = CreateGenericArguments (0, type.GetGenericArguments (), ca, dynamicCursor + 1);
592                                 if (declaringType == null) {
593                                         // Simple case, no nesting
594                                         spec = CreateType (type_def, null, null, 0, canImportBaseType);
595                                         spec = spec.MakeGenericType (targs);
596                                 } else {
597                                         //
598                                         // Nested type case, converting .NET types like
599                                         // A`1.B`1.C`1<int, long, string> to typespec like
600                                         // A<int>.B<long>.C<string>
601                                         //
602                                         var nested_hierarchy = new List<TypeSpec> ();
603                                         while (declaringType.IsNested) {
604                                                 nested_hierarchy.Add (declaringType);
605                                                 declaringType = declaringType.DeclaringType;
606                                         }
607
608                                         int targs_pos = 0;
609                                         if (declaringType.Arity > 0) {
610                                                 spec = declaringType.MakeGenericType (targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ());
611                                                 targs_pos = spec.Arity;
612                                         } else {
613                                                 spec = declaringType;
614                                         }
615
616                                         for (int i = nested_hierarchy.Count; i != 0; --i) {
617                                                 var t = nested_hierarchy [i - 1];
618                                                 spec = MemberCache.FindNestedType (spec, t.Name, t.Arity);
619                                                 if (t.Arity > 0) {
620                                                         spec = spec.MakeGenericType (targs.Skip (targs_pos).Take (spec.Arity).ToArray ());
621                                                         targs_pos += t.Arity;
622                                                 }
623                                         }
624
625                                         string name = type.Name;
626                                         int index = name.IndexOf ('`');
627                                         if (index > 0)
628                                                 name = name.Substring (0, index);
629
630                                         spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
631                                         if (spec.Arity > 0) {
632                                                 spec = spec.MakeGenericType (targs.Skip (targs_pos).ToArray ());
633                                         }
634                                 }
635
636                                 // Don't add generic type with dynamic arguments, they can interfere with same type
637                                 // using object type arguments
638                                 if (!spec.HasDynamicElement) {
639
640                                         // Add to reading cache to speed up reading
641                                         if (!import_cache.ContainsKey (type))
642                                                 import_cache.Add (type, spec);
643                                 }
644
645                                 return spec;
646                         }
647
648                         Modifiers mod;
649                         MemberKind kind;
650
651                         var ma = type.Attributes;
652                         switch (ma & TypeAttributes.VisibilityMask) {
653                         case TypeAttributes.Public:
654                         case TypeAttributes.NestedPublic:
655                                 mod = Modifiers.PUBLIC;
656                                 break;
657                         case TypeAttributes.NestedPrivate:
658                                 mod = Modifiers.PRIVATE;
659                                 break;
660                         case TypeAttributes.NestedFamily:
661                                 mod = Modifiers.PROTECTED;
662                                 break;
663                         case TypeAttributes.NestedFamORAssem:
664                                 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
665                                 break;
666                         default:
667                                 mod = Modifiers.INTERNAL;
668                                 break;
669                         }
670
671                         if ((ma & TypeAttributes.Interface) != 0) {
672                                 kind = MemberKind.Interface;
673                         } else if (type.IsGenericParameter) {
674                                 kind = MemberKind.TypeParameter;
675                         } else if (type.IsClass || type.IsAbstract) {                           // System.Reflection: System.Enum returns false for IsClass
676                                 if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) {
677                                         kind = MemberKind.Delegate;
678                                         mod |= Modifiers.SEALED;
679                                 } else {
680                                         kind = MemberKind.Class;
681                                         if ((ma & TypeAttributes.Sealed) != 0) {
682                                                 mod |= Modifiers.SEALED;
683                                                 if ((ma & TypeAttributes.Abstract) != 0)
684                                                         mod |= Modifiers.STATIC;
685                                         } else if ((ma & TypeAttributes.Abstract) != 0) {
686                                                 mod |= Modifiers.ABSTRACT;
687                                         }
688                                 }
689                         } else if (type.IsEnum) {
690                                 kind = MemberKind.Enum;
691                         } else {
692                                 kind = MemberKind.Struct;
693                                 mod |= Modifiers.SEALED;
694                         }
695
696                         var definition = new ImportedTypeDefinition (this, type);
697                         PredefinedTypeSpec pt;
698
699                         if (kind == MemberKind.Enum) {
700                                 const BindingFlags underlying_member = BindingFlags.DeclaredOnly |
701                                         BindingFlags.Instance |
702                                         BindingFlags.Public | BindingFlags.NonPublic;
703
704                                 var type_members = type.GetFields (underlying_member);
705                                 foreach (var type_member in type_members) {
706                                         spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod);
707                                         break;
708                                 }
709
710                                 if (spec == null)
711                                         kind = MemberKind.Class;
712
713                         } else if (kind == MemberKind.TypeParameter) {
714                                 // Return as type_cache was updated
715                                 return CreateTypeParameter (type, declaringType);
716                         } else if (type.IsGenericTypeDefinition) {
717                                 definition.TypeParameters = CreateGenericParameters (type, declaringType);
718
719                                 // Constraints are not loaded on demand and can reference this type
720                                 if (import_cache.TryGetValue (type, out spec))
721                                         return spec;
722
723                         } else if (type_2_predefined.TryGetValue (type, out pt)) {
724                                 spec = pt;
725                                 pt.SetDefinition (definition, type);
726                         }
727
728                         if (spec == null)
729                                 spec = new TypeSpec (kind, declaringType, definition, type, mod);
730
731                         import_cache.Add (type, spec);
732
733                         //
734                         // Two stage setup as the base type can be inflated declaring type or
735                         // another nested type inside same declaring type which has not been
736                         // loaded, therefore we can import a base type of nested types once
737                         // the types have been imported
738                         //
739                         if (canImportBaseType)
740                                 ImportTypeBase (spec, type);
741
742                         return spec;
743                 }
744
745                 public ImportedAssemblyDefinition GetAssemblyDefinition (Assembly assembly)
746                 {
747                         ImportedAssemblyDefinition def;
748                         if (!assembly_2_definition.TryGetValue (assembly, out def)) {
749
750                                 // This can happen in dynamic context only
751                                 def = new ImportedAssemblyDefinition (assembly);
752                                 assembly_2_definition.Add (assembly, def);
753                                 def.ReadAttributes ();
754                         }
755
756                         return def;
757                 }
758
759                 public void ImportTypeBase (Type type)
760                 {
761                         TypeSpec spec = import_cache[type];
762                         if (spec != null)
763                                 ImportTypeBase (spec, type);
764                 }
765
766                 void ImportTypeBase (TypeSpec spec, Type type)
767                 {
768                         if (spec.Kind == MemberKind.Interface)
769                                 spec.BaseType = TypeManager.object_type;
770                         else if (type.BaseType != null) {
771                                 if (type.BaseType.IsGenericType)
772                                         spec.BaseType = CreateType (type.BaseType, type, 0, true);
773                                 else
774                                         spec.BaseType = CreateType (type.BaseType);
775                         }
776
777                         var ifaces = type.GetInterfaces ();
778                         if (ifaces.Length > 0) {
779                                 foreach (Type iface in ifaces) {
780                                         spec.AddInterface (CreateType (iface));
781                                 }
782                         }
783                 }
784
785                 TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType)
786                 {
787                         Variance variance;
788                         switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
789                         case GenericParameterAttributes.Covariant:
790                                 variance = Variance.Covariant;
791                                 break;
792                         case GenericParameterAttributes.Contravariant:
793                                 variance = Variance.Contravariant;
794                                 break;
795                         default:
796                                 variance = Variance.None;
797                                 break;
798                         }
799
800                         SpecialConstraint special = SpecialConstraint.None;
801                         var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
802
803                         if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) {
804                                 special |= SpecialConstraint.Struct;
805                         } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) {
806                                 special = SpecialConstraint.Constructor;
807                         }
808
809                         if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) {
810                                 special |= SpecialConstraint.Class;
811                         }
812
813                         TypeParameterSpec spec;
814                         var def = new ImportedTypeParameterDefinition (type);
815                         if (type.DeclaringMethod != null)
816                                 spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type);
817                         else
818                                 spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type);
819
820                         // Add it now, so any constraint can reference it and get same instance
821                         import_cache.Add (type, spec);
822
823                         var constraints = type.GetGenericParameterConstraints ();
824                         List<TypeSpec> tparams = null;
825                         foreach (var ct in constraints) {
826                                 if (ct.IsGenericParameter) {
827                                         if (tparams == null)
828                                                 tparams = new List<TypeSpec> ();
829
830                                         tparams.Add (CreateType (ct));
831                                         continue;
832                                 }
833
834                                 if (ct.IsClass) {
835                                         if (ct == typeof (ValueType)) {
836                                                 spec.BaseType = TypeManager.value_type;
837                                         } else {
838                                                 spec.BaseType = CreateType (ct);
839                                         }
840
841                                         continue;
842                                 }
843
844                                 spec.AddInterface (CreateType (ct));
845                         }
846
847                         if (spec.BaseType == null)
848                                 spec.BaseType = TypeManager.object_type;
849
850                         if (tparams != null)
851                                 spec.TypeArguments = tparams.ToArray ();
852
853                         return spec;
854                 }
855
856                 public bool HasAttribute (IList<CustomAttributeData> attributesData, Type type)
857                 {
858                         if (attributesData.Count == 0)
859                                 return false;
860
861                         foreach (var attr in attributesData) {
862                                 if (attr.Constructor.DeclaringType == type)
863                                         return true;
864                         }
865
866                         return false;
867                 }
868
869                 static Type HasExtensionAttribute (IList<CustomAttributeData> attributes)
870                 {
871                         if (attributes.Count == 0)
872                                 return null;
873
874                         foreach (var attr in attributes) {
875                                 var dt = attr.Constructor.DeclaringType;
876                                 if (dt.Name == "ExtensionAttribute" && dt.Namespace == "System.Runtime.CompilerServices") {
877                                         return dt;
878                                 }
879                         }
880
881                         return null;
882                 }
883
884                 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
885                 {
886                         // It can be used more than once when importing same assembly
887                         // into 2 or more global aliases
888                         ImportedAssemblyDefinition definition;
889                         if (!assembly_2_definition.TryGetValue (assembly, out definition)) {
890                                 definition = new ImportedAssemblyDefinition (assembly);
891                                 assembly_2_definition.Add (assembly, definition);
892
893                                 definition.ReadAttributes ();
894                         }
895
896                         Type extension_type = definition.HasExtensionMethod ? HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (assembly)) : null;
897
898                         //
899                         // This part tries to simulate loading of top-level
900                         // types only, any missing dependencies are ignores here.
901                         // Full error report is reported later when the type is
902                         // actually used
903                         //
904                         Type[] all_types;
905                         try {
906                                 all_types = assembly.GetTypes ();
907                         } catch (ReflectionTypeLoadException e) {
908                                 all_types = e.Types;
909                         }
910
911                         ImportTypes (all_types, targetNamespace, extension_type);
912                 }
913
914                 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
915                 {
916                         var module_definition = new ImportedModuleDefinition (module, this);
917                         module_definition.ReadAttributes ();
918
919                         Type extension_type = HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (module));
920
921                         Type[] all_types;
922                         try {
923                                 all_types = module.GetTypes ();
924                         } catch (ReflectionTypeLoadException e) {
925                                 all_types = e.Types;
926                         }
927
928                         ImportTypes (all_types, targetNamespace, extension_type);
929
930                         return module_definition;
931                 }
932
933                 void ImportTypes (Type[] types, Namespace targetNamespace, Type extension_type)
934                 {
935                         Namespace ns = targetNamespace;
936                         string prev_namespace = null;
937                         foreach (var t in types) {
938                                 if (t == null)
939                                         continue;
940
941                                 // Be careful not to trigger full parent type loading
942                                 if (t.MemberType == MemberTypes.NestedType)
943                                         continue;
944
945                                 if (t.Name[0] == '<')
946                                         continue;
947
948                                 var it = CreateType (t, null, t, 0, true);
949                                 if (it == null)
950                                         continue;
951
952                                 if (prev_namespace != t.Namespace) {
953                                         ns = t.Namespace == null ? targetNamespace : targetNamespace.GetNamespace (t.Namespace, true);
954                                         prev_namespace = t.Namespace;
955                                 }
956
957                                 ns.AddType (it);
958
959                                 if (it.IsStatic && extension_type != null && t.IsDefined (extension_type, false)) {
960                                         it.SetExtensionMethodContainer ();
961                                 }
962                         }
963                 }
964
965                 public TypeSpec ImportType (Type type)
966                 {
967                         return ImportType (type, null, 0);
968                 }
969
970                 public TypeSpec ImportType (Type type, ICustomAttributeProvider ca, int dynamicCursor)
971                 {
972                         if (type.HasElementType) {
973                                 var element = type.GetElementType ();
974                                 var spec = ImportType (element, ca, dynamicCursor + 1);
975
976                                 if (type.IsArray)
977                                         return ArrayContainer.MakeType (spec, type.GetArrayRank ());
978                                 if (type.IsByRef)
979                                         return ReferenceContainer.MakeType (spec);
980                                 if (type.IsPointer)
981                                         return PointerContainer.MakeType (spec);
982
983                                 throw new NotImplementedException ("Unknown element type " + type.ToString ());
984                         }
985
986                         return CreateType (type, ca, dynamicCursor, true);
987                 }
988
989                 static bool IsDynamicType (ICustomAttributeProvider ca, int index)
990                 {
991 #if NET_4_0
992                         if (ca.IsDefined (typeof (DynamicAttribute), false)) {
993                                 if (index == 0)
994                                         return true;
995
996                                 var v = (DynamicAttribute) ca.GetCustomAttributes (typeof (DynamicAttribute), false)[0];
997                                 return v.TransformFlags[index];
998                         }
999 #endif
1000                         return false;
1001                 }
1002
1003                 //
1004                 // Decimal constants cannot be encoded in the constant blob, and thus are marked
1005                 // as IsInitOnly ('readonly' in C# parlance).  We get its value from the 
1006                 // DecimalConstantAttribute metadata.
1007                 //
1008                 static Constant ReadDecimalConstant (IList<CustomAttributeData> attrs)
1009                 {
1010                         if (attrs.Count == 0)
1011                                 return null;
1012
1013                         foreach (var ca in attrs) {
1014                                 if (ca.Constructor.DeclaringType != typeof (DecimalConstantAttribute))
1015                                         continue;
1016
1017                                 var value = new decimal (
1018                                         (int) (uint) ca.ConstructorArguments[4].Value,
1019                                         (int) (uint) ca.ConstructorArguments[3].Value,
1020                                         (int) (uint) ca.ConstructorArguments[2].Value,
1021                                         (byte) ca.ConstructorArguments[1].Value != 0,
1022                                         (byte) ca.ConstructorArguments[0].Value);
1023
1024                                 return new DecimalConstant (value, Location.Null).Resolve (null);
1025                         }
1026
1027                         return null;
1028                 }
1029
1030                 static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType)
1031                 {
1032                         Modifiers mod;
1033                         var ma = mb.Attributes;
1034                         switch (ma & MethodAttributes.MemberAccessMask) {
1035                         case MethodAttributes.Public:
1036                                 mod = Modifiers.PUBLIC;
1037                                 break;
1038                         case MethodAttributes.Assembly:
1039                                 mod = Modifiers.INTERNAL;
1040                                 break;
1041                         case MethodAttributes.Family:
1042                                 mod = Modifiers.PROTECTED;
1043                                 break;
1044                         case MethodAttributes.FamORAssem:
1045                                 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
1046                                 break;
1047                         default:
1048                                 mod = Modifiers.PRIVATE;
1049                                 break;
1050                         }
1051
1052                         if ((ma & MethodAttributes.Static) != 0) {
1053                                 mod |= Modifiers.STATIC;
1054                                 return mod;
1055                         }
1056                         if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) {
1057                                 mod |= Modifiers.ABSTRACT;
1058                                 return mod;
1059                         }
1060
1061                         if ((ma & MethodAttributes.Final) != 0)
1062                                 mod |= Modifiers.SEALED;
1063
1064                         // It can be sealed and override
1065                         if ((ma & MethodAttributes.Virtual) != 0) {
1066                                 if ((ma & MethodAttributes.NewSlot) != 0 || !declaringType.IsClass) {
1067                                         // No private virtual or sealed virtual
1068                                         if ((mod & (Modifiers.PRIVATE | Modifiers.SEALED)) == 0)
1069                                                 mod |= Modifiers.VIRTUAL;
1070                                 } else {
1071                                         mod |= Modifiers.OVERRIDE;
1072                                 }
1073                         }
1074
1075                         return mod;
1076                 }
1077         }
1078
1079         class ImportedMemberDefinition : IMemberDefinition
1080         {
1081                 protected class AttributesBag
1082                 {
1083                         public static readonly AttributesBag Default = new AttributesBag ();
1084
1085                         public AttributeUsageAttribute AttributeUsage;
1086                         public ObsoleteAttribute Obsolete;
1087                         public string[] Conditionals;
1088                         public string DefaultIndexerName;
1089                         public bool IsNotCLSCompliant;
1090                         public TypeSpec CoClass;
1091                         
1092                         public static AttributesBag Read (MemberInfo mi, ReflectionMetaImporter typeImporter)
1093                         {
1094                                 AttributesBag bag = null;
1095                                 List<string> conditionals = null;
1096
1097                                 // It should not throw any loading exception
1098                                 IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (mi);
1099
1100                                 foreach (var a in attrs) {
1101                                         var type = a.Constructor.DeclaringType;
1102                                         if (type == typeof (ObsoleteAttribute)) {
1103                                                 if (bag == null)
1104                                                         bag = new AttributesBag ();
1105
1106                                                 var args = a.ConstructorArguments;
1107
1108                                                 if (args.Count == 1) {
1109                                                         bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value);
1110                                                 } else if (args.Count == 2) {
1111                                                         bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value);
1112                                                 } else {
1113                                                         bag.Obsolete = new ObsoleteAttribute ();
1114                                                 }
1115
1116                                                 continue;
1117                                         }
1118
1119                                         if (type == typeof (ConditionalAttribute)) {
1120                                                 if (bag == null)
1121                                                         bag = new AttributesBag ();
1122
1123                                                 if (conditionals == null)
1124                                                         conditionals = new List<string> (2);
1125
1126                                                 conditionals.Add ((string) a.ConstructorArguments[0].Value);
1127                                                 continue;
1128                                         }
1129
1130                                         if (type == typeof (CLSCompliantAttribute)) {
1131                                                 if (bag == null)
1132                                                         bag = new AttributesBag ();
1133
1134                                                 bag.IsNotCLSCompliant = !(bool) a.ConstructorArguments[0].Value;
1135                                                 continue;
1136                                         }
1137
1138                                         // Type only attributes
1139                                         if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) {
1140                                                 if (type == typeof (DefaultMemberAttribute)) {
1141                                                         if (bag == null)
1142                                                                 bag = new AttributesBag ();
1143
1144                                                         bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value;
1145                                                         continue;
1146                                                 }
1147
1148                                                 if (type == typeof (AttributeUsageAttribute)) {
1149                                                         if (bag == null)
1150                                                                 bag = new AttributesBag ();
1151
1152                                                         bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value);
1153                                                         foreach (var named in a.NamedArguments) {
1154                                                                 if (named.MemberInfo.Name == "AllowMultiple")
1155                                                                         bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value;
1156                                                                 else if (named.MemberInfo.Name == "Inherited")
1157                                                                         bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value;
1158                                                         }
1159                                                         continue;
1160                                                 }
1161
1162                                                 // Interface only attribute
1163                                                 if (typeImporter != null && type == typeof (CoClassAttribute)) {
1164                                                         if (bag == null)
1165                                                                 bag = new AttributesBag ();
1166
1167                                                         bag.CoClass = typeImporter.ImportType ((Type) a.ConstructorArguments[0].Value);
1168                                                         continue;
1169                                                 }
1170                                         }
1171                                 }
1172
1173                                 if (bag == null)
1174                                         return Default;
1175
1176                                 if (conditionals != null)
1177                                         bag.Conditionals = conditionals.ToArray ();
1178                                 
1179                                 return bag;
1180                         }
1181                 }
1182
1183                 protected readonly MemberInfo provider;
1184                 protected AttributesBag cattrs;
1185
1186                 public ImportedMemberDefinition (MemberInfo provider)
1187                 {
1188                         this.provider = provider;
1189                 }
1190
1191                 #region Properties
1192
1193                 public bool IsImported {
1194                         get {
1195                                 return true;
1196                         }
1197                 }
1198
1199                 public virtual string Name {
1200                         get {
1201                                 return provider.Name;
1202                         }
1203                 }
1204
1205                 #endregion
1206
1207                 public string[] ConditionalConditions ()
1208                 {
1209                         if (cattrs == null)
1210                                 ReadAttributes ();
1211
1212                         return cattrs.Conditionals;
1213                 }
1214
1215                 public ObsoleteAttribute GetAttributeObsolete ()
1216                 {
1217                         if (cattrs == null)
1218                                 ReadAttributes ();
1219
1220                         return cattrs.Obsolete;
1221                 }
1222
1223                 public bool IsNotCLSCompliant ()
1224                 {
1225                         if (cattrs == null)
1226                                 ReadAttributes ();
1227
1228                         return cattrs.IsNotCLSCompliant;
1229                 }
1230
1231                 protected virtual void ReadAttributes ()
1232                 {
1233                         cattrs = AttributesBag.Read (provider, null);
1234                 }
1235
1236                 public void SetIsAssigned ()
1237                 {
1238                         // Unused for imported members
1239                 }
1240
1241                 public void SetIsUsed ()
1242                 {
1243                         // Unused for imported members
1244                 }
1245         }
1246
1247         public class ImportedModuleDefinition
1248         {
1249                 readonly Module module;
1250                 bool cls_compliant;
1251                 //ReflectionMetaImporter metaImporter;
1252                 
1253                 public ImportedModuleDefinition (Module module, ReflectionMetaImporter metaImporter)
1254                 {
1255                         this.module = module;
1256                         //this.metaImporter = metaImporter;
1257                 }
1258
1259                 #region Properties
1260
1261                 public bool IsCLSCompliant {
1262                         get {
1263                                 return cls_compliant;
1264                         }
1265                 }
1266
1267                 public string Name {
1268                         get {
1269                                 return module.Name;
1270                         }
1271                 }
1272
1273                 #endregion
1274
1275                 public void ReadAttributes ()
1276                 {
1277                         IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (module);
1278                         foreach (var a in attrs) {
1279                                 var type = a.Constructor.DeclaringType;
1280                                 if (type == typeof (CLSCompliantAttribute)) {
1281                                         cls_compliant = (bool) a.ConstructorArguments[0].Value;
1282                                         continue;
1283                                 }
1284                         }
1285                 }
1286
1287                 //
1288                 // Reads assembly attributes which where attached to a special type because
1289                 // module does have assembly manifest
1290                 //
1291                 public List<Attribute> ReadAssemblyAttributes ()
1292                 {
1293                         var t = module.GetType (AssemblyAttributesPlaceholder.GetGeneratedName (Name));
1294                         if (t == null)
1295                                 return null;
1296
1297                         var field = t.GetField (AssemblyAttributesPlaceholder.AssemblyFieldName, BindingFlags.NonPublic | BindingFlags.Static);
1298                         if (field == null)
1299                                 return null;
1300
1301                         // TODO: implement, the idea is to fabricate specil Attribute class and
1302                         // add it to OptAttributes before resolving the source code attributes
1303                         // Need to build module location as well for correct error reporting
1304
1305                         //var assembly_attributes = CustomAttributeData.GetCustomAttributes (field);
1306                         //var attrs = new List<Attribute> (assembly_attributes.Count);
1307                         //foreach (var a in assembly_attributes)
1308                         //{
1309                         //    var type = metaImporter.ImportType (a.Constructor.DeclaringType);
1310                         //    var ctor = metaImporter.CreateMethod (a.Constructor, type);
1311
1312                         //    foreach (var carg in a.ConstructorArguments) {
1313                         //        carg.Value
1314                         //    }
1315
1316                         //    attrs.Add (new Attribute ("assembly", ctor, null, Location.Null, true));
1317                         //}
1318
1319                         return null;
1320                 }
1321         }
1322
1323         public class ImportedAssemblyDefinition : IAssemblyDefinition
1324         {
1325                 readonly Assembly assembly;
1326                 readonly AssemblyName aname;
1327                 bool cls_compliant;
1328                 bool contains_extension_methods;
1329
1330                 List<AssemblyName> internals_visible_to;
1331                 Dictionary<IAssemblyDefinition, AssemblyName> internals_visible_to_cache;
1332
1333                 public ImportedAssemblyDefinition (Assembly assembly)
1334                 {
1335                         this.assembly = assembly;
1336                         this.aname = assembly.GetName ();
1337                 }
1338
1339                 #region Properties
1340
1341                 public Assembly Assembly {
1342                         get {
1343                                 return assembly;
1344                         }
1345                 }
1346
1347                 public string FullName {
1348                         get {
1349                                 return aname.FullName;
1350                         }
1351                 }
1352
1353                 public bool HasExtensionMethod {
1354                         get {
1355                                 return contains_extension_methods;
1356                         }
1357                 }
1358
1359                 public bool HasStrongName {
1360                         get {
1361                                 return aname.GetPublicKey ().Length != 0;
1362                         }
1363                 }
1364
1365                 public bool IsCLSCompliant {
1366                         get {
1367                                 return cls_compliant;
1368                         }
1369                 }
1370
1371                 public string Location {
1372                         get {
1373                                 return assembly.Location;
1374                         }
1375                 }
1376
1377                 public string Name {
1378                         get {
1379                                 return aname.Name;
1380                         }
1381                 }
1382
1383                 #endregion
1384
1385                 public byte[] GetPublicKeyToken ()
1386                 {
1387                         return aname.GetPublicKeyToken ();
1388                 }
1389
1390                 public AssemblyName GetAssemblyVisibleToName (IAssemblyDefinition assembly)
1391                 {
1392                         return internals_visible_to_cache [assembly];
1393                 }
1394
1395                 public bool IsFriendAssemblyTo (IAssemblyDefinition assembly)
1396                 {
1397                         if (internals_visible_to == null)
1398                                 return false;
1399
1400                         AssemblyName is_visible = null;
1401                         if (internals_visible_to_cache == null) {
1402                                 internals_visible_to_cache = new Dictionary<IAssemblyDefinition, AssemblyName> ();
1403                         } else {
1404                                 if (internals_visible_to_cache.TryGetValue (assembly, out is_visible))
1405                                         return is_visible != null;
1406                         }
1407
1408                         var token = assembly.GetPublicKeyToken ();
1409                         if (token != null && token.Length == 0)
1410                                 token = null;
1411
1412                         foreach (var internals in internals_visible_to) {
1413                                 if (internals.Name != assembly.Name)
1414                                         continue;
1415
1416                                 if (token == null && assembly is AssemblyDefinition) {
1417                                         is_visible = internals;
1418                                         break;
1419                                 }
1420
1421                                 if (!ArrayComparer.IsEqual (token, internals.GetPublicKeyToken ()))
1422                                         continue;
1423
1424                                 is_visible = internals;
1425                                 break;
1426                         }
1427
1428                         internals_visible_to_cache.Add (assembly, is_visible);
1429                         return is_visible != null;
1430                 }
1431
1432                 public void ReadAttributes ()
1433                 {
1434                         IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (assembly);
1435
1436                         foreach (var a in attrs) {
1437                                 var type = a.Constructor.DeclaringType;
1438                                 if (type == typeof (CLSCompliantAttribute)) {
1439                                         cls_compliant = (bool) a.ConstructorArguments[0].Value;
1440                                         continue;
1441                                 }
1442
1443                                 if (type == typeof (InternalsVisibleToAttribute)) {
1444                                         string s = a.ConstructorArguments[0].Value as string;
1445                                         if (s == null)
1446                                                 continue;
1447
1448                                         var an = new AssemblyName (s);
1449                                         if (internals_visible_to == null)
1450                                                 internals_visible_to = new List<AssemblyName> ();
1451
1452                                         internals_visible_to.Add (an);
1453                                         continue;
1454                                 }
1455
1456                                 if (type.Name == "ExtensionAttribute" && type.Namespace == "System.Runtime.CompilerServices") {
1457                                         contains_extension_methods = true;
1458                                         continue;
1459                                 }
1460                         }
1461                 }
1462
1463                 public override string ToString ()
1464                 {
1465                         return FullName;
1466                 }
1467         }
1468
1469         class ImportedMethodDefinition : ImportedMemberDefinition, IParametersMember
1470         {
1471                 readonly AParametersCollection parameters;
1472
1473                 public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters)
1474                         : base (provider)
1475                 {
1476                         this.parameters = parameters;
1477                 }
1478
1479                 #region Properties
1480
1481                 public AParametersCollection Parameters {
1482                         get {
1483                                 return parameters;
1484                         }
1485                 }
1486
1487                 public TypeSpec MemberType {
1488                         get {
1489                                 throw new NotImplementedException ();
1490                         }
1491                 }
1492
1493                 #endregion
1494         }
1495
1496         class ImportedIndexerDefinition : ImportedMemberDefinition, IParametersMember
1497         {
1498                 readonly AParametersCollection parameters;
1499
1500                 public ImportedIndexerDefinition (PropertyInfo provider, AParametersCollection parameters)
1501                         : base (provider)
1502                 {
1503                         this.parameters = parameters;
1504                 }
1505
1506                 #region Properties
1507
1508                 public AParametersCollection Parameters {
1509                         get {
1510                                 return parameters;
1511                         }
1512                 }
1513
1514                 public TypeSpec MemberType {
1515                         get {
1516                                 throw new NotImplementedException ();
1517                         }
1518                 }
1519
1520                 #endregion
1521         }
1522
1523         class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition
1524         {
1525                 TypeParameterSpec[] tparams;
1526
1527                 public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams)
1528                         : base (provider, parameters)
1529                 {
1530                         this.tparams = tparams;
1531                 }
1532
1533                 #region Properties
1534
1535                 public TypeParameterSpec[] TypeParameters {
1536                         get {
1537                                 return tparams;
1538                         }
1539                 }
1540
1541                 public int TypeParametersCount {
1542                         get {
1543                                 return tparams.Length;
1544                         }
1545                 }
1546
1547                 #endregion
1548         }
1549
1550         class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition
1551         {
1552                 TypeParameterSpec[] tparams;
1553                 string name;
1554                 ReflectionMetaImporter meta_import;
1555
1556                 public ImportedTypeDefinition (ReflectionMetaImporter metaImport, Type type)
1557                         : base (type)
1558                 {
1559                         this.meta_import = metaImport;
1560                 }
1561
1562                 #region Properties
1563
1564                 public IAssemblyDefinition DeclaringAssembly {
1565                         get {
1566                                 return meta_import.GetAssemblyDefinition (provider.Module.Assembly);
1567                         }
1568                 }
1569
1570                 public override string Name {
1571                         get {
1572                                 if (name == null) {
1573                                         name = base.Name;
1574                                         if (tparams != null)
1575                                                 name = name.Substring (0, name.IndexOf ('`'));
1576                                 }
1577
1578                                 return name;
1579                         }
1580                 }
1581
1582                 public string Namespace {
1583                         get {
1584                                 return ((Type) provider).Namespace;
1585                         }
1586                 }
1587
1588                 public int TypeParametersCount {
1589                         get {
1590                                 return tparams == null ? 0 : tparams.Length;
1591                         }
1592                 }
1593
1594                 public TypeParameterSpec[] TypeParameters {
1595                         get {
1596                                 return tparams;
1597                         }
1598                         set {
1599                                 tparams = value;
1600                         }
1601                 }
1602
1603                 #endregion
1604
1605                 public TypeSpec GetAttributeCoClass ()
1606                 {
1607                         if (cattrs == null)
1608                                 ReadAttributes ();
1609
1610                         return cattrs.CoClass;
1611                 }
1612
1613                 public string GetAttributeDefaultMember ()
1614                 {
1615                         if (cattrs == null)
1616                                 ReadAttributes ();
1617
1618                         return cattrs.DefaultIndexerName;
1619                 }
1620
1621                 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1622                 {
1623                         if (cattrs == null)
1624                                 ReadAttributes ();
1625
1626                         return cattrs.AttributeUsage;
1627                 }
1628
1629                 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1630                 {
1631                         var a = meta_import.GetAssemblyDefinition (provider.Module.Assembly);
1632                         return a == assembly || a.IsFriendAssemblyTo (assembly);
1633                 }
1634
1635                 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1636                 {
1637                         //
1638                         // Not interested in members of nested private types unless the importer needs them
1639                         //
1640                         if (declaringType.IsPrivate && meta_import.IgnorePrivateMembers) {
1641                                 cache = MemberCache.Empty;
1642                                 return;
1643                         }
1644
1645                         var loading_type = (Type) provider;
1646                         const BindingFlags all_members = BindingFlags.DeclaredOnly |
1647                                 BindingFlags.Static | BindingFlags.Instance |
1648                                 BindingFlags.Public | BindingFlags.NonPublic;
1649
1650                         const MethodAttributes explicit_impl = MethodAttributes.NewSlot |
1651                                         MethodAttributes.Virtual | MethodAttributes.HideBySig |
1652                                         MethodAttributes.Final;
1653
1654                         Dictionary<MethodBase, MethodSpec> possible_accessors = null;
1655                         List<EventSpec> imported_events = null;
1656                         EventSpec event_spec;
1657                         MemberSpec imported;
1658                         MethodInfo m;
1659                         MemberInfo[] all;
1660                         try {
1661                                 all = loading_type.GetMembers (all_members);
1662                         } catch (Exception e) {
1663                                 throw new InternalErrorException (e, "Could not import type `{0}' from `{1}'",
1664                                         declaringType.GetSignatureForError (), declaringType.MemberDefinition.DeclaringAssembly.FullName);
1665                         }
1666
1667                         if (cache == null) {
1668                                 cache = new MemberCache (all.Length);
1669
1670                                 //
1671                                 // Do the types first as they can be referenced by the members before
1672                                 // they are found or inflated
1673                                 //
1674                                 foreach (var member in all) {
1675                                         if (member.MemberType != MemberTypes.NestedType)
1676                                                 continue;
1677
1678                                         Type t = (Type) member;
1679
1680                                         // Ignore compiler generated types, mostly lambda containers
1681                                         if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate)
1682                                                 continue;
1683
1684                                         imported = meta_import.CreateType (t, declaringType, t, 0, false);
1685                                         cache.AddMember (imported);
1686                                 }
1687
1688                                 foreach (var member in all) {
1689                                         if (member.MemberType != MemberTypes.NestedType)
1690                                                 continue;
1691
1692                                         Type t = (Type) member;
1693
1694                                         if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate)
1695                                                 continue;
1696
1697                                         meta_import.ImportTypeBase (t);
1698                                 }
1699                         }
1700
1701                         if (!onlyTypes) {
1702                                 //
1703                                 // The logic here requires methods to be returned first which seems to work for both Mono and .NET
1704                                 //
1705                                 foreach (var member in all) {
1706                                         switch (member.MemberType) {
1707                                         case MemberTypes.Constructor:
1708                                         case MemberTypes.Method:
1709                                                 MethodBase mb = (MethodBase) member;
1710                                                 var attrs = mb.Attributes;
1711
1712                                                 if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
1713                                                         if (meta_import.IgnorePrivateMembers)
1714                                                                 continue;
1715
1716                                                         // Ignore explicitly implemented members
1717                                                         if ((attrs & explicit_impl) == explicit_impl)
1718                                                                 continue;
1719
1720                                                         // Ignore compiler generated methods
1721                                                         if (meta_import.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), typeof (CompilerGeneratedAttribute)))
1722                                                                 continue;
1723                                                 }
1724
1725                                                 imported = meta_import.CreateMethod (mb, declaringType);
1726                                                 if (imported.Kind == MemberKind.Method && !imported.IsGeneric) {
1727                                                         if (possible_accessors == null)
1728                                                                 possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
1729
1730                                                         // There are no metadata rules for accessors, we have to consider any method as possible candidate
1731                                                         possible_accessors.Add (mb, (MethodSpec) imported);
1732                                                 }
1733
1734                                                 break;
1735                                         case MemberTypes.Property:
1736                                                 if (possible_accessors == null)
1737                                                         continue;
1738
1739                                                 var p = (PropertyInfo) member;
1740                                                 //
1741                                                 // Links possible accessors with property
1742                                                 //
1743                                                 MethodSpec get, set;
1744                                                 m = p.GetGetMethod (true);
1745                                                 if (m == null || !possible_accessors.TryGetValue (m, out get))
1746                                                         get = null;
1747
1748                                                 m = p.GetSetMethod (true);
1749                                                 if (m == null || !possible_accessors.TryGetValue (m, out set))
1750                                                         set = null;
1751
1752                                                 // No accessors registered (e.g. explicit implementation)
1753                                                 if (get == null && set == null)
1754                                                         continue;
1755
1756                                                 imported = meta_import.CreateProperty (p, declaringType, get, set);
1757                                                 if (imported == null)
1758                                                         continue;
1759
1760                                                 break;
1761                                         case MemberTypes.Event:
1762                                                 if (possible_accessors == null)
1763                                                         continue;
1764
1765                                                 var e = (EventInfo) member;
1766                                                 //
1767                                                 // Links accessors with event
1768                                                 //
1769                                                 MethodSpec add, remove;
1770                                                 m = e.GetAddMethod (true);
1771                                                 if (m == null || !possible_accessors.TryGetValue (m, out add))
1772                                                         add = null;
1773
1774                                                 m = e.GetRemoveMethod (true);
1775                                                 if (m == null || !possible_accessors.TryGetValue (m, out remove))
1776                                                         remove = null;
1777
1778                                                 // Both accessors are required
1779                                                 if (add == null || remove == null)
1780                                                         continue;
1781
1782                                                 event_spec = meta_import.CreateEvent (e, declaringType, add, remove);
1783                                                 if (!meta_import.IgnorePrivateMembers) {
1784                                                         if (imported_events == null)
1785                                                                 imported_events = new List<EventSpec> ();
1786
1787                                                         imported_events.Add (event_spec);
1788                                                 }
1789
1790                                                 imported = event_spec;
1791                                                 break;
1792                                         case MemberTypes.Field:
1793                                                 var fi = (FieldInfo) member;
1794
1795                                                 imported = meta_import.CreateField (fi, declaringType);
1796                                                 if (imported == null)
1797                                                         continue;
1798
1799                                                 //
1800                                                 // For dynamic binder event has to be fully restored to allow operations
1801                                                 // within the type container to work correctly
1802                                                 //
1803                                                 if (imported_events != null) {
1804                                                         // The backing event field should be private but it may not
1805                                                         int index = imported_events.FindIndex (l => l.Name == fi.Name);
1806                                                         if (index >= 0) {
1807                                                                 event_spec = imported_events[index];
1808                                                                 event_spec.BackingField = (FieldSpec) imported;
1809                                                                 imported_events.RemoveAt (index);
1810                                                                 continue;
1811                                                         }
1812                                                 }
1813
1814                                                 break;
1815                                         case MemberTypes.NestedType:
1816                                                 // Already in the cache from the first pass
1817                                                 continue;
1818                                         default:
1819                                                 throw new NotImplementedException (member.ToString ());
1820                                         }
1821
1822                                         cache.AddMember (imported);
1823                                 }
1824                         }
1825
1826                         if (declaringType.IsInterface && declaringType.Interfaces != null) {
1827                                 foreach (var iface in declaringType.Interfaces) {
1828                                         cache.AddInterface (iface);
1829                                 }
1830                         }
1831                 }
1832
1833                 protected override void ReadAttributes ()
1834                 {
1835                         cattrs = AttributesBag.Read (provider, meta_import);
1836                 }
1837         }
1838
1839         class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition
1840         {
1841                 public ImportedTypeParameterDefinition (Type type)
1842                         : base (type)
1843                 {
1844                 }
1845
1846                 #region Properties
1847
1848                 public IAssemblyDefinition DeclaringAssembly {
1849                         get {
1850                                 throw new NotImplementedException ();
1851                         }
1852                 }
1853
1854                 public string Namespace {
1855                         get {
1856                                 return null;
1857                         }
1858                 }
1859
1860                 public int TypeParametersCount {
1861                         get {
1862                                 return 0;
1863                         }
1864                 }
1865
1866                 public TypeParameterSpec[] TypeParameters {
1867                         get {
1868                                 return null;
1869                         }
1870                 }
1871
1872                 #endregion
1873
1874                 public TypeSpec GetAttributeCoClass ()
1875                 {
1876                         return null;
1877                 }
1878
1879                 public string GetAttributeDefaultMember ()
1880                 {
1881                         throw new NotSupportedException ();
1882                 }
1883
1884                 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1885                 {
1886                         throw new NotSupportedException ();
1887                 }
1888
1889                 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1890                 {
1891                         throw new NotImplementedException ();
1892                 }
1893
1894                 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1895                 {
1896                         throw new NotImplementedException ();
1897                 }
1898         }
1899 }