Merge branch 'cecil-light'
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / TypeReference.cs
1 //
2 // TypeReference.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2010 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30
31 using Mono.Cecil.Metadata;
32 using Mono.Collections.Generic;
33
34 namespace Mono.Cecil {
35
36         public enum MetadataType : byte {
37                 Void = ElementType.Void,
38                 Boolean = ElementType.Boolean,
39                 Char = ElementType.Char,
40                 SByte = ElementType.I1,
41                 Byte = ElementType.U1,
42                 Int16 = ElementType.I2,
43                 UInt16 = ElementType.U2,
44                 Int32 = ElementType.I4,
45                 UInt32 = ElementType.U4,
46                 Int64 = ElementType.I8,
47                 UInt64 = ElementType.U8,
48                 Single = ElementType.R4,
49                 Double = ElementType.R8,
50                 String = ElementType.String,
51                 Pointer = ElementType.Ptr,
52                 ByReference = ElementType.ByRef,
53                 ValueType = ElementType.ValueType,
54                 Class = ElementType.Class,
55                 Var = ElementType.Var,
56                 Array = ElementType.Array,
57                 GenericInstance = ElementType.GenericInst,
58                 TypedByReference = ElementType.TypedByRef,
59                 IntPtr = ElementType.I,
60                 UIntPtr = ElementType.U,
61                 FunctionPointer = ElementType.FnPtr,
62                 Object = ElementType.Object,
63                 MVar = ElementType.MVar,
64                 RequiredModifier = ElementType.CModReqD,
65                 OptionalModifier = ElementType.CModOpt,
66                 Sentinel = ElementType.Sentinel,
67                 Pinned = ElementType.Pinned,
68         }
69
70         public class TypeReference : MemberReference, IGenericParameterProvider, IGenericContext {
71
72                 string @namespace;
73                 bool value_type;
74                 internal IMetadataScope scope;
75                 internal ModuleDefinition module;
76
77                 internal ElementType etype = ElementType.None;
78
79                 string fullname;
80
81                 protected Collection<GenericParameter> generic_parameters;
82
83                 public override string Name {
84                         get { return base.Name; }
85                         set {
86                                 base.Name = value;
87                                 fullname = null;
88                         }
89                 }
90
91                 public virtual string Namespace {
92                         get { return @namespace; }
93                         set {
94                                 @namespace = value;
95                                 fullname = null;
96                         }
97                 }
98
99                 public virtual bool IsValueType {
100                         get { return value_type; }
101                         set { value_type = value; }
102                 }
103
104                 public override ModuleDefinition Module {
105                         get {
106                                 if (module != null)
107                                         return module;
108
109                                 var declaring_type = this.DeclaringType;
110                                 if (declaring_type != null)
111                                         return declaring_type.Module;
112
113                                 return null;
114                         }
115                 }
116
117                 IGenericParameterProvider IGenericContext.Type {
118                         get { return this; }
119                 }
120
121                 IGenericParameterProvider IGenericContext.Method {
122                         get { return null; }
123                 }
124
125                 GenericParameterType IGenericParameterProvider.GenericParameterType {
126                         get { return GenericParameterType.Type; }
127                 }
128
129                 public virtual bool HasGenericParameters {
130                         get { return !generic_parameters.IsNullOrEmpty (); }
131                 }
132
133                 public virtual Collection<GenericParameter> GenericParameters {
134                         get {
135                                 if (generic_parameters != null)
136                                         return generic_parameters;
137
138                                 return generic_parameters = new Collection<GenericParameter> ();
139                         }
140                 }
141
142                 public virtual IMetadataScope Scope {
143                         get {
144                                 var declaring_type = this.DeclaringType;
145                                 if (declaring_type != null)
146                                         return declaring_type.Scope;
147
148                                 return scope;
149                         }
150                 }
151
152                 public bool IsNested {
153                         get { return this.DeclaringType != null; }
154                 }
155
156                 public override TypeReference DeclaringType {
157                         get { return base.DeclaringType; }
158                         set {
159                                 base.DeclaringType = value;
160                                 fullname = null;
161                         }
162                 }
163
164                 public override string FullName {
165                         get {
166                                 if (fullname != null)
167                                         return fullname;
168
169                                 if (IsNested)
170                                         return fullname = DeclaringType.FullName + "/" + Name;
171
172                                 if (string.IsNullOrEmpty (@namespace))
173                                         return fullname = Name;
174
175                                 return fullname = @namespace + "." + Name;
176                         }
177                 }
178
179                 public virtual bool IsByReference {
180                         get { return false; }
181                 }
182
183                 public virtual bool IsPointer {
184                         get { return false; }
185                 }
186
187                 public virtual bool IsSentinel {
188                         get { return false; }
189                 }
190
191                 public virtual bool IsArray {
192                         get { return false; }
193                 }
194
195                 public virtual bool IsGenericParameter {
196                         get { return false; }
197                 }
198
199                 public virtual bool IsGenericInstance {
200                         get { return false; }
201                 }
202
203                 public virtual bool IsRequiredModifier {
204                         get { return false; }
205                 }
206
207                 public virtual bool IsOptionalModifier {
208                         get { return false; }
209                 }
210
211                 public virtual bool IsPinned {
212                         get { return false; }
213                 }
214
215                 public virtual bool IsFunctionPointer {
216                         get { return false; }
217                 }
218
219                 public bool IsPrimitive {
220                         get {
221                                 switch (etype) {
222                                 case ElementType.Boolean:
223                                 case ElementType.Char:
224                                 case ElementType.I:
225                                 case ElementType.U:
226                                 case ElementType.I1:
227                                 case ElementType.U1:
228                                 case ElementType.I2:
229                                 case ElementType.U2:
230                                 case ElementType.I4:
231                                 case ElementType.U4:
232                                 case ElementType.I8:
233                                 case ElementType.U8:
234                                 case ElementType.R4:
235                                 case ElementType.R8:
236                                         return true;
237                                 default:
238                                         return false;
239                                 }
240                         }
241                 }
242
243                 public virtual MetadataType MetadataType {
244                         get {
245                                 switch (etype) {
246                                 case ElementType.None:
247                                         return IsValueType ? MetadataType.ValueType : MetadataType.Class;
248                                 default:
249                                         return (MetadataType) etype;
250                                 }
251                         }
252                 }
253
254                 protected TypeReference (string @namespace, string name)
255                         : base (name)
256                 {
257                         this.@namespace = @namespace ?? string.Empty;
258                         this.token = new MetadataToken (TokenType.TypeRef, 0);
259                 }
260
261                 public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope)
262                         : this (@namespace, name)
263                 {
264                         this.module = module;
265                         this.scope = scope;
266                 }
267
268                 public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType) :
269                         this (@namespace, name, module, scope)
270                 {
271                         value_type = valueType;
272                 }
273
274                 public virtual TypeReference GetElementType ()
275                 {
276                         return this;
277                 }
278
279                 public virtual TypeDefinition Resolve ()
280                 {
281                         var module = this.Module;
282                         if (module == null)
283                                 throw new NotSupportedException ();
284
285                         return module.Resolve (this);
286                 }
287         }
288
289         static partial class Mixin {
290
291                 public static bool IsTypeOf (this TypeReference self, string @namespace, string name)
292                 {
293                         return self.Name == name
294                                 && self.Namespace == @namespace;
295                 }
296
297                 public static bool IsTypeSpecification (this TypeReference type)
298                 {
299                         switch (type.etype) {
300                         case ElementType.Array:
301                         case ElementType.ByRef:
302                         case ElementType.CModOpt:
303                         case ElementType.CModReqD:
304                         case ElementType.FnPtr:
305                         case ElementType.GenericInst:
306                         case ElementType.MVar:
307                         case ElementType.Pinned:
308                         case ElementType.Ptr:
309                         case ElementType.SzArray:
310                         case ElementType.Sentinel:
311                         case ElementType.Var:
312                                 return true;
313                         }
314
315                         return false;
316                 }
317
318                 public static TypeDefinition CheckedResolve (this TypeReference self)
319                 {
320                         var type = self.Resolve ();
321                         if (type == null)
322                                 throw new InvalidOperationException (string.Format ("Failed to resolve type: {0}", self.FullName));
323
324                         return type;
325                 }
326         }
327 }