2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / import.cs
blob8c74402d8d59496a2ddb8104bab8216bc25aaf14
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;
16 namespace Mono.CSharp
18 static class Import
20 public static FieldSpec CreateField (FieldInfo fi)
22 // TODO MemberCache: remove
23 var cs = TypeManager.GetConstant (fi);
24 if (cs != null)
25 return cs;
26 var fb = TypeManager.GetFieldCore (fi);
27 if (fb != null)
28 return fb.Spec;
29 // End
31 Modifiers mod = 0;
32 var fa = fi.Attributes;
33 switch (fa & FieldAttributes.FieldAccessMask) {
34 case FieldAttributes.Public:
35 mod = Modifiers.PUBLIC;
36 break;
37 case FieldAttributes.Assembly:
38 mod = Modifiers.INTERNAL;
39 break;
40 case FieldAttributes.Family:
41 mod = Modifiers.PROTECTED;
42 break;
43 case FieldAttributes.FamORAssem:
44 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
45 break;
46 default:
47 mod = Modifiers.PRIVATE;
48 break;
51 // TODO MemberCache: Remove completely and use only Imported
52 IMemberDefinition definition;
53 var gfd = TypeManager.GetGenericFieldDefinition (fi);
54 fb = TypeManager.GetFieldCore (gfd);
55 if (fb != null) {
56 definition = fb;
57 } else {
58 cs = TypeManager.GetConstant (gfd);
59 if (cs != null)
60 definition = cs.MemberDefinition;
61 else
62 definition = new ImportedMemberDefinition (fi);
65 if ((fa & FieldAttributes.Literal) != 0) {
66 Expression c;
67 if (gfd is System.Reflection.Emit.FieldBuilder) {
68 // TODO: Remove after MemberCache
69 c = TypeManager.GetConstant (gfd).Value;
70 } else {
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);
80 if (dc != null)
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;
92 if (pa.IsDefined) {
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);
102 // TODO: volatile
104 return new FieldSpec (definition, fi, mod);
107 public static EventSpec CreateEvent (EventInfo ei)
109 // TODO MemberCache: Remove
110 var ef = TypeManager.GetEventField (ei);
111 if (ef != null)
112 return ef;
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;
130 if (mc != null)
131 return mc.Spec;
133 Modifiers mod = 0;
134 var ma = mb.Attributes;
135 switch (ma & MethodAttributes.MemberAccessMask) {
136 case MethodAttributes.Public:
137 mod = Modifiers.PUBLIC;
138 break;
139 case MethodAttributes.Assembly:
140 mod = Modifiers.INTERNAL;
141 break;
142 case MethodAttributes.Family:
143 mod = Modifiers.PROTECTED;
144 break;
145 case MethodAttributes.FamORAssem:
146 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
147 break;
148 default:
149 mod = Modifiers.PRIVATE;
150 break;
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));
168 } else {
169 definition = new ImportedMemberDefinition (mb);
172 // TODO MemberCache: Use AParametersCollection p = ParametersImported.Create (mb);
173 AParametersCollection p = TypeManager.GetParameterData (mb);
175 MemberKind kind;
176 if (mb.IsConstructor) {
177 kind = MemberKind.Constructor;
178 } else {
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);
197 return ms;
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)
209 Modifiers mod = 0;
210 var ma = type.Attributes;
211 switch (ma & TypeAttributes.VisibilityMask) {
212 case TypeAttributes.Public:
213 case TypeAttributes.NestedPublic:
214 mod = Modifiers.PUBLIC;
215 break;
216 case TypeAttributes.NestedPrivate:
217 mod = Modifiers.PRIVATE;
218 break;
219 case TypeAttributes.NestedFamily:
220 mod = Modifiers.PROTECTED;
221 break;
222 case TypeAttributes.NestedFamORAssem:
223 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
224 break;
225 default:
226 mod = Modifiers.INTERNAL;
227 break;
230 var type_def = TypeManager.DropGenericTypeArguments (type);
232 MemberKind kind;
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;
240 else
241 kind = MemberKind.Class;
242 } else {
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?
255 return spec;
258 public static TypeSpec ImportType (Type type)
260 if (type.IsDefined (typeof (CompilerGeneratedAttribute), false))
261 return null;
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;
274 if (!pa.IsDefined)
275 return null;
277 object[] attrs = fi.GetCustomAttributes (pa.Type, false);
278 if (attrs.Length != 1)
279 return null;
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)
298 return null;
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)
312 : base (provider)
316 public MethodInfo MakeGenericMethod (Type[] targs)
318 return ((MethodInfo) provider).MakeGenericMethod (targs);
322 class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition
324 public ImportedTypeDefinition (Type type)
325 : base (type)
329 public void LoadMembers (MemberCache cache)
331 throw new NotImplementedException ();