2 // import.cs: System.Reflection conversions
4 // Authors: Marek Safar (marek.safar@gmail.com)
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 // Copyright 2009, 2010 Novell, Inc
12 using System.Reflection;
13 using System.Runtime.CompilerServices;
20 public static FieldSpec CreateField (FieldInfo fi)
22 // TODO MemberCache: remove
23 var cs = TypeManager.GetConstant (fi);
26 var fb = TypeManager.GetFieldCore (fi);
32 var fa = fi.Attributes;
33 switch (fa & FieldAttributes.FieldAccessMask) {
34 case FieldAttributes.Public:
35 mod = Modifiers.PUBLIC;
37 case FieldAttributes.Assembly:
38 mod = Modifiers.INTERNAL;
40 case FieldAttributes.Family:
41 mod = Modifiers.PROTECTED;
43 case FieldAttributes.FamORAssem:
44 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
47 mod = Modifiers.PRIVATE;
51 // TODO MemberCache: Remove completely and use only Imported
52 IMemberDefinition definition;
53 var gfd = TypeManager.GetGenericFieldDefinition (fi);
54 fb = TypeManager.GetFieldCore (gfd);
58 cs = TypeManager.GetConstant (gfd);
60 definition = cs.MemberDefinition;
62 definition = new ImportedMemberDefinition (fi);
65 if ((fa & FieldAttributes.Literal) != 0) {
67 if (gfd is System.Reflection.Emit.FieldBuilder) {
68 // TODO: Remove after MemberCache
69 c = TypeManager.GetConstant (gfd).Value;
71 c = Constant.CreateConstantFromValue (fi.FieldType, gfd.GetValue (gfd), Location.Null);
74 return new ConstSpec (definition, fi, mod, c);
77 if ((fa & FieldAttributes.InitOnly) != 0) {
78 if (fi.FieldType == TypeManager.decimal_type) {
79 var dc = ReadDecimalConstant (gfd);
81 return new ConstSpec (definition, fi, mod, dc);
84 mod |= Modifiers.READONLY;
87 if ((fa & FieldAttributes.Static) != 0)
88 mod |= Modifiers.STATIC;
90 if (!TypeManager.IsReferenceType (fi.FieldType)) {
91 PredefinedAttribute pa = PredefinedAttributes.Get.FixedBuffer;
93 if (gfd is System.Reflection.Emit.FieldBuilder) {
94 // TODO: Remove this after MemberCache fix
95 } else if (gfd.IsDefined (pa.Type, false)) {
96 var element_field = fi.FieldType.GetField (FixedField.FixedElementName);
97 return new FixedFieldSpec (definition, fi, element_field, mod);
104 return new FieldSpec (definition, fi, mod);
107 public static EventSpec CreateEvent (EventInfo ei)
109 // TODO MemberCache: Remove
110 var ef = TypeManager.GetEventField (ei);
114 var add_accessor = CreateMethod (TypeManager.GetAddMethod (ei));
115 var remove_accessor = CreateMethod (TypeManager.GetRemoveMethod (ei));
117 if (add_accessor.Modifiers != remove_accessor.Modifiers)
118 throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
120 var definition = new ImportedMemberDefinition (ei);
121 return new EventSpec (definition, ei, add_accessor.Modifiers, add_accessor, remove_accessor) {
122 EventType = ei.EventHandlerType
126 public static MethodSpec CreateMethod (MethodBase mb)
128 // TODO MemberCache: Remove
129 MethodCore mc = TypeManager.GetMethod (mb) as MethodCore;
134 var ma = mb.Attributes;
135 switch (ma & MethodAttributes.MemberAccessMask) {
136 case MethodAttributes.Public:
137 mod = Modifiers.PUBLIC;
139 case MethodAttributes.Assembly:
140 mod = Modifiers.INTERNAL;
142 case MethodAttributes.Family:
143 mod = Modifiers.PROTECTED;
145 case MethodAttributes.FamORAssem:
146 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
149 mod = Modifiers.PRIVATE;
153 if ((ma & MethodAttributes.Static) != 0)
154 mod |= Modifiers.STATIC;
155 if ((ma & MethodAttributes.Virtual) != 0)
156 mod |= Modifiers.VIRTUAL;
157 if ((ma & MethodAttributes.Abstract) != 0)
158 mod |= Modifiers.ABSTRACT;
159 if ((ma & MethodAttributes.Final) != 0)
160 mod |= Modifiers.SEALED;
162 IMemberDefinition definition;
163 var gmd = mb as MethodInfo;
164 if (gmd != null && gmd.IsGenericMethodDefinition) {
165 definition = new ImportedGenericMethodDefinition (gmd);
166 } else if (mb.IsGenericMethod) { // TODO MemberCache: Remove me
167 definition = new ImportedGenericMethodDefinition ((MethodInfo) TypeManager.DropGenericMethodArguments (mb));
169 definition = new ImportedMemberDefinition (mb);
172 // TODO MemberCache: Use AParametersCollection p = ParametersImported.Create (mb);
173 AParametersCollection p = TypeManager.GetParameterData (mb);
176 if (mb.IsConstructor) {
177 kind = MemberKind.Constructor;
180 // Detect operators and destructors
182 string name = mb.Name;
183 kind = MemberKind.Method;
184 if (!mb.DeclaringType.IsInterface && name.Length > 6) {
185 if ((mod & Modifiers.STATIC) != 0 && name[2] == '_' && name[1] == 'p' && name[0] == 'o') {
186 var op_type = Operator.GetType (name);
187 if (op_type.HasValue) {
188 kind = MemberKind.Operator;
190 } else if (p.IsEmpty && (mod & Modifiers.STATIC) == 0 && name == Destructor.MetadataName) {
191 kind = MemberKind.Destructor;
196 MethodSpec ms = new MethodSpec (kind, definition, mb, p, mod);
200 public static PropertySpec CreateProperty (PropertyInfo pi)
202 var definition = new ImportedMemberDefinition (pi);
203 var mod = Modifiers.PRIVATE; // TODO: modifiers
204 return new PropertySpec (MemberKind.Property | MemberKind.Indexer, definition, pi, mod);
207 static TypeSpec CreateType (Type type)
210 var ma = type.Attributes;
211 switch (ma & TypeAttributes.VisibilityMask) {
212 case TypeAttributes.Public:
213 case TypeAttributes.NestedPublic:
214 mod = Modifiers.PUBLIC;
216 case TypeAttributes.NestedPrivate:
217 mod = Modifiers.PRIVATE;
219 case TypeAttributes.NestedFamily:
220 mod = Modifiers.PROTECTED;
222 case TypeAttributes.NestedFamORAssem:
223 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
226 mod = Modifiers.INTERNAL;
230 var type_def = TypeManager.DropGenericTypeArguments (type);
233 if (type_def.IsInterface)
234 kind = MemberKind.Interface;
235 else if (type_def.IsEnum)
236 kind = MemberKind.Enum;
237 else if (type_def.IsClass) {
238 if (type_def.BaseType == TypeManager.multicast_delegate_type)
239 kind = MemberKind.Delegate;
241 kind = MemberKind.Class;
243 kind = MemberKind.Struct;
246 if (type.IsGenericType) {
247 throw new NotImplementedException ();
250 var definition = new ImportedTypeDefinition (type_def);
251 var spec = new TypeSpec (kind, definition, type, type.Name, mod);
253 // TODO: BaseType for class only?
258 public static TypeSpec ImportType (Type type)
260 if (type.IsDefined (typeof (CompilerGeneratedAttribute), false))
263 return CreateType (type);
267 // Decimal constants cannot be encoded in the constant blob, and thus are marked
268 // as IsInitOnly ('readonly' in C# parlance). We get its value from the
269 // DecimalConstantAttribute metadata.
271 static Constant ReadDecimalConstant (FieldInfo fi)
273 PredefinedAttribute pa = PredefinedAttributes.Get.DecimalConstant;
277 object[] attrs = fi.GetCustomAttributes (pa.Type, false);
278 if (attrs.Length != 1)
281 return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null);
285 class ImportedMemberDefinition : IMemberDefinition
287 protected readonly ICustomAttributeProvider provider;
289 public ImportedMemberDefinition (ICustomAttributeProvider provider)
291 this.provider = provider;
294 public ObsoleteAttribute GetObsoleteAttribute ()
296 var res = provider.GetCustomAttributes (typeof (ObsoleteAttribute), false);
297 if (res == null || res.Length < 1)
300 return res [0] as ObsoleteAttribute;
303 public void SetIsUsed ()
305 // Unused for imported members
309 class ImportedGenericMethodDefinition : ImportedMemberDefinition, IGenericMethodDefinition
311 public ImportedGenericMethodDefinition (MethodInfo provider)
316 public MethodInfo MakeGenericMethod (Type[] targs)
318 return ((MethodInfo) provider).MakeGenericMethod (targs);
322 class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition
324 public ImportedTypeDefinition (Type type)
329 public void LoadMembers (MemberCache cache)
331 throw new NotImplementedException ();