* Monodoc/provider.cs, Monodoc/ecma-provider.cs: Improve cache support
[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 Novell, Inc
9 //
10
11 using System;
12 using System.Reflection;
13 using System.Runtime.CompilerServices;
14 using System.Linq;
15
16 namespace Mono.CSharp
17 {
18         static class Import
19         {
20                 public static FieldSpec CreateField (FieldInfo fi)
21                 {
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
30
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;
49                         }
50
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);
63                         }
64
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);
72                                 }
73
74                                 return new ConstSpec (definition, fi, mod, c);
75                         }
76
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);
82                                 }
83
84                                 mod |= Modifiers.READONLY;
85                         }
86
87                         if ((fa & FieldAttributes.Static) != 0)
88                                 mod |= Modifiers.STATIC;
89
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);
98                                         }
99                                 }
100                         }
101
102                         // TODO: volatile
103
104                         return new FieldSpec (definition, fi, mod);
105                 }
106
107                 public static MethodSpec CreateMethod (MethodBase mb)
108                 {
109                         // TODO MemberCache: Remove
110                         MethodCore mc = TypeManager.GetMethod (mb) as MethodCore;
111                         if (mc != null)
112                                 return mc.Spec;
113
114                         Modifiers mod = 0;
115                         var ma = mb.Attributes;
116                         switch (ma & MethodAttributes.MemberAccessMask) {
117                                 case MethodAttributes.Public:
118                                         mod = Modifiers.PUBLIC;
119                                         break;
120                                 case MethodAttributes.Assembly:
121                                         mod = Modifiers.INTERNAL;
122                                         break;
123                                 case MethodAttributes.Family:
124                                         mod = Modifiers.PROTECTED;
125                                         break;
126                                 case MethodAttributes.FamORAssem:
127                                         mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
128                                         break;
129                                 default:
130                                         mod = Modifiers.PRIVATE;
131                                         break;
132                         }
133
134                         if ((ma & MethodAttributes.Static) != 0)
135                                 mod |= Modifiers.STATIC;
136                         if ((ma & MethodAttributes.Virtual) != 0)
137                                 mod |= Modifiers.VIRTUAL;
138                         if ((ma & MethodAttributes.Abstract) != 0)
139                                 mod |= Modifiers.ABSTRACT;
140                         if ((ma & MethodAttributes.Final) != 0)
141                                 mod |= Modifiers.SEALED;
142
143                         IMemberDefinition definition;
144                         var gmd = mb as MethodInfo;
145                         if (gmd != null && gmd.IsGenericMethodDefinition) {
146                                 definition = new ImportedGenericMethodDefinition (gmd);
147                         } else if (mb.IsGenericMethod) {        // TODO MemberCache: Remove me
148                                 definition = new ImportedGenericMethodDefinition ((MethodInfo) TypeManager.DropGenericMethodArguments (mb));
149                         } else {
150                                 definition = new ImportedMemberDefinition (mb);
151                         }
152
153                         // TODO MemberCache: Use AParametersCollection p = ParametersImported.Create (mb);
154                         AParametersCollection p = TypeManager.GetParameterData (mb);
155                         MethodSpec ms = new MethodSpec (definition, mb, p, mod);
156                         return ms;
157                 }
158
159                 public static PropertySpec CreateProperty (PropertyInfo pi)
160                 {
161                         var definition = new ImportedMemberDefinition (pi);
162                         var mod = Modifiers.PRIVATE;    // TODO: modifiers
163                         return new PropertySpec (definition, pi, mod);
164                 }
165
166                 //
167                 // Decimal constants cannot be encoded in the constant blob, and thus are marked
168                 // as IsInitOnly ('readonly' in C# parlance).  We get its value from the 
169                 // DecimalConstantAttribute metadata.
170                 //
171                 static Constant ReadDecimalConstant (FieldInfo fi)
172                 {
173                         PredefinedAttribute pa = PredefinedAttributes.Get.DecimalConstant;
174                         if (!pa.IsDefined)
175                                 return null;
176
177                         object[] attrs = fi.GetCustomAttributes (pa.Type, false);
178                         if (attrs.Length != 1)
179                                 return null;
180
181                         return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null);
182                 }
183         }
184
185         class ImportedMemberDefinition : IMemberDefinition
186         {
187                 protected readonly ICustomAttributeProvider provider;
188
189                 public ImportedMemberDefinition (ICustomAttributeProvider provider)
190                 {
191                         this.provider = provider;
192                 }
193
194                 public ObsoleteAttribute GetObsoleteAttribute ()
195                 {
196                         var res = provider.GetCustomAttributes (typeof (ObsoleteAttribute), false);
197                         if (res == null || res.Length < 1)
198                                 return null;
199
200                         return res [0] as ObsoleteAttribute;
201                 }
202
203                 public void SetIsUsed ()
204                 {
205                         // Unused for imported members
206                 }
207         }
208
209         class ImportedGenericMethodDefinition : ImportedMemberDefinition, IGenericMethodDefinition
210         {
211                 public ImportedGenericMethodDefinition (MethodInfo provider)
212                         : base (provider)
213                 {
214                 }
215
216                 public MethodInfo MakeGenericMethod (Type[] targs)
217                 {
218                         return ((MethodInfo) provider).MakeGenericMethod (targs);
219                 }
220         }
221 }