Remove IVT from System.ServiceModel on MonoDroid, MonoTouch profiles.
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / DefaultImporter.cs
1 //
2 // DefaultReferenceImporter.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //
7 // (C) 2007 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 namespace Mono.Cecil {
30
31         using System;
32
33         public class DefaultImporter : IImporter {
34
35                 ModuleDefinition m_module;
36
37                 public ModuleDefinition Module {
38                         get { return m_module; }
39                 }
40
41                 public DefaultImporter (ModuleDefinition module)
42                 {
43                         m_module = module;
44                 }
45
46                 public AssemblyNameReference ImportAssembly (AssemblyNameReference asm)
47                 {
48                         AssemblyNameReference asmRef = GetAssemblyNameReference (asm);
49                         if (asmRef != null)
50                                 return asmRef;
51
52                         asmRef = new AssemblyNameReference (
53                                 asm.Name, asm.Culture, asm.Version);
54                         asmRef.PublicKeyToken = asm.PublicKeyToken;
55                         asmRef.HashAlgorithm = asm.HashAlgorithm;
56                         m_module.AssemblyReferences.Add (asmRef);
57                         return asmRef;
58                 }
59
60                 AssemblyNameReference GetAssemblyNameReference (AssemblyNameReference asm)
61                 {
62                         foreach (AssemblyNameReference reference in m_module.AssemblyReferences)
63                                 if (reference.FullName == asm.FullName)
64                                         return reference;
65
66                         return null;
67                 }
68
69                 TypeSpecification GetTypeSpec (TypeSpecification original, ImportContext context)
70                 {
71                         TypeSpecification typeSpec;
72
73                         TypeReference elementType = ImportTypeReference (original.ElementType, context);
74                         if (original is PointerType) {
75                                 typeSpec = new PointerType (elementType);
76                         } else if (original is ArrayType) { // deal with complex arrays
77                                 typeSpec = new ArrayType (elementType);
78                         } else if (original is ReferenceType) {
79                                 typeSpec = new ReferenceType (elementType);
80                         } else if (original is GenericInstanceType) {
81                                 GenericInstanceType git = original as GenericInstanceType;
82                                 GenericInstanceType genElemType = new GenericInstanceType (elementType);
83
84                                 context.GenericContext.CheckProvider (genElemType.GetOriginalType (), git.GenericArguments.Count);
85                                 foreach (TypeReference arg in git.GenericArguments)
86                                         genElemType.GenericArguments.Add (ImportTypeReference (arg, context));
87
88                                 typeSpec = genElemType;
89                         } else if (original is ModifierOptional) {
90                                 TypeReference mt = (original as ModifierOptional).ModifierType;
91                                 typeSpec = new ModifierOptional (elementType, ImportTypeReference (mt, context));
92                         } else if (original is ModifierRequired) {
93                                 TypeReference mt = (original as ModifierRequired).ModifierType;
94                                 typeSpec = new ModifierRequired (elementType, ImportTypeReference (mt, context));
95                         } else if (original is SentinelType) {
96                                 typeSpec = new SentinelType (elementType);
97                         } else if (original is FunctionPointerType) {
98                                 FunctionPointerType ori = original as FunctionPointerType;
99
100                                 FunctionPointerType fnptr = new FunctionPointerType (
101                                         ori.HasThis,
102                                         ori.ExplicitThis,
103                                         ori.CallingConvention,
104                                         new MethodReturnType (ImportTypeReference (ori.ReturnType.ReturnType, context)));
105
106                                 foreach (ParameterDefinition parameter in ori.Parameters)
107                                         fnptr.Parameters.Add (new ParameterDefinition (ImportTypeReference (parameter.ParameterType, context)));
108
109                                 typeSpec = fnptr;
110                         } else
111                                 throw new ReflectionException ("Unknown element type: {0}", original.GetType ().Name);
112
113                         return typeSpec;
114                 }
115
116                 static GenericParameter GetGenericParameter (GenericParameter gp, ImportContext context)
117                 {
118                         GenericParameter p;
119                         if (gp.Owner is TypeReference)
120                                 p = context.GenericContext.Type.GenericParameters [gp.Position];
121                         else if (gp.Owner is MethodReference)
122                                 p = context.GenericContext.Method.GenericParameters [gp.Position];
123                         else
124                                 throw new NotSupportedException ();
125
126                         return p;
127                 }
128
129                 TypeReference AdjustReference (TypeReference type, TypeReference reference)
130                 {
131                         if (type.IsValueType && !reference.IsValueType)
132                                 reference.IsValueType = true;
133
134                         if (type.HasGenericParameters) {
135                                 for (int i = reference.GenericParameters.Count; i < type.GenericParameters.Count; i++)
136                                         reference.GenericParameters.Add (new GenericParameter (i, reference));
137                         }
138
139                         return reference;
140                 }
141
142                 public virtual TypeReference ImportTypeReference (TypeReference t, ImportContext context)
143                 {
144                         if (t.Module == m_module)
145                                 return t;
146
147                         if (t is TypeSpecification)
148                                 return GetTypeSpec (t as TypeSpecification, context);
149
150                         if (t is GenericParameter)
151                                 return GetGenericParameter (t as GenericParameter, context);
152
153                         TypeReference type = m_module.TypeReferences [t.FullName];
154                         if (type != null)
155                                 return AdjustReference (t, type);
156
157                         AssemblyNameReference asm;
158                         if (t.Scope is AssemblyNameReference)
159                                 asm = ImportAssembly ((AssemblyNameReference) t.Scope);
160                         else if (t.Scope is ModuleDefinition)
161                                 asm = ImportAssembly (((ModuleDefinition) t.Scope).Assembly.Name);
162                         else
163                                 throw new NotImplementedException ();
164
165                         if (t.DeclaringType != null) {
166                                 type = new TypeReference (t.Name, string.Empty, asm, t.IsValueType);
167                                 type.DeclaringType = ImportTypeReference (t.DeclaringType, context);
168                         } else
169                                 type = new TypeReference (t.Name, t.Namespace, asm, t.IsValueType);
170
171                         TypeReference contextType = context.GenericContext.Type;
172
173                         context.GenericContext.Type = type;
174
175                         GenericParameter.CloneInto (t, type, context);
176
177                         context.GenericContext.Type = contextType;
178
179                         m_module.TypeReferences.Add (type);
180                         return type;
181                 }
182
183                 public virtual FieldReference ImportFieldReference (FieldReference fr, ImportContext context)
184                 {
185                         if (fr.DeclaringType.Module == m_module)
186                                 return fr;
187
188                         FieldReference field = (FieldReference) GetMemberReference (fr);
189                         if (field != null)
190                                 return field;
191
192                         field = new FieldReference (
193                                 fr.Name,
194                                 ImportTypeReference (fr.DeclaringType, context),
195                                 ImportTypeReference (fr.FieldType, context));
196
197                         m_module.MemberReferences.Add (field);
198                         return field;
199                 }
200
201                 MethodReference GetMethodSpec (MethodReference meth, ImportContext context)
202                 {
203                         if (!(meth is GenericInstanceMethod))
204                                 return null;
205
206                         GenericInstanceMethod gim = meth as GenericInstanceMethod;
207                         GenericInstanceMethod ngim = new GenericInstanceMethod (
208                                 ImportMethodReference (gim.ElementMethod, context));
209
210                         context.GenericContext.CheckProvider (ngim.GetOriginalMethod (), gim.GenericArguments.Count);
211                         foreach (TypeReference arg in gim.GenericArguments)
212                                 ngim.GenericArguments.Add (ImportTypeReference (arg, context));
213
214                         return ngim;
215                 }
216
217                 public virtual MethodReference ImportMethodReference (MethodReference mr, ImportContext context)
218                 {
219                         if (mr.DeclaringType.Module == m_module)
220                                 return mr;
221
222                         if (mr is MethodSpecification)
223                                 return GetMethodSpec (mr, context);
224
225                         MethodReference meth = (MethodReference) GetMemberReference (mr);
226                         if (meth != null)
227                                 return meth;
228
229                         meth = new MethodReference (
230                                 mr.Name,
231                                 mr.HasThis,
232                                 mr.ExplicitThis,
233                                 mr.CallingConvention);
234                         meth.DeclaringType = ImportTypeReference (mr.DeclaringType, context);
235
236                         TypeReference contextType = context.GenericContext.Type;
237                         MethodReference contextMethod = context.GenericContext.Method;
238
239                         context.GenericContext.Method = meth;
240                         context.GenericContext.Type = meth.DeclaringType.GetOriginalType();
241
242                         GenericParameter.CloneInto (mr, meth, context);
243
244                         meth.ReturnType.ReturnType = ImportTypeReference (mr.ReturnType.ReturnType, context);
245
246                         foreach (ParameterDefinition param in mr.Parameters)
247                                 meth.Parameters.Add (new ParameterDefinition (
248                                         ImportTypeReference (param.ParameterType, context)));
249
250                         context.GenericContext.Type = contextType;
251                         context.GenericContext.Method = contextMethod;
252
253                         m_module.MemberReferences.Add (meth);
254                         return meth;
255                 }
256
257                 MemberReference GetMemberReference (MemberReference member)
258                 {
259                         foreach (MemberReference reference in m_module.MemberReferences)
260                                 if (reference.ToString () == member.ToString ())
261                                         return reference;
262
263                         return null;
264                 }
265         }
266 }