2010-01-07 Marek Safar <marek.safar@gmail.com>
[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: remove after MemberCache fix
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: Remove completely
52                         IMemberDetails details;
53                         var gfd = TypeManager.GetGenericFieldDefinition (fi);
54                         fb = TypeManager.GetFieldCore (gfd);
55                         if (fb != null) {
56                                 details = fb;
57                         } else {
58                                 cs = TypeManager.GetConstant (gfd);
59                                 if (cs != null)
60                                         details = cs.MemberDetails;
61                                 else
62                                         details = new ImportedMemberDetails (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 (details, 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 (details, 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 (details, fi, element_field, mod);
98                                         }
99                                 }
100                         }
101
102                         // TODO: volatile
103
104                         return new FieldSpec (details, fi, mod);
105                 }
106
107                 //
108                 // Decimal constants cannot be encoded in the constant blob, and thus are marked
109                 // as IsInitOnly ('readonly' in C# parlance).  We get its value from the 
110                 // DecimalConstantAttribute metadata.
111                 //
112                 static Constant ReadDecimalConstant (FieldInfo fi)
113                 {
114                         PredefinedAttribute pa = PredefinedAttributes.Get.DecimalConstant;
115                         if (!pa.IsDefined)
116                                 return null;
117
118                         object[] attrs = fi.GetCustomAttributes (pa.Type, false);
119                         if (attrs.Length != 1)
120                                 return null;
121
122                         return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null);
123                 }
124         }
125
126         class ImportedMemberDetails : IMemberDetails
127         {
128                 readonly ICustomAttributeProvider provider;
129
130                 public ImportedMemberDetails (ICustomAttributeProvider provider)
131                 {
132                         this.provider = provider;
133                 }
134
135                 public ObsoleteAttribute GetObsoleteAttribute ()
136                 {
137                         var res = provider.GetCustomAttributes (typeof (ObsoleteAttribute), false);
138                         if (res == null || res.Length < 1)
139                                 return null;
140
141                         return res [0] as ObsoleteAttribute;
142                 }
143         }
144 }