~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/mono-addins/Mono.Addins.CecilReflector/Mono.Addins.CecilReflector/Reflector.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Reflector.cs
 
2
//
 
3
// Author:
 
4
//   Lluis Sanchez Gual <lluis@novell.com>
 
5
//
 
6
// Copyright (c) 2007 Novell, Inc (http://www.novell.com)
 
7
//
 
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
9
// of this software and associated documentation files (the "Software"), to deal
 
10
// in the Software without restriction, including without limitation the rights
 
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
12
// copies of the Software, and to permit persons to whom the Software is
 
13
// furnished to do so, subject to the following conditions:
 
14
//
 
15
// The above copyright notice and this permission notice shall be included in
 
16
// all copies or substantial portions of the Software.
 
17
//
 
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
24
// THE SOFTWARE.
 
25
//
 
26
//
 
27
 
 
28
using System;
 
29
using System.Collections;
 
30
using System.Reflection;
 
31
using Mono.Addins;
 
32
using Mono.Addins.Database;
 
33
using Mono.Cecil;
 
34
using CustomAttribute = Mono.Cecil.CustomAttribute;
 
35
using MA = Mono.Addins.Database;
 
36
using System.Collections.Generic;
 
37
 
 
38
namespace Mono.Addins.CecilReflector
 
39
{
 
40
        public class Reflector: IAssemblyReflector
 
41
        {
 
42
                IAssemblyLocator locator;
 
43
                Hashtable cachedAssemblies = new Hashtable ();
 
44
                
 
45
                public void Initialize (IAssemblyLocator locator)
 
46
                {
 
47
                        this.locator = locator;
 
48
                }
 
49
                
 
50
                public object[] GetCustomAttributes (object obj, Type type, bool inherit)
 
51
                {
 
52
                        Mono.Cecil.ICustomAttributeProvider aprov = obj as Mono.Cecil.ICustomAttributeProvider;
 
53
                        if (aprov == null)
 
54
                                return new object [0];
 
55
                        
 
56
                        ArrayList atts = new ArrayList ();
 
57
                        foreach (CustomAttribute att in aprov.CustomAttributes) {
 
58
                                object catt = ConvertAttribute (att, type);
 
59
                                if (catt != null)
 
60
                                        atts.Add (catt);
 
61
                        }
 
62
                        if (inherit && (obj is TypeDefinition)) {
 
63
                                TypeDefinition td = (TypeDefinition) obj;
 
64
                                if (td.BaseType != null && td.BaseType.FullName != "System.Object") {
 
65
                                        TypeDefinition bt = FindTypeDefinition (td.Module.Assembly, td.BaseType);
 
66
                                        if (bt != null)
 
67
                                                atts.AddRange (GetCustomAttributes (bt, type, true));
 
68
                                }
 
69
                        }
 
70
                        return atts.ToArray ();
 
71
                }
 
72
                
 
73
                object ConvertAttribute (CustomAttribute att, Type expectedType)
 
74
                {
 
75
                        Type attype = typeof(IAssemblyReflector).Assembly.GetType (att.Constructor.DeclaringType.FullName);
 
76
 
 
77
                        if (attype == null || !expectedType.IsAssignableFrom (attype))
 
78
                                return null;
 
79
                        
 
80
                        object ob;
 
81
                        
 
82
                        if (att.ConstructorArguments.Count > 0) {
 
83
                                object[] cargs = new object [att.ConstructorArguments.Count];
 
84
                                ArrayList typeParameters = null;
 
85
 
 
86
                                // Constructor parameters of type System.Type can't be set because types from the assembly
 
87
                                // can't be loaded. The parameter value will be set later using a type name property.
 
88
                                for (int n=0; n<cargs.Length; n++) {
 
89
                                        cargs [n] = att.ConstructorArguments [n].Value;
 
90
                                        string atype = att.Constructor.Parameters[n].ParameterType.FullName;
 
91
                                        if (atype == "System.Type") {
 
92
                                                if (typeParameters == null)
 
93
                                                        typeParameters = new ArrayList ();
 
94
                                                cargs [n] = typeof(object);
 
95
                                                typeParameters.Add (n);
 
96
                                        }
 
97
                                }
 
98
                                ob = Activator.CreateInstance (attype, cargs);
 
99
                                
 
100
                                // If there are arguments of type System.Type, set them using the property
 
101
                                if (typeParameters != null) {
 
102
                                        Type[] ptypes = new Type [cargs.Length];
 
103
                                        for (int n=0; n<cargs.Length; n++) {
 
104
                                                ptypes [n] = cargs [n].GetType ();
 
105
                                        }
 
106
                                        ConstructorInfo ci = attype.GetConstructor (ptypes);
 
107
                                        ParameterInfo[] ciParams = ci.GetParameters ();
 
108
                                        
 
109
                                        for (int n=0; n<typeParameters.Count; n++) {
 
110
                                                int ip = (int) typeParameters [n];
 
111
                                                string propName = ciParams[ip].Name;
 
112
                                                propName = char.ToUpper (propName [0]) + propName.Substring (1) + "Name";
 
113
                                                PropertyInfo pi = attype.GetProperty (propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 
114
 
 
115
                                                if (pi == null)
 
116
                                                        throw new InvalidOperationException ("Property '" + propName + "' not found in type '" + attype + "'.");
 
117
 
 
118
                                                pi.SetValue (ob, ((TypeReference) att.ConstructorArguments [ip].Value).FullName, null);
 
119
                                        }
 
120
                                }
 
121
                        } else {
 
122
                                ob = Activator.CreateInstance (attype);
 
123
                        }
 
124
                        
 
125
                        foreach (Mono.Cecil.CustomAttributeNamedArgument namedArgument in att.Properties) {
 
126
                                string pname = namedArgument.Name;
 
127
                                PropertyInfo prop = attype.GetProperty (pname);
 
128
                                if (prop != null) {
 
129
                                        if (prop.PropertyType == typeof(System.Type)) {
 
130
                                                // We can't load the type. We have to use the typeName property instead.
 
131
                                                pname += "Name";
 
132
                                                prop = attype.GetProperty (pname, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 
133
                                                
 
134
                                                if (prop == null)
 
135
                                                        throw new InvalidOperationException ("Property '" + pname + "' not found in type '" + attype + "'.");
 
136
 
 
137
                                                prop.SetValue (ob, ((TypeReference) namedArgument.Argument.Value).FullName, null);
 
138
                                        } else
 
139
                                                prop.SetValue (ob, namedArgument.Argument.Value, null);
 
140
                                }
 
141
                        }
 
142
                        return ob;
 
143
                }
 
144
                
 
145
                public List<MA.CustomAttribute> GetRawCustomAttributes (object obj, Type type, bool inherit)
 
146
                {
 
147
                        List<MA.CustomAttribute> atts = new List<MA.CustomAttribute> ();
 
148
                        Mono.Cecil.ICustomAttributeProvider aprov = obj as Mono.Cecil.ICustomAttributeProvider;
 
149
                        if (aprov == null)
 
150
                                return atts;
 
151
                        
 
152
                        foreach (CustomAttribute att in aprov.CustomAttributes) {
 
153
                                MA.CustomAttribute catt = ConvertToRawAttribute (att, type.FullName);
 
154
                                if (catt != null)
 
155
                                        atts.Add (catt);
 
156
                        }
 
157
                        if (inherit && (obj is TypeDefinition)) {
 
158
                                TypeDefinition td = (TypeDefinition) obj;
 
159
                                if (td.BaseType != null && td.BaseType.FullName != "System.Object") {
 
160
                                        TypeDefinition bt = FindTypeDefinition (td.Module.Assembly, td.BaseType);
 
161
                                        if (bt != null)
 
162
                                                atts.AddRange (GetRawCustomAttributes (bt, type, true));
 
163
                                }
 
164
                        }
 
165
                        return atts;
 
166
                }
 
167
                
 
168
                MA.CustomAttribute ConvertToRawAttribute (CustomAttribute att, string expectedType)
 
169
                {
 
170
                        TypeDefinition attType = FindTypeDefinition (att.Constructor.DeclaringType.Module.Assembly, att.Constructor.DeclaringType);
 
171
                        
 
172
                        if (attType == null || !TypeIsAssignableFrom (expectedType, attType))
 
173
                                return null;
 
174
 
 
175
                        MA.CustomAttribute mat = new MA.CustomAttribute ();
 
176
                        mat.TypeName = att.Constructor.DeclaringType.FullName;
 
177
                        
 
178
                        if (att.ConstructorArguments.Count > 0) {
 
179
                                var arguments = att.ConstructorArguments;
 
180
                                
 
181
                                MethodReference constructor = FindConstructor (att);
 
182
                                if (constructor == null)
 
183
                                        throw new InvalidOperationException ("Custom attribute constructor not found");
 
184
 
 
185
                                for (int n=0; n<arguments.Count; n++) {
 
186
                                        ParameterDefinition par = constructor.Parameters[n];
 
187
                                        object val = arguments [n].Value;
 
188
                                        if (val != null) {
 
189
                                                string name = par.Name;
 
190
                                                NodeAttributeAttribute bat = (NodeAttributeAttribute) GetCustomAttribute (par, typeof(NodeAttributeAttribute), false);
 
191
                                                if (bat != null)
 
192
                                                        name = bat.Name;
 
193
                                                mat.Add (name, Convert.ToString (val, System.Globalization.CultureInfo.InvariantCulture));
 
194
                                        }
 
195
                                }
 
196
                        }
 
197
                        
 
198
                        foreach (Mono.Cecil.CustomAttributeNamedArgument namedArgument in att.Properties) {
 
199
                                string pname = namedArgument.Name;
 
200
                                object val = namedArgument.Argument.Value;
 
201
                                if (val == null)
 
202
                                        continue;
 
203
 
 
204
                                foreach (TypeDefinition td in GetInheritanceChain (attType)) {
 
205
                                        PropertyDefinition prop = GetMember (td.Properties, pname);
 
206
                                        if (prop == null)
 
207
                                                continue;
 
208
 
 
209
                                        NodeAttributeAttribute bat = (NodeAttributeAttribute) GetCustomAttribute (prop, typeof(NodeAttributeAttribute), false);
 
210
                                        if (bat != null) {
 
211
                                                string name = string.IsNullOrEmpty (bat.Name) ? prop.Name : bat.Name;
 
212
                                                mat.Add (name, Convert.ToString (val, System.Globalization.CultureInfo.InvariantCulture));
 
213
                                        }
 
214
                                }
 
215
                        }
 
216
                        
 
217
                        foreach (Mono.Cecil.CustomAttributeNamedArgument namedArgument in att.Fields) {
 
218
                                string pname = namedArgument.Name;
 
219
                                object val = namedArgument.Argument.Value;
 
220
                                if (val == null)
 
221
                                        continue;
 
222
 
 
223
                                foreach (TypeDefinition td in GetInheritanceChain (attType)) {
 
224
                                        FieldDefinition field = GetMember (td.Fields, pname);
 
225
                                        if (field != null) {
 
226
                                                NodeAttributeAttribute bat = (NodeAttributeAttribute) GetCustomAttribute (field, typeof(NodeAttributeAttribute), false);
 
227
                                                if (bat != null) {
 
228
                                                        string name = string.IsNullOrEmpty (bat.Name) ? field.Name : bat.Name;
 
229
                                                        mat.Add (name, Convert.ToString (val, System.Globalization.CultureInfo.InvariantCulture));
 
230
                                                }
 
231
                                        }
 
232
                                }
 
233
                        }
 
234
 
 
235
                        return mat;
 
236
                }
 
237
 
 
238
                static TMember GetMember<TMember> (ICollection<TMember> members, string name) where TMember : class, IMemberDefinition
 
239
                {
 
240
                        foreach (var member in members)
 
241
                                if (member.Name == name)
 
242
                                        return member;
 
243
 
 
244
                        return null;
 
245
                }
 
246
                
 
247
                IEnumerable<TypeDefinition> GetInheritanceChain (TypeDefinition td)
 
248
                {
 
249
                        yield return td;
 
250
                        while (td != null && td.BaseType != null && td.BaseType.FullName != "System.Object") {
 
251
                                td = FindTypeDefinition (td.Module.Assembly, td.BaseType);
 
252
                                if (td != null)
 
253
                                        yield return td;
 
254
                        }
 
255
                }
 
256
 
 
257
                MethodReference FindConstructor (CustomAttribute att)
 
258
                {
 
259
                        // The constructor provided by CustomAttribute.Constructor is lacking some information, such as the parameter
 
260
                        // name and custom attributes. Since we need the full info, we have to look it up in the declaring type.
 
261
                        
 
262
                        TypeDefinition atd = FindTypeDefinition (att.Constructor.DeclaringType.Module.Assembly, att.Constructor.DeclaringType);
 
263
                        foreach (MethodReference met in atd.Methods) {
 
264
                                if (met.Name != ".ctor")
 
265
                                        continue;
 
266
 
 
267
                                if (met.Parameters.Count == att.Constructor.Parameters.Count) {
 
268
                                        for (int n = met.Parameters.Count - 1; n >= 0; n--) {
 
269
                                                if (met.Parameters[n].ParameterType.FullName != att.Constructor.Parameters[n].ParameterType.FullName)
 
270
                                                        break;
 
271
                                                if (n == 0)
 
272
                                                        return met;
 
273
                                        }
 
274
                                }
 
275
                        }
 
276
                        return null;
 
277
                }
 
278
 
 
279
                public object LoadAssembly (string file)
 
280
                {
 
281
                        return LoadAssembly (file, false);
 
282
                }
 
283
 
 
284
                public AssemblyDefinition LoadAssembly (string file, bool cache)
 
285
                {
 
286
                        AssemblyDefinition adef = (AssemblyDefinition) cachedAssemblies [file];
 
287
                        if (adef != null)
 
288
                                return adef;
 
289
                        adef = AssemblyDefinition.ReadAssembly (file);
 
290
                        if (adef != null && cache)
 
291
                                cachedAssemblies [file] = adef;
 
292
                        return adef;
 
293
                }
 
294
                
 
295
                public string[] GetResourceNames (object asm)
 
296
                {
 
297
                        AssemblyDefinition adef = (AssemblyDefinition) asm;
 
298
                        List<string> names = new List<string> (adef.MainModule.Resources.Count);
 
299
                        foreach (Resource res in adef.MainModule.Resources) {
 
300
                                if (res is EmbeddedResource)
 
301
                                        names.Add (res.Name);
 
302
                        }
 
303
                        return names.ToArray ();
 
304
                }
 
305
                
 
306
                public System.IO.Stream GetResourceStream (object asm, string resourceName)
 
307
                {
 
308
                        AssemblyDefinition adef = (AssemblyDefinition) asm;
 
309
                        foreach (Resource res in adef.MainModule.Resources) {
 
310
                                EmbeddedResource r = res as EmbeddedResource;
 
311
                                if (r != null && r.Name == resourceName)
 
312
                                        return r.GetResourceStream ();
 
313
                        }
 
314
                        throw new InvalidOperationException ("Resource not found: " + resourceName);
 
315
                }
 
316
 
 
317
                public object LoadAssemblyFromReference (object asmReference)
 
318
                {
 
319
                        AssemblyNameReference aref = (AssemblyNameReference) asmReference;
 
320
                        string loc = locator.GetAssemblyLocation (aref.FullName);
 
321
                        if (loc != null)
 
322
                                return LoadAssembly (loc);
 
323
                        else
 
324
                                return null;
 
325
                }
 
326
 
 
327
                public System.Collections.IEnumerable GetAssemblyTypes (object asm)
 
328
                {
 
329
                        return ((AssemblyDefinition)asm).MainModule.Types;
 
330
                }
 
331
 
 
332
                public System.Collections.IEnumerable GetAssemblyReferences (object asm)
 
333
                {
 
334
                        return ((AssemblyDefinition)asm).MainModule.AssemblyReferences;
 
335
                }
 
336
 
 
337
                public object GetType (object asm, string typeName)
 
338
                {
 
339
                        if (typeName.IndexOf ('`') != -1) {
 
340
                                foreach (TypeDefinition td in ((AssemblyDefinition)asm).MainModule.Types) {
 
341
                                        if (td.FullName == typeName) {
 
342
                                                return td;
 
343
                                        }
 
344
                                }
 
345
                        }
 
346
                        TypeDefinition t = ((AssemblyDefinition)asm).MainModule.GetType (typeName);
 
347
                        if (t != null) {
 
348
                                return t;
 
349
                        } else {
 
350
                                return null;
 
351
                        }
 
352
                }
 
353
 
 
354
                public object GetCustomAttribute (object obj, Type type, bool inherit)
 
355
                {
 
356
                        foreach (object att in GetCustomAttributes (obj, type, inherit))
 
357
                                if (type.IsInstanceOfType (att))
 
358
                                        return att;
 
359
                        return null;
 
360
                }
 
361
 
 
362
                public string GetTypeName (object type)
 
363
                {
 
364
                        return ((TypeDefinition)type).Name;
 
365
                }
 
366
 
 
367
                public string GetTypeFullName (object type)
 
368
                {
 
369
                        return ((TypeDefinition)type).FullName;
 
370
                }
 
371
 
 
372
                public string GetTypeAssemblyQualifiedName (object type)
 
373
                {
 
374
                        AssemblyDefinition asm = GetAssemblyDefinition ((TypeDefinition)type);
 
375
                        return ((TypeDefinition)type).FullName + ", " + asm.Name.FullName;
 
376
                }
 
377
                
 
378
                AssemblyDefinition GetAssemblyDefinition (TypeDefinition t)
 
379
                {
 
380
                        return t.Module.Assembly;
 
381
                }
 
382
 
 
383
                public System.Collections.IEnumerable GetBaseTypeFullNameList (object type)
 
384
                {
 
385
                        TypeDefinition t = (TypeDefinition) type;
 
386
                        AssemblyDefinition asm = GetAssemblyDefinition (t);
 
387
 
 
388
                        ArrayList list = new ArrayList ();
 
389
                        Hashtable visited = new Hashtable ();
 
390
                        GetBaseTypeFullNameList (visited, list, asm, t);
 
391
                        list.Remove (t.FullName);
 
392
                        return list;
 
393
                }
 
394
 
 
395
                void GetBaseTypeFullNameList (Hashtable visited, ArrayList list, AssemblyDefinition asm, TypeReference tr)
 
396
                {
 
397
                        if (tr.FullName == "System.Object" || visited.Contains (tr.FullName))
 
398
                                return;
 
399
                        
 
400
                        visited [tr.FullName] = tr;
 
401
                        list.Add (tr.FullName);
 
402
                        
 
403
                        TypeDefinition type = FindTypeDefinition (asm, tr);
 
404
                        if (type == null)
 
405
                                return;
 
406
 
 
407
                        asm = GetAssemblyDefinition (type);
 
408
 
 
409
                        if (type.BaseType != null)
 
410
                                GetBaseTypeFullNameList (visited, list, asm, type.BaseType);
 
411
 
 
412
                        foreach (TypeReference interf in type.Interfaces)
 
413
                                GetBaseTypeFullNameList (visited, list, asm, interf);
 
414
                }
 
415
                
 
416
                TypeDefinition FindTypeDefinition (AssemblyDefinition referencer, TypeReference rt)
 
417
                {
 
418
                        if (rt is TypeDefinition)
 
419
                                return (TypeDefinition) rt;
 
420
 
 
421
                        string name = rt.FullName;
 
422
                        TypeDefinition td = GetType (referencer, name) as TypeDefinition;
 
423
                        if (td != null)
 
424
                                return td;
 
425
                        int i = name.IndexOf ('<');
 
426
                        if (i != -1) {
 
427
                                name = name.Substring (0, i);
 
428
                                td = GetType (referencer, name) as TypeDefinition;
 
429
                                if (td != null)
 
430
                                        return td;
 
431
                        }
 
432
                        
 
433
                        foreach (AssemblyNameReference aref in referencer.MainModule.AssemblyReferences) {
 
434
                                string loc = locator.GetAssemblyLocation (aref.FullName);
 
435
                                if (loc == null)
 
436
                                        continue;
 
437
                                AssemblyDefinition asm = LoadAssembly (loc, true);
 
438
                                td = GetType (asm, name) as TypeDefinition;
 
439
                                if (td != null)
 
440
                                        return td;
 
441
                        }
 
442
                        return null;
 
443
                }
 
444
 
 
445
                public bool TypeIsAssignableFrom (object baseType, object type)
 
446
                {
 
447
                        string baseName = ((TypeDefinition)baseType).FullName;
 
448
                        foreach (string bt in GetBaseTypeFullNameList (type))
 
449
                                if (bt == baseName)
 
450
                                        return true;
 
451
                        return false;
 
452
                }
 
453
 
 
454
                public bool TypeIsAssignableFrom (string baseTypeName, object type)
 
455
                {
 
456
                        foreach (string bt in GetBaseTypeFullNameList (type))
 
457
                                if (bt == baseTypeName)
 
458
                                        return true;
 
459
                        return false;
 
460
                }
 
461
 
 
462
                public IEnumerable GetFields (object type)
 
463
                {
 
464
                        return ((TypeDefinition)type).Fields;
 
465
                }
 
466
 
 
467
                public string GetFieldName (object field)
 
468
                {
 
469
                        return ((FieldDefinition)field).Name;
 
470
                }
 
471
 
 
472
                public string GetFieldTypeFullName (object field)
 
473
                {
 
474
                        return ((FieldDefinition)field).FieldType.FullName;
 
475
                }
 
476
        }
 
477
}