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