add SafeSerializationEventArgs
[mcs.git] / mcs / import.cs
blob900144ac91d500c3a2d9437e27877a2867fa4874
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 //
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;
19 namespace Mono.CSharp
21 public static class Import
23 static Dictionary<Type, TypeSpec> import_cache;
24 static Dictionary<Type, PredefinedTypeSpec> type_2_predefined;
26 public static void Initialize ()
28 import_cache = new Dictionary<Type, TypeSpec> (1024, ReferenceEquality<Type>.Default);
30 // Setup mapping for predefined types
31 type_2_predefined = new Dictionary<Type, PredefinedTypeSpec> () {
32 { typeof (object), TypeManager.object_type },
33 { typeof (System.ValueType), TypeManager.value_type },
34 { typeof (System.Attribute), TypeManager.attribute_type },
36 { typeof (int), TypeManager.int32_type },
37 { typeof (long), TypeManager.int64_type },
38 { typeof (uint), TypeManager.uint32_type },
39 { typeof (ulong), TypeManager.uint64_type },
40 { typeof (byte), TypeManager.byte_type },
41 { typeof (sbyte), TypeManager.sbyte_type },
42 { typeof (short), TypeManager.short_type },
43 { typeof (ushort), TypeManager.ushort_type },
45 { typeof (System.Collections.IEnumerator), TypeManager.ienumerator_type },
46 { typeof (System.Collections.IEnumerable), TypeManager.ienumerable_type },
47 { typeof (System.IDisposable), TypeManager.idisposable_type },
49 { typeof (char), TypeManager.char_type },
50 { typeof (string), TypeManager.string_type },
51 { typeof (float), TypeManager.float_type },
52 { typeof (double), TypeManager.double_type },
53 { typeof (decimal), TypeManager.decimal_type },
54 { typeof (bool), TypeManager.bool_type },
55 { typeof (System.IntPtr), TypeManager.intptr_type },
56 { typeof (System.UIntPtr), TypeManager.uintptr_type },
58 { typeof (System.MulticastDelegate), TypeManager.multicast_delegate_type },
59 { typeof (System.Delegate), TypeManager.delegate_type },
60 { typeof (System.Enum), TypeManager.enum_type },
61 { typeof (System.Array), TypeManager.array_type },
62 { typeof (void), TypeManager.void_type },
63 { typeof (System.Type), TypeManager.type_type },
64 { typeof (System.Exception), TypeManager.exception_type },
65 { typeof (System.RuntimeFieldHandle), TypeManager.runtime_field_handle_type },
66 { typeof (System.RuntimeTypeHandle), TypeManager.runtime_handle_type }
70 public static FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
72 Modifiers mod = 0;
73 var fa = fi.Attributes;
74 switch (fa & FieldAttributes.FieldAccessMask) {
75 case FieldAttributes.Public:
76 mod = Modifiers.PUBLIC;
77 break;
78 case FieldAttributes.Assembly:
79 mod = Modifiers.INTERNAL;
80 break;
81 case FieldAttributes.Family:
82 mod = Modifiers.PROTECTED;
83 break;
84 case FieldAttributes.FamORAssem:
85 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
86 break;
87 default:
88 mod = Modifiers.PRIVATE;
89 break;
92 // Ignore private fields (even for error reporting) to not require extra dependencies
93 if (mod == Modifiers.PRIVATE)
94 return null;
96 var definition = new ImportedMemberDefinition (fi);
98 if ((fa & FieldAttributes.Literal) != 0) {
99 var c = Constant.CreateConstantFromValue (ImportType (fi.FieldType), fi.GetValue (fi), Location.Null);
100 return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, c);
103 if ((fa & FieldAttributes.InitOnly) != 0) {
104 if (fi.FieldType == typeof (decimal)) {
105 var dc = ReadDecimalConstant (fi);
106 if (dc != null)
107 return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, dc);
110 mod |= Modifiers.READONLY;
111 } else {
112 var reqs = fi.GetRequiredCustomModifiers ();
113 if (reqs.Length > 0) {
114 foreach (Type t in reqs) {
115 if (t == typeof (System.Runtime.CompilerServices.IsVolatile)) {
116 mod |= Modifiers.VOLATILE;
117 break;
123 if ((fa & FieldAttributes.Static) != 0)
124 mod |= Modifiers.STATIC;
126 if (fi.FieldType.IsValueType) {
127 if (fi.IsDefined (typeof (FixedBufferAttribute), false)) {
128 var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType);
129 return new FixedFieldSpec (declaringType, definition, fi, element_field, mod);
133 return new FieldSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod);
136 public static EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
138 add.IsAccessor = true;
139 remove.IsAccessor = true;
141 if (add.Modifiers != remove.Modifiers)
142 throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
144 var definition = new ImportedMemberDefinition (ei);
145 return new EventSpec (declaringType, definition, ImportType (ei.EventHandlerType), add.Modifiers, add, remove);
148 static T[] CreateGenericParameters<T> (Type type, TypeSpec declaringType) where T : TypeSpec
150 Type[] tparams = type.GetGenericArguments ();
152 int parent_owned_count;
153 if (type.IsNested) {
154 parent_owned_count = type.DeclaringType.GetGenericArguments ().Length;
157 // System.Reflection duplicates parent type parameters for each
158 // nested type with slightly modified properties (eg. different owner)
159 // This just makes things more complicated (think of cloned constraints)
160 // therefore we remap any nested type owned by parent using `type_cache'
161 // to the single TypeParameterSpec
163 if (declaringType != null && parent_owned_count > 0) {
164 int read_count = 0;
165 while (read_count != parent_owned_count) {
166 var tparams_count = declaringType.Arity;
167 if (tparams_count != 0) {
168 var parent_tp = declaringType.MemberDefinition.TypeParameters;
169 read_count += tparams_count;
170 for (int i = 0; i < tparams_count; i++) {
171 import_cache.Add (tparams[parent_owned_count - read_count + i], parent_tp[i]);
175 declaringType = declaringType.DeclaringType;
178 } else {
179 parent_owned_count = 0;
182 if (tparams.Length - parent_owned_count == 0)
183 return null;
185 return CreateGenericParameters<T> (parent_owned_count, tparams);
188 static T[] CreateGenericParameters<T> (int first, Type[] tparams) where T : TypeSpec
190 var tspec = new T [tparams.Length - first];
191 for (int pos = first; pos < tparams.Length; ++pos) {
192 var type = tparams[pos];
193 if (type.HasElementType) {
194 var element = type.GetElementType ();
195 var spec = CreateType (element);
197 if (type.IsArray) {
198 tspec[pos - first] = (T) (TypeSpec) ArrayContainer.MakeType (spec, type.GetArrayRank ());
199 continue;
202 throw new NotImplementedException ("Unknown element type " + type.ToString ());
205 tspec [pos - first] = (T) CreateType (type);
208 return tspec;
211 public static MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
213 Modifiers mod = ReadMethodModifiers (mb, declaringType);
214 //if (declaringType.IsInterface) {
215 // mod = (mod & ~Modifiers.ABSTRACT) | Modifiers.VIRTUAL;
218 bool is_generic;
219 ImportedMethodDefinition definition;
221 var parameters = ParametersImported.Create (declaringType, mb);
223 if (mb.IsGenericMethod) {
224 if (!mb.IsGenericMethodDefinition)
225 throw new NotSupportedException ("assert");
227 var tparams = CreateGenericParameters<TypeParameterSpec>(0, mb.GetGenericArguments ());
228 definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams);
229 is_generic = true;
230 } else {
231 definition = new ImportedMethodDefinition (mb, parameters);
232 is_generic = false;
235 MemberKind kind;
236 TypeSpec returnType;
237 if (mb.MemberType == MemberTypes.Constructor) {
238 kind = MemberKind.Constructor;
239 returnType = TypeManager.void_type;
240 } else {
242 // Detect operators and destructors
244 string name = mb.Name;
245 kind = MemberKind.Method;
246 if (!mb.DeclaringType.IsInterface && name.Length > 6) {
247 if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) {
248 if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') {
249 var op_type = Operator.GetType (name);
250 if (op_type.HasValue) {
251 kind = MemberKind.Operator;
254 } else if (parameters.IsEmpty && name == Destructor.MetadataName) {
255 kind = MemberKind.Destructor;
259 returnType = ImportType (((MethodInfo)mb).ReturnType);
262 MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod);
263 if (is_generic)
264 ms.IsGeneric = true;
266 return ms;
270 // Returns null when the property is not valid C# property
272 public static PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
274 var definition = new ImportedMemberDefinition (pi);
276 Modifiers mod = 0;
277 AParametersCollection param = null;
278 TypeSpec type = null;
279 if (get != null) {
280 mod = get.Modifiers;
281 param = get.Parameters;
282 type = get.ReturnType;
285 bool is_valid_property = true;
286 if (set != null) {
287 if (set.ReturnType != TypeManager.void_type)
288 is_valid_property = false;
290 var set_param_count = set.Parameters.Count - 1;
291 if (set_param_count < 0)
292 is_valid_property = false;
294 var data = new IParameterData [set_param_count];
295 var types = new TypeSpec[set_param_count];
296 for (int i = 0; i < set_param_count; ++i ) {
297 data[i] = set.Parameters.FixedParameters[i];
298 types[i] = set.Parameters.Types[i];
301 var set_param = new ParametersImported (data, types);
302 var set_type = set.Parameters.Types[set_param_count];
304 if (mod == 0) {
305 mod = set.Modifiers;
306 param = set_param;
307 type = set_type;
308 } else {
309 if (set_param_count != get.Parameters.Count)
310 is_valid_property = false;
312 if (get.ReturnType != set_type)
313 is_valid_property = false;
315 // Possible custom accessor modifiers
316 if ((mod & ~Modifiers.AccessibilityMask) != (set.Modifiers & ~Modifiers.AccessibilityMask)) {
317 var get_acc = mod & Modifiers.AccessibilityMask;
318 if (get_acc != Modifiers.PUBLIC) {
319 var set_acc = set.Modifiers & Modifiers.AccessibilityMask;
320 // If the accessor modifiers are not same, do extra restriction checks
321 if (get_acc != set_acc) {
322 var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc);
323 var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc);
324 if (get_restr && set_restr) {
325 is_valid_property = false; // Neither is more restrictive
328 if (set_restr) {
329 mod &= ~Modifiers.AccessibilityMask;
330 mod |= set_acc;
338 PropertySpec spec = null;
339 if (!param.IsEmpty) {
340 var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
341 if (index_name == null) {
342 is_valid_property = false;
343 } else {
344 if (get != null) {
345 if (get.IsStatic)
346 is_valid_property = false;
347 if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
348 is_valid_property = false;
350 if (set != null) {
351 if (set.IsStatic)
352 is_valid_property = false;
353 if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
354 is_valid_property = false;
358 if (is_valid_property)
359 spec = new IndexerSpec (declaringType, definition, type, param, pi, mod);
362 if (spec == null)
363 spec = new PropertySpec (MemberKind.Property, declaringType, definition, type, pi, mod);
365 if (!is_valid_property) {
366 spec.IsNotRealProperty = true;
367 return spec;
370 if (set != null)
371 spec.Set = set;
372 if (get != null)
373 spec.Get = get;
375 return spec;
378 public static TypeSpec CreateType (Type type)
380 return CreateType (type, null);
383 public static TypeSpec CreateType (Type type, TypeSpec declaringType)
385 TypeSpec spec;
386 if (import_cache.TryGetValue (type, out spec))
387 return spec;
389 if (type.IsGenericType && !type.IsGenericTypeDefinition) {
390 var type_def = type.GetGenericTypeDefinition ();
391 spec = CreateType (type_def, declaringType);
393 var targs = CreateGenericParameters<TypeSpec> (type, null);
395 InflatedTypeSpec inflated;
396 if (targs == null) {
397 // Inflating nested non-generic type, same in TypeSpec::InflateMember
398 inflated = new InflatedTypeSpec (spec, declaringType, TypeSpec.EmptyTypes);
399 } else {
400 // CreateGenericParameters constraint could inflate type
401 if (import_cache.ContainsKey (type))
402 return import_cache[type];
404 inflated = spec.MakeGenericType (targs);
406 // Use of reading cache to speed up reading only
407 import_cache.Add (type, inflated);
410 return inflated;
413 Modifiers mod;
414 MemberKind kind;
416 var ma = type.Attributes;
417 switch (ma & TypeAttributes.VisibilityMask) {
418 case TypeAttributes.Public:
419 case TypeAttributes.NestedPublic:
420 mod = Modifiers.PUBLIC;
421 break;
422 case TypeAttributes.NestedPrivate:
423 mod = Modifiers.PRIVATE;
424 break;
425 case TypeAttributes.NestedFamily:
426 mod = Modifiers.PROTECTED;
427 break;
428 case TypeAttributes.NestedFamORAssem:
429 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
430 break;
431 default:
432 mod = Modifiers.INTERNAL;
433 break;
436 if ((ma & TypeAttributes.Interface) != 0) {
437 kind = MemberKind.Interface;
438 } else if (type.IsGenericParameter) {
439 kind = MemberKind.TypeParameter;
440 } else if (type.IsClass || type.IsAbstract) { // SRE: System.Enum returns false for IsClass
441 if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) {
442 kind = MemberKind.Delegate;
443 } else {
444 kind = MemberKind.Class;
446 if (type == typeof (object)) {
447 #if NET_4_0
448 var pa = PredefinedAttributes.Get.Dynamic.Type;
449 if (pa != null && type.IsDefined (typeof (DynamicAttribute), false))
450 return InternalType.Dynamic;
451 #endif
454 if ((ma & TypeAttributes.Sealed) != 0) {
455 mod |= Modifiers.SEALED;
456 if ((ma & TypeAttributes.Abstract) != 0)
457 mod |= Modifiers.STATIC;
458 } else if ((ma & TypeAttributes.Abstract) != 0) {
459 mod |= Modifiers.ABSTRACT;
462 } else if (type.IsEnum) {
463 kind = MemberKind.Enum;
464 } else {
465 kind = MemberKind.Struct;
466 mod |= Modifiers.SEALED;
469 var definition = new ImportedTypeDefinition (type);
470 PredefinedTypeSpec pt;
472 if (kind == MemberKind.Enum) {
473 const BindingFlags underlying_member = BindingFlags.DeclaredOnly |
474 BindingFlags.Instance |
475 BindingFlags.Public | BindingFlags.NonPublic;
477 var type_members = type.GetFields (underlying_member);
478 foreach (var type_member in type_members) {
479 spec = new EnumSpec (declaringType, definition, Import.CreateType (type_member.FieldType), type, mod);
480 break;
483 if (spec == null)
484 kind = MemberKind.Class;
486 } else if (kind == MemberKind.TypeParameter) {
487 // Return as type_cache was updated
488 return CreateTypeParameter (type, declaringType);
489 } else if (type.IsGenericTypeDefinition) {
490 definition.TypeParameters = CreateGenericParameters<TypeParameterSpec>(type, declaringType);
492 // Constraints are not loaded on demand and can reference this type
493 if (import_cache.TryGetValue (type, out spec))
494 return spec;
496 } else if (type_2_predefined.TryGetValue (type, out pt)) {
497 spec = pt;
498 pt.SetDefinition (definition, type);
501 if (spec == null)
502 spec = new TypeSpec (kind, declaringType, definition, type, mod);
504 import_cache.Add (type, spec);
506 if (kind == MemberKind.Interface)
507 spec.BaseType = TypeManager.object_type;
508 else if (type.BaseType != null)
509 spec.BaseType = CreateType (type.BaseType);
511 var ifaces = type.GetInterfaces ();
512 if (ifaces.Length > 0) {
513 foreach (Type iface in ifaces) {
514 spec.AddInterface (Import.CreateType (iface));
518 return spec;
521 static TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType)
523 Variance variance;
524 switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
525 case GenericParameterAttributes.Covariant:
526 variance = Variance.Covariant;
527 break;
528 case GenericParameterAttributes.Contravariant:
529 variance = Variance.Contravariant;
530 break;
531 default:
532 variance = Variance.None;
533 break;
536 SpecialConstraint special = SpecialConstraint.None;
537 var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
539 if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) {
540 special |= SpecialConstraint.Struct;
541 } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) {
542 special = SpecialConstraint.Constructor;
545 if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) {
546 special |= SpecialConstraint.Class;
549 TypeParameterSpec spec;
550 var def = new ImportedTypeParameterDefinition (type);
551 if (type.DeclaringMethod != null)
552 spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type);
553 else
554 spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type);
556 // Add it now, so any constraint can reference it and get same instance
557 import_cache.Add (type, spec);
559 var constraints = type.GetGenericParameterConstraints ();
560 foreach (var ct in constraints) {
561 // TODO MemberCache: What to do ??
562 if (ct.IsGenericParameter) {
563 continue;
566 if (ct.IsClass) {
567 if (ct == typeof (ValueType)) {
568 spec.BaseType = TypeManager.value_type;
569 } else {
570 spec.BaseType = CreateType (ct);
573 continue;
576 spec.AddInterface (CreateType (ct));
579 if (spec.BaseType == null)
580 spec.BaseType = TypeManager.object_type;
582 return spec;
585 public static TypeSpec ImportType (Type type)
587 if (type.HasElementType) {
588 var element = type.GetElementType ();
589 var spec = ImportType (element);
591 if (type.IsArray)
592 return ArrayContainer.MakeType (spec, type.GetArrayRank ());
593 if (type.IsByRef)
594 return ReferenceContainer.MakeType (spec);
595 if (type.IsPointer)
596 return PointerContainer.MakeType (spec);
598 throw new NotImplementedException ("Unknown element type " + type.ToString ());
601 TypeSpec dtype;
602 if (type.IsNested)
603 dtype = ImportType (type.DeclaringType);
604 else
605 dtype = null;
607 return CreateType (type, dtype);
611 // Decimal constants cannot be encoded in the constant blob, and thus are marked
612 // as IsInitOnly ('readonly' in C# parlance). We get its value from the
613 // DecimalConstantAttribute metadata.
615 static Constant ReadDecimalConstant (FieldInfo fi)
617 object[] attrs = fi.GetCustomAttributes (typeof (DecimalConstantAttribute), false);
618 if (attrs.Length != 1)
619 return null;
621 return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null);
624 static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType)
626 Modifiers mod;
627 var ma = mb.Attributes;
628 switch (ma & MethodAttributes.MemberAccessMask) {
629 case MethodAttributes.Public:
630 mod = Modifiers.PUBLIC;
631 break;
632 case MethodAttributes.Assembly:
633 mod = Modifiers.INTERNAL;
634 break;
635 case MethodAttributes.Family:
636 mod = Modifiers.PROTECTED;
637 break;
638 case MethodAttributes.FamORAssem:
639 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
640 break;
641 default:
642 mod = Modifiers.PRIVATE;
643 break;
646 if ((ma & MethodAttributes.Static) != 0) {
647 mod |= Modifiers.STATIC;
648 } else if ((ma & MethodAttributes.Final) != 0) {
649 mod |= Modifiers.SEALED;
650 } else if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) {
651 mod |= Modifiers.ABSTRACT;
654 // It can be sealed and override
655 if ((ma & MethodAttributes.Virtual) != 0) {
656 if ((ma & MethodAttributes.NewSlot) != 0 || !declaringType.IsClass || mod == Modifiers.PRIVATE) {
657 mod |= Modifiers.VIRTUAL;
658 } else {
659 // Cannot set to OVERRIDE without full hierarchy checks
660 // this flag indicates that the method could be override
661 // but further validation is needed
662 mod |= Modifiers.OVERRIDE_UNCHECKED;
666 return mod;
670 class ImportedMemberDefinition : IMemberDefinition
672 protected class AttributesBag
674 public static readonly AttributesBag Default = new AttributesBag ();
676 public AttributeUsageAttribute AttributeUsage;
677 public ObsoleteAttribute Obsolete;
678 public string[] Conditionals;
679 public string DefaultIndexerName;
680 public bool IsNotCLSCompliant;
682 public static AttributesBag Read (MemberInfo mi)
684 AttributesBag bag = null;
685 List<string> conditionals = null;
687 var attrs = CustomAttributeData.GetCustomAttributes (mi);
688 foreach (var a in attrs) {
689 var type = a.Constructor.DeclaringType;
690 if (type == typeof (ObsoleteAttribute)) {
691 if (bag == null)
692 bag = new AttributesBag ();
694 var args = a.ConstructorArguments;
696 if (args.Count == 1) {
697 bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value);
698 } else if (args.Count == 2) {
699 bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value);
700 } else {
701 bag.Obsolete = new ObsoleteAttribute ();
704 continue;
707 if (type == typeof (ConditionalAttribute)) {
708 if (bag == null)
709 bag = new AttributesBag ();
711 if (conditionals == null)
712 conditionals = new List<string> (2);
714 conditionals.Add ((string) a.ConstructorArguments[0].Value);
715 continue;
718 if (type == typeof (CLSCompliantAttribute)) {
719 if (bag == null)
720 bag = new AttributesBag ();
722 bag.IsNotCLSCompliant = !(bool) a.ConstructorArguments[0].Value;
723 continue;
726 // Type only attributes
727 if (type == typeof (DefaultMemberAttribute)) {
728 if (bag == null)
729 bag = new AttributesBag ();
731 bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value;
732 continue;
735 if (type == typeof (AttributeUsageAttribute)) {
736 if (bag == null)
737 bag = new AttributesBag ();
739 bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value);
740 foreach (var named in a.NamedArguments) {
741 if (named.MemberInfo.Name == "AllowMultiple")
742 bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value;
743 else if (named.MemberInfo.Name == "Inherited")
744 bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value;
746 continue;
750 if (bag == null)
751 return Default;
753 if (conditionals != null)
754 bag.Conditionals = conditionals.ToArray ();
756 return bag;
760 protected readonly MemberInfo provider;
761 protected AttributesBag cattrs;
763 public ImportedMemberDefinition (MemberInfo provider)
765 this.provider = provider;
768 #region Properties
770 public Assembly Assembly {
771 get {
772 return provider.Module.Assembly;
776 public bool IsImported {
777 get {
778 return true;
782 public virtual string Name {
783 get {
784 return provider.Name;
788 #endregion
790 public string[] ConditionalConditions ()
792 if (cattrs == null)
793 ReadAttributes ();
795 return cattrs.Conditionals;
798 public ObsoleteAttribute GetAttributeObsolete ()
800 if (cattrs == null)
801 ReadAttributes ();
803 return cattrs.Obsolete;
806 public bool IsNotCLSCompliant ()
808 if (cattrs == null)
809 ReadAttributes ();
811 return cattrs.IsNotCLSCompliant;
814 protected void ReadAttributes ()
816 cattrs = AttributesBag.Read (provider);
819 public void SetIsAssigned ()
821 // Unused for imported members
824 public void SetIsUsed ()
826 // Unused for imported members
830 class ImportedMethodDefinition : ImportedMemberDefinition, IParametersMember
832 readonly AParametersCollection parameters;
834 public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters)
835 : base (provider)
837 this.parameters = parameters;
840 #region Properties
842 public AParametersCollection Parameters {
843 get {
844 return parameters;
848 public TypeSpec MemberType {
849 get {
850 throw new NotImplementedException ();
854 #endregion
857 class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition
859 TypeParameterSpec[] tparams;
861 public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams)
862 : base (provider, parameters)
864 this.tparams = tparams;
867 #region Properties
869 public TypeParameterSpec[] TypeParameters {
870 get {
871 return tparams;
875 public int TypeParametersCount {
876 get {
877 return tparams.Length;
881 #endregion
884 class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition
886 TypeParameterSpec[] tparams;
887 string name;
889 public ImportedTypeDefinition (Type type)
890 : base (type)
894 #region Properties
896 public override string Name {
897 get {
898 if (name == null) {
899 name = base.Name;
900 if (tparams != null)
901 name = name.Substring (0, name.IndexOf ('`'));
904 return name;
908 public string Namespace {
909 get {
910 return ((Type) provider).Namespace;
914 public int TypeParametersCount {
915 get {
916 return tparams == null ? 0 : tparams.Length;
920 public TypeParameterSpec[] TypeParameters {
921 get {
922 return tparams;
924 set {
925 tparams = value;
929 #endregion
931 public TypeSpec GetAttributeCoClass ()
933 // TODO: Use ReadAttributes
934 var attr = provider.GetCustomAttributes (typeof (CoClassAttribute), false);
935 if (attr.Length < 1)
936 return null;
938 return Import.CreateType (((CoClassAttribute) attr[0]).CoClass);
941 public string GetAttributeDefaultMember ()
943 if (cattrs == null)
944 ReadAttributes ();
946 return cattrs.DefaultIndexerName;
949 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
951 if (cattrs == null)
952 ReadAttributes ();
954 return cattrs.AttributeUsage;
957 public MemberCache LoadMembers (TypeSpec declaringType)
959 var loading_type = (Type) provider;
960 const BindingFlags all_members = BindingFlags.DeclaredOnly |
961 BindingFlags.Static | BindingFlags.Instance |
962 BindingFlags.Public | BindingFlags.NonPublic;
964 const MethodAttributes explicit_impl = MethodAttributes.NewSlot |
965 MethodAttributes.Virtual | MethodAttributes.HideBySig |
966 MethodAttributes.Final;
968 Dictionary<MethodBase, MethodSpec> possible_accessors = null;
969 MemberSpec imported;
970 MethodInfo m;
971 List<string> fields_to_ignore = null;
974 // This requires methods to be returned first which seems to work for both Mono and .NET
976 var all = loading_type.GetMembers (all_members);
978 var cache = new MemberCache (all.Length);
979 foreach (var member in all) {
980 switch (member.MemberType) {
981 case MemberTypes.Constructor:
982 case MemberTypes.Method:
983 MethodBase mb = (MethodBase) member;
985 // Ignore explicitly implemented members
986 if ((mb.Attributes & explicit_impl) == explicit_impl && (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
987 continue;
989 // Ignore compiler generated methods
990 if (mb.IsPrivate && mb.IsDefined (typeof (CompilerGeneratedAttribute), false))
991 continue;
993 imported = Import.CreateMethod (mb, declaringType);
994 if (imported.Kind == MemberKind.Method) {
995 if (possible_accessors == null)
996 possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
998 // There are no metadata rules for accessors, we have to any method as possible candidate
999 possible_accessors.Add (mb, (MethodSpec) imported);
1002 break;
1003 case MemberTypes.Property:
1004 if (possible_accessors == null)
1005 continue;
1007 var p = (PropertyInfo) member;
1009 // Links possible accessors with property
1011 MethodSpec get, set;
1012 m = p.GetGetMethod (true);
1013 if (m == null || !possible_accessors.TryGetValue (m, out get))
1014 get = null;
1016 m = p.GetSetMethod (true);
1017 if (m == null || !possible_accessors.TryGetValue (m, out set))
1018 set = null;
1020 // No accessors registered (e.g. explicit implementation)
1021 if (get == null && set == null)
1022 continue;
1024 imported = Import.CreateProperty (p, declaringType, get, set);
1025 if (imported == null)
1026 continue;
1028 break;
1029 case MemberTypes.Event:
1030 if (possible_accessors == null)
1031 continue;
1033 var e = (EventInfo) member;
1035 // Links accessors with event
1037 MethodSpec add, remove;
1038 m = e.GetAddMethod (true);
1039 if (m == null || !possible_accessors.TryGetValue (m, out add))
1040 add = null;
1042 m = e.GetRemoveMethod (true);
1043 if (m == null || !possible_accessors.TryGetValue (m, out remove))
1044 remove = null;
1046 // Both accessors are required
1047 if (add == null || remove == null)
1048 continue;
1050 if (fields_to_ignore == null)
1051 fields_to_ignore = new List<string> ();
1053 fields_to_ignore.Add (e.Name);
1055 imported = Import.CreateEvent (e, declaringType, add, remove);
1056 break;
1057 case MemberTypes.Field:
1058 var fi = (FieldInfo) member;
1060 // Ignore compiler generated fields
1061 if (fi.IsPrivate && fi.IsDefined (typeof (CompilerGeneratedAttribute), false))
1062 continue;
1064 if (fields_to_ignore != null && fields_to_ignore.Contains (fi.Name))
1065 continue;
1067 imported = Import.CreateField (fi, declaringType);
1068 if (imported == null)
1069 continue;
1071 break;
1072 case MemberTypes.NestedType:
1073 Type t = (Type) member;
1075 // Ignore compiler generated types, mostly lambda containers
1076 if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false))
1077 continue;
1079 imported = Import.CreateType (t, declaringType);
1080 break;
1081 default:
1082 throw new NotImplementedException (member.ToString ());
1085 cache.AddMember (imported);
1088 if (declaringType.IsInterface && declaringType.Interfaces != null) {
1089 foreach (var iface in declaringType.Interfaces) {
1090 cache.AddInterface (iface);
1094 return cache;
1098 class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition
1100 public ImportedTypeParameterDefinition (Type type)
1101 : base (type)
1105 #region Properties
1107 public string Namespace {
1108 get {
1109 return null;
1113 public int TypeParametersCount {
1114 get {
1115 return 0;
1119 public TypeParameterSpec[] TypeParameters {
1120 get {
1121 return null;
1125 #endregion
1127 public TypeSpec GetAttributeCoClass ()
1129 return null;
1132 public string GetAttributeDefaultMember ()
1134 throw new NotSupportedException ();
1137 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1139 throw new NotSupportedException ();
1142 public MemberCache LoadMembers (TypeSpec declaringType)
1144 throw new NotImplementedException ();