1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections.Generic;
21
using System.Diagnostics;
23
using System.Runtime.CompilerServices;
24
using System.Runtime.InteropServices;
25
using System.Threading;
26
using ICSharpCode.NRefactory.Documentation;
27
using ICSharpCode.NRefactory.Semantics;
28
using ICSharpCode.NRefactory.TypeSystem.Implementation;
29
using ICSharpCode.NRefactory.Utils;
32
namespace ICSharpCode.NRefactory.TypeSystem
35
/// Allows loading an IProjectContent from an already compiled assembly.
37
/// <remarks>Instance methods are not thread-safe; you need to create multiple instances of CecilLoader
38
/// if you want to load multiple project contents in parallel.</remarks>
39
public class CecilLoader
42
/// Version number of the cecil loader.
43
/// Should be incremented when fixing bugs in the cecil loader so that project contents cached on disk
44
/// (which might be incorrect due to the bug) are re-created.
46
const int cecilLoaderVersion = 1;
50
/// Specifies whether to include internal members. The default is false.
52
public bool IncludeInternalMembers { get; set; }
55
/// Specifies whether to use lazy loading. The default is false.
56
/// If this property is set to true, the CecilLoader will not copy all the relevant information
57
/// out of the Cecil object model, but will maintain references to the Cecil objects.
58
/// This speeds up the loading process and avoids loading unnecessary information, but it causes
59
/// the Cecil objects to stay in memory (which can significantly increase memory usage).
60
/// It also prevents serialization of the Cecil-loaded type system.
63
/// Because the type system can be used on multiple threads, but Cecil is not
64
/// thread-safe for concurrent read access, the CecilLoader will lock on the <see cref="ModuleDefinition"/> instance
65
/// for every delay-loading operation.
66
/// If you access the Cecil objects directly in your application, you may need to take the same lock.
68
public bool LazyLoad { get; set; }
71
/// Gets/Sets the documentation provider that is used to retrieve the XML documentation for all members.
73
public IDocumentationProvider DocumentationProvider { get; set; }
75
InterningProvider interningProvider;
78
/// Gets/Sets the interning provider.
80
public InterningProvider InterningProvider {
81
get { return interningProvider; }
84
throw new ArgumentNullException();
85
interningProvider = value;
90
/// Gets/Sets the cancellation token used by the cecil loader.
92
public CancellationToken CancellationToken { get; set; }
95
/// This delegate gets executed whenever an entity was loaded.
98
/// This callback may be to build a dictionary that maps between
99
/// entities and cecil objects.
100
/// Warning: if delay-loading is used and the type system is accessed by multiple threads,
101
/// the callback may be invoked concurrently on multiple threads.
103
public Action<IUnresolvedEntity, MemberReference> OnEntityLoaded { get; set; }
106
/// Gets a value indicating whether this instance stores references to the cecil objects.
109
/// <c>true</c> if this instance has references to the cecil objects; otherwise, <c>false</c>.
111
public bool HasCecilReferences { get { return typeSystemTranslationTable != null; } }
114
ModuleDefinition currentModule;
115
CecilUnresolvedAssembly currentAssembly;
118
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.CecilLoader"/> class.
122
// Enable interning by default.
123
this.InterningProvider = new SimpleInterningProvider();
127
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.CecilLoader"/> class.
129
/// <param name='createCecilReferences'>
130
/// If true references to the cecil objects are hold. In this case the cecil loader can do a type system -> cecil mapping.
132
[Obsolete("The built-in entity<->cecil mapping is obsolete. Use the OnEntityLoaded callback instead!")]
133
public CecilLoader(bool createCecilReferences) : this()
135
if (createCecilReferences)
136
typeSystemTranslationTable = new Dictionary<object, object> ();
140
/// Creates a nested CecilLoader for lazy-loading.
142
private CecilLoader(CecilLoader loader)
144
// use a shared typeSystemTranslationTable
145
this.typeSystemTranslationTable = loader.typeSystemTranslationTable;
146
this.IncludeInternalMembers = loader.IncludeInternalMembers;
147
this.LazyLoad = loader.LazyLoad;
148
this.OnEntityLoaded = loader.OnEntityLoaded;
149
this.currentModule = loader.currentModule;
150
this.currentAssembly = loader.currentAssembly;
151
// don't use interning - the interning provider is most likely not thread-safe
152
this.interningProvider = InterningProvider.Dummy;
153
// don't use cancellation for delay-loaded members
156
#region Load From AssemblyDefinition
158
/// Loads the assembly definition into a project content.
160
/// <returns>Unresolved type system representing the assembly</returns>
161
[CLSCompliant(false)]
162
public IUnresolvedAssembly LoadAssembly(AssemblyDefinition assemblyDefinition)
164
if (assemblyDefinition == null)
165
throw new ArgumentNullException("assemblyDefinition");
166
return LoadModule(assemblyDefinition.MainModule);
170
/// Loads the module definition into a project content.
172
/// <returns>Unresolved type system representing the assembly</returns>
173
[CLSCompliant(false)]
174
public IUnresolvedAssembly LoadModule(ModuleDefinition moduleDefinition)
176
if (moduleDefinition == null)
177
throw new ArgumentNullException("moduleDefinition");
179
this.currentModule = moduleDefinition;
181
// Read assembly and module attributes
182
IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>();
183
IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>();
184
AssemblyDefinition assemblyDefinition = moduleDefinition.Assembly;
185
if (assemblyDefinition != null) {
186
AddAttributes(assemblyDefinition, assemblyAttributes);
188
AddAttributes(moduleDefinition, moduleAttributes);
190
assemblyAttributes = interningProvider.InternList(assemblyAttributes);
191
moduleAttributes = interningProvider.InternList(moduleAttributes);
193
this.currentAssembly = new CecilUnresolvedAssembly(assemblyDefinition != null ? assemblyDefinition.Name.FullName : moduleDefinition.Name, this.DocumentationProvider);
194
currentAssembly.Location = moduleDefinition.FullyQualifiedName;
195
currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
196
currentAssembly.ModuleAttributes.AddRange(assemblyAttributes);
198
// Register type forwarders:
199
foreach (ExportedType type in moduleDefinition.ExportedTypes) {
200
if (type.IsForwarder) {
201
int typeParameterCount;
202
string ns = type.Namespace;
203
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
204
ns = interningProvider.Intern(ns);
205
name = interningProvider.Intern(name);
206
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount);
207
typeRef = interningProvider.Intern(typeRef);
208
var key = new TopLevelTypeName(ns, name, typeParameterCount);
209
currentAssembly.AddTypeForwarder(key, typeRef);
213
// Create and register all types:
214
CecilLoader cecilLoaderCloneForLazyLoading = LazyLoad ? new CecilLoader(this) : null;
215
List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>();
216
List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>();
217
foreach (TypeDefinition td in moduleDefinition.Types) {
218
this.CancellationToken.ThrowIfCancellationRequested();
219
if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
220
string name = td.Name;
221
if (name.Length == 0)
225
var t = new LazyCecilTypeDefinition(cecilLoaderCloneForLazyLoading, td);
226
currentAssembly.AddTypeDefinition(t);
227
RegisterCecilObject(t, td);
229
var t = CreateTopLevelTypeDefinition(td);
230
cecilTypeDefs.Add(td);
232
currentAssembly.AddTypeDefinition(t);
233
// The registration will happen after the members are initialized
237
// Initialize the type's members:
238
for (int i = 0; i < typeDefs.Count; i++) {
239
InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]);
242
AddToTypeSystemTranslationTable(this.currentAssembly, assemblyDefinition);
243
// Freezing the assembly here is important:
244
// otherwise it will be frozen when a compilation is first created
245
// from it. But freezing has the effect of changing some collection instances
246
// (to ReadOnlyCollection). This hidden mutation was causing a crash
247
// when the FastSerializer was saving the assembly at the same time as
248
// the first compilation was created from it.
249
// By freezing the assembly now, we ensure it is usable on multiple
250
// threads without issues.
251
currentAssembly.Freeze();
253
var result = this.currentAssembly;
254
this.currentAssembly = null;
255
this.currentModule = null;
260
/// Sets the current module.
261
/// This causes ReadTypeReference() to use <see cref="DefaultAssemblyReference.CurrentAssembly"/> for references
264
[CLSCompliant(false)]
265
public void SetCurrentModule(ModuleDefinition module)
267
this.currentModule = module;
271
/// Loads a type from Cecil.
273
/// <param name="typeDefinition">The Cecil TypeDefinition.</param>
274
/// <returns>ITypeDefinition representing the Cecil type.</returns>
275
[CLSCompliant(false)]
276
public IUnresolvedTypeDefinition LoadType(TypeDefinition typeDefinition)
278
if (typeDefinition == null)
279
throw new ArgumentNullException("typeDefinition");
280
var td = CreateTopLevelTypeDefinition(typeDefinition);
281
InitTypeDefinition(typeDefinition, td);
286
#region IUnresolvedAssembly implementation
287
[Serializable, FastSerializerVersion(cecilLoaderVersion)]
288
sealed class CecilUnresolvedAssembly : DefaultUnresolvedAssembly, IDocumentationProvider
290
readonly IDocumentationProvider documentationProvider;
292
public CecilUnresolvedAssembly(string fullAssemblyName, IDocumentationProvider documentationProvider)
293
: base(fullAssemblyName)
295
this.documentationProvider = documentationProvider;
298
DocumentationComment IDocumentationProvider.GetDocumentation(IEntity entity)
300
if (documentationProvider != null)
301
return documentationProvider.GetDocumentation(entity);
308
#region Load Assembly From Disk
309
public IUnresolvedAssembly LoadAssemblyFile(string fileName)
311
if (fileName == null)
312
throw new ArgumentNullException("fileName");
313
var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() };
314
ModuleDefinition module = ModuleDefinition.ReadModule(fileName, param);
315
return LoadModule(module);
318
// used to prevent Cecil from loading referenced assemblies
319
sealed class DummyAssemblyResolver : IAssemblyResolver
321
public AssemblyDefinition Resolve(AssemblyNameReference name)
326
public AssemblyDefinition Resolve(string fullName)
331
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
336
public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters)
343
#region Read Type Reference
345
/// Reads a type reference.
347
/// <param name="type">The Cecil type reference that should be converted into
348
/// a type system type reference.</param>
349
/// <param name="typeAttributes">Attributes associated with the Cecil type reference.
350
/// This is used to support the 'dynamic' type.</param>
351
[CLSCompliant(false)]
352
public ITypeReference ReadTypeReference(TypeReference type, ICustomAttributeProvider typeAttributes = null)
355
return CreateType(type, typeAttributes, ref typeIndex);
358
ITypeReference CreateType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex)
360
while (type is OptionalModifierType || type is RequiredModifierType) {
361
type = ((TypeSpecification)type).ElementType;
364
return SpecialType.UnknownType;
367
if (type is Mono.Cecil.ByReferenceType) {
369
return interningProvider.Intern(
370
new ByReferenceTypeReference(
372
(type as Mono.Cecil.ByReferenceType).ElementType,
373
typeAttributes, ref typeIndex)));
374
} else if (type is Mono.Cecil.PointerType) {
376
return interningProvider.Intern(
377
new PointerTypeReference(
379
(type as Mono.Cecil.PointerType).ElementType,
380
typeAttributes, ref typeIndex)));
381
} else if (type is Mono.Cecil.ArrayType) {
383
return interningProvider.Intern(
384
new ArrayTypeReference(
386
(type as Mono.Cecil.ArrayType).ElementType,
387
typeAttributes, ref typeIndex),
388
(type as Mono.Cecil.ArrayType).Rank));
389
} else if (type is GenericInstanceType) {
390
GenericInstanceType gType = (GenericInstanceType)type;
391
ITypeReference baseType = CreateType(gType.ElementType, typeAttributes, ref typeIndex);
392
ITypeReference[] para = new ITypeReference[gType.GenericArguments.Count];
393
for (int i = 0; i < para.Length; ++i) {
395
para[i] = CreateType(gType.GenericArguments[i], typeAttributes, ref typeIndex);
397
return interningProvider.Intern(new ParameterizedTypeReference(baseType, para));
398
} else if (type is GenericParameter) {
399
GenericParameter typeGP = (GenericParameter)type;
400
return TypeParameterReference.Create(typeGP.Owner is MethodDefinition ? EntityType.Method : EntityType.TypeDefinition, typeGP.Position);
401
} else if (type.IsNested) {
402
ITypeReference typeRef = CreateType(type.DeclaringType, typeAttributes, ref typeIndex);
403
int partTypeParameterCount;
404
string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out partTypeParameterCount);
405
namepart = interningProvider.Intern(namepart);
406
return interningProvider.Intern(new NestedTypeReference(typeRef, namepart, partTypeParameterCount));
408
string ns = interningProvider.Intern(type.Namespace ?? string.Empty);
409
string name = type.Name;
411
throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
413
if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
414
return SpecialType.Dynamic;
416
int typeParameterCount;
417
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount);
418
name = interningProvider.Intern(name);
419
if (currentAssembly != null) {
420
IUnresolvedTypeDefinition c = currentAssembly.GetTypeDefinition(ns, name, typeParameterCount);
424
return interningProvider.Intern(new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount));
429
IAssemblyReference GetAssemblyReference(IMetadataScope scope)
431
if (scope == null || scope == currentModule)
432
return DefaultAssemblyReference.CurrentAssembly;
434
return interningProvider.Intern(new DefaultAssemblyReference(scope.Name));
437
static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
439
if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
441
foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
442
TypeReference type = a.AttributeType;
443
if (type.Name == "DynamicAttribute" && type.Namespace == "System.Runtime.CompilerServices") {
444
if (a.ConstructorArguments.Count == 1) {
445
CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
446
if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
447
return (bool)values[typeIndex].Value;
456
#region Read Attributes
457
#region Assembly Attributes
458
static readonly ITypeReference assemblyVersionAttributeTypeRef = typeof(System.Reflection.AssemblyVersionAttribute).ToTypeReference();
460
void AddAttributes(AssemblyDefinition assembly, IList<IUnresolvedAttribute> outputList)
462
if (assembly.HasCustomAttributes) {
463
AddCustomAttributes(assembly.CustomAttributes, outputList);
465
if (assembly.HasSecurityDeclarations) {
466
AddSecurityAttributes(assembly.SecurityDeclarations, outputList);
469
// AssemblyVersionAttribute
470
if (assembly.Name.Version != null) {
471
var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String });
472
assemblyVersion.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString()));
473
outputList.Add(interningProvider.Intern(assemblyVersion));
477
IConstantValue CreateSimpleConstantValue(ITypeReference type, object value)
479
return interningProvider.Intern(new SimpleConstantValue(type, interningProvider.InternValue(value)));
483
#region Module Attributes
484
void AddAttributes(ModuleDefinition module, IList<IUnresolvedAttribute> outputList)
486
if (module.HasCustomAttributes) {
487
AddCustomAttributes(module.CustomAttributes, outputList);
492
#region Parameter Attributes
493
static readonly IUnresolvedAttribute inAttribute = new DefaultUnresolvedAttribute(typeof(InAttribute).ToTypeReference());
494
static readonly IUnresolvedAttribute outAttribute = new DefaultUnresolvedAttribute(typeof(OutAttribute).ToTypeReference());
496
void AddAttributes(ParameterDefinition parameter, DefaultUnresolvedParameter targetParameter)
498
if (!targetParameter.IsOut) {
500
targetParameter.Attributes.Add(inAttribute);
502
targetParameter.Attributes.Add(outAttribute);
504
if (parameter.HasCustomAttributes) {
505
AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes);
507
if (parameter.HasMarshalInfo) {
508
targetParameter.Attributes.Add(ConvertMarshalInfo(parameter.MarshalInfo));
513
#region Method Attributes
514
static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference();
515
static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true);
516
static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, false);
517
static readonly ITypeReference callingConventionTypeRef = typeof(CallingConvention).ToTypeReference();
518
static readonly IUnresolvedAttribute preserveSigAttribute = new DefaultUnresolvedAttribute(typeof(PreserveSigAttribute).ToTypeReference());
519
static readonly ITypeReference methodImplAttributeTypeRef = typeof(MethodImplAttribute).ToTypeReference();
520
static readonly ITypeReference methodImplOptionsTypeRef = typeof(MethodImplOptions).ToTypeReference();
522
static bool HasAnyAttributes(MethodDefinition methodDefinition)
524
if (methodDefinition.HasPInvokeInfo)
526
if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0)
528
if (methodDefinition.MethodReturnType.HasFieldMarshal)
530
return methodDefinition.HasCustomAttributes || methodDefinition.MethodReturnType.HasCustomAttributes;
533
void AddAttributes(MethodDefinition methodDefinition, IList<IUnresolvedAttribute> attributes, IList<IUnresolvedAttribute> returnTypeAttributes)
535
MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
537
#region DllImportAttribute
538
if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
539
PInvokeInfo info = methodDefinition.PInvokeInfo;
540
var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String });
541
dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, info.Module.Name));
543
if (info.IsBestFitDisabled)
544
dllImport.AddNamedFieldArgument("BestFitMapping", falseValue);
545
if (info.IsBestFitEnabled)
546
dllImport.AddNamedFieldArgument("BestFitMapping", trueValue);
548
CallingConvention callingConvention;
549
switch (info.Attributes & PInvokeAttributes.CallConvMask) {
550
case (PInvokeAttributes)0:
551
Debug.WriteLine ("P/Invoke calling convention not set on:" + methodDefinition.FullName);
552
callingConvention = CallingConvention.StdCall;
554
case PInvokeAttributes.CallConvCdecl:
555
callingConvention = CallingConvention.Cdecl;
557
case PInvokeAttributes.CallConvFastcall:
558
callingConvention = CallingConvention.FastCall;
560
case PInvokeAttributes.CallConvStdCall:
561
callingConvention = CallingConvention.StdCall;
563
case PInvokeAttributes.CallConvThiscall:
564
callingConvention = CallingConvention.ThisCall;
566
case PInvokeAttributes.CallConvWinapi:
567
callingConvention = CallingConvention.Winapi;
570
throw new NotSupportedException("unknown calling convention");
572
if (callingConvention != CallingConvention.Winapi)
573
dllImport.AddNamedFieldArgument("CallingConvention", CreateSimpleConstantValue(callingConventionTypeRef, (int)callingConvention));
575
CharSet charSet = CharSet.None;
576
switch (info.Attributes & PInvokeAttributes.CharSetMask) {
577
case PInvokeAttributes.CharSetAnsi:
578
charSet = CharSet.Ansi;
580
case PInvokeAttributes.CharSetAuto:
581
charSet = CharSet.Auto;
583
case PInvokeAttributes.CharSetUnicode:
584
charSet = CharSet.Unicode;
587
if (charSet != CharSet.None)
588
dllImport.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet));
590
if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name)
591
dllImport.AddNamedFieldArgument("EntryPoint", CreateSimpleConstantValue(KnownTypeReference.String, info.EntryPoint));
594
dllImport.AddNamedFieldArgument("ExactSpelling", trueValue);
596
if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
597
implAttributes &= ~MethodImplAttributes.PreserveSig;
599
dllImport.AddNamedFieldArgument("PreserveSig", falseValue);
601
if (info.SupportsLastError)
602
dllImport.AddNamedFieldArgument("SetLastError", trueValue);
604
if (info.IsThrowOnUnmappableCharDisabled)
605
dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", falseValue);
606
if (info.IsThrowOnUnmappableCharEnabled)
607
dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", trueValue);
609
attributes.Add(interningProvider.Intern(dllImport));
613
#region PreserveSigAttribute
614
if (implAttributes == MethodImplAttributes.PreserveSig) {
615
attributes.Add(preserveSigAttribute);
620
#region MethodImplAttribute
621
if (implAttributes != 0) {
622
var methodImpl = new DefaultUnresolvedAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef });
623
methodImpl.PositionalArguments.Add(CreateSimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes));
624
attributes.Add(interningProvider.Intern(methodImpl));
628
if (methodDefinition.HasCustomAttributes) {
629
AddCustomAttributes(methodDefinition.CustomAttributes, attributes);
631
if (methodDefinition.HasSecurityDeclarations) {
632
AddSecurityAttributes(methodDefinition.SecurityDeclarations, attributes);
634
if (methodDefinition.MethodReturnType.HasMarshalInfo) {
635
returnTypeAttributes.Add(ConvertMarshalInfo(methodDefinition.MethodReturnType.MarshalInfo));
637
if (methodDefinition.MethodReturnType.HasCustomAttributes) {
638
AddCustomAttributes(methodDefinition.MethodReturnType.CustomAttributes, returnTypeAttributes);
643
#region Type Attributes
644
static readonly DefaultUnresolvedAttribute serializableAttribute = new DefaultUnresolvedAttribute(typeof(SerializableAttribute).ToTypeReference());
645
static readonly DefaultUnresolvedAttribute comImportAttribute = new DefaultUnresolvedAttribute(typeof(ComImportAttribute).ToTypeReference());
646
static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference();
647
static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference();
648
static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference();
650
void AddAttributes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition targetEntity)
652
// SerializableAttribute
653
if (typeDefinition.IsSerializable)
654
targetEntity.Attributes.Add(serializableAttribute);
656
// ComImportAttribute
657
if (typeDefinition.IsImport)
658
targetEntity.Attributes.Add(comImportAttribute);
660
#region StructLayoutAttribute
661
LayoutKind layoutKind = LayoutKind.Auto;
662
switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) {
663
case TypeAttributes.SequentialLayout:
664
layoutKind = LayoutKind.Sequential;
666
case TypeAttributes.ExplicitLayout:
667
layoutKind = LayoutKind.Explicit;
670
CharSet charSet = CharSet.None;
671
switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) {
672
case TypeAttributes.AnsiClass:
673
charSet = CharSet.Ansi;
675
case TypeAttributes.AutoClass:
676
charSet = CharSet.Auto;
678
case TypeAttributes.UnicodeClass:
679
charSet = CharSet.Unicode;
682
LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto;
683
if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) {
684
DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef });
685
structLayout.PositionalArguments.Add(CreateSimpleConstantValue(layoutKindTypeRef, (int)layoutKind));
686
if (charSet != CharSet.Ansi) {
687
structLayout.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet));
689
if (typeDefinition.PackingSize > 0) {
690
structLayout.AddNamedFieldArgument("Pack", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.PackingSize));
692
if (typeDefinition.ClassSize > 0) {
693
structLayout.AddNamedFieldArgument("Size", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.ClassSize));
695
targetEntity.Attributes.Add(interningProvider.Intern(structLayout));
699
if (typeDefinition.HasCustomAttributes) {
700
AddCustomAttributes(typeDefinition.CustomAttributes, targetEntity.Attributes);
702
if (typeDefinition.HasSecurityDeclarations) {
703
AddSecurityAttributes(typeDefinition.SecurityDeclarations, targetEntity.Attributes);
708
#region Field Attributes
709
static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference();
710
static readonly IUnresolvedAttribute nonSerializedAttribute = new DefaultUnresolvedAttribute(typeof(NonSerializedAttribute).ToTypeReference());
712
void AddAttributes(FieldDefinition fieldDefinition, IUnresolvedEntity targetEntity)
714
// FieldOffsetAttribute
715
if (fieldDefinition.HasLayoutInfo) {
716
DefaultUnresolvedAttribute fieldOffset = new DefaultUnresolvedAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 });
717
fieldOffset.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset));
718
targetEntity.Attributes.Add(interningProvider.Intern(fieldOffset));
721
// NonSerializedAttribute
722
if (fieldDefinition.IsNotSerialized) {
723
targetEntity.Attributes.Add(nonSerializedAttribute);
726
if (fieldDefinition.HasMarshalInfo) {
727
targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo));
730
if (fieldDefinition.HasCustomAttributes) {
731
AddCustomAttributes(fieldDefinition.CustomAttributes, targetEntity.Attributes);
736
#region Event Attributes
737
void AddAttributes(EventDefinition eventDefinition, IUnresolvedEntity targetEntity)
739
if (eventDefinition.HasCustomAttributes) {
740
AddCustomAttributes(eventDefinition.CustomAttributes, targetEntity.Attributes);
745
#region Property Attributes
746
void AddAttributes(PropertyDefinition propertyDefinition, IUnresolvedEntity targetEntity)
748
if (propertyDefinition.HasCustomAttributes) {
749
AddCustomAttributes(propertyDefinition.CustomAttributes, targetEntity.Attributes);
754
#region MarshalAsAttribute (ConvertMarshalInfo)
755
static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference();
756
static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference();
758
IUnresolvedAttribute ConvertMarshalInfo(MarshalInfo marshalInfo)
760
DefaultUnresolvedAttribute attr = new DefaultUnresolvedAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef });
761
attr.PositionalArguments.Add(CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType));
763
FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
765
attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)fami.Size));
766
if (fami.ElementType != NativeType.None)
767
attr.AddNamedFieldArgument("ArraySubType", CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)fami.ElementType));
769
SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
770
if (sami != null && sami.ElementType != VariantType.None) {
771
attr.AddNamedFieldArgument("SafeArraySubType", CreateSimpleConstantValue(typeof(VarEnum).ToTypeReference(), (int)sami.ElementType));
773
ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo;
775
if (ami.ElementType != NativeType.Max)
776
attr.AddNamedFieldArgument("ArraySubType", CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)ami.ElementType));
778
attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)ami.Size));
779
if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0)
780
attr.AddNamedFieldArgument("SizeParamIndex", CreateSimpleConstantValue(KnownTypeReference.Int16, (short)ami.SizeParameterIndex));
782
CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
784
attr.AddNamedFieldArgument("MarshalType", CreateSimpleConstantValue(KnownTypeReference.String, cmi.ManagedType.FullName));
785
if (!string.IsNullOrEmpty(cmi.Cookie))
786
attr.AddNamedFieldArgument("MarshalCookie", CreateSimpleConstantValue(KnownTypeReference.String, cmi.Cookie));
788
FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo;
790
attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)fssmi.Size));
793
return InterningProvider.Intern(attr);
797
#region Custom Attributes (ReadAttribute)
798
void AddCustomAttributes(Mono.Collections.Generic.Collection<CustomAttribute> attributes, IList<IUnresolvedAttribute> targetCollection)
800
foreach (var cecilAttribute in attributes) {
801
TypeReference type = cecilAttribute.AttributeType;
802
if (type.Namespace == "System.Runtime.CompilerServices") {
803
if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute" || type.Name == "DecimalConstantAttribute")
805
} else if (type.Name == "ParamArrayAttribute" && type.Namespace == "System") {
808
targetCollection.Add(ReadAttribute(cecilAttribute));
812
[CLSCompliant(false)]
813
public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute)
815
if (attribute == null)
816
throw new ArgumentNullException("attribute");
817
MethodReference ctor = attribute.Constructor;
818
ITypeReference attributeType = ReadTypeReference(attribute.AttributeType);
819
IList<ITypeReference> ctorParameterTypes = EmptyList<ITypeReference>.Instance;
820
if (ctor.HasParameters) {
821
ctorParameterTypes = new ITypeReference[ctor.Parameters.Count];
822
for (int i = 0; i < ctorParameterTypes.Count; i++) {
823
ctorParameterTypes[i] = ReadTypeReference(ctor.Parameters[i].ParameterType);
825
ctorParameterTypes = interningProvider.InternList(ctorParameterTypes);
827
return interningProvider.Intern(new CecilUnresolvedAttribute(attributeType, ctorParameterTypes, attribute.GetBlob()));
831
#region CecilUnresolvedAttribute
832
static int GetBlobHashCode(byte[] blob)
836
foreach (byte b in blob) {
844
static bool BlobEquals(byte[] a, byte[] b)
846
if (a.Length != b.Length)
848
for (int i = 0; i < a.Length; i++) {
855
[Serializable, FastSerializerVersion(cecilLoaderVersion)]
856
sealed class CecilUnresolvedAttribute : IUnresolvedAttribute, ISupportsInterning
858
internal readonly ITypeReference attributeType;
859
internal readonly IList<ITypeReference> ctorParameterTypes;
860
internal readonly byte[] blob;
862
public CecilUnresolvedAttribute(ITypeReference attributeType, IList<ITypeReference> ctorParameterTypes, byte[] blob)
864
Debug.Assert(attributeType != null);
865
Debug.Assert(ctorParameterTypes != null);
866
Debug.Assert(blob != null);
867
this.attributeType = attributeType;
868
this.ctorParameterTypes = ctorParameterTypes;
872
DomRegion IUnresolvedAttribute.Region {
873
get { return DomRegion.Empty; }
876
IAttribute IUnresolvedAttribute.CreateResolvedAttribute(ITypeResolveContext context)
878
if (context.CurrentAssembly == null)
879
throw new InvalidOperationException("Cannot resolve CecilUnresolvedAttribute without a parent assembly");
880
return new CecilResolvedAttribute(context, this);
883
int ISupportsInterning.GetHashCodeForInterning()
885
return attributeType.GetHashCode() ^ ctorParameterTypes.GetHashCode() ^ GetBlobHashCode(blob);
888
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
890
CecilUnresolvedAttribute o = other as CecilUnresolvedAttribute;
891
return o != null && attributeType == o.attributeType && ctorParameterTypes == o.ctorParameterTypes
892
&& BlobEquals(blob, o.blob);
897
#region CecilResolvedAttribute
898
sealed class CecilResolvedAttribute : IAttribute
900
readonly ITypeResolveContext context;
901
readonly byte[] blob;
902
readonly IList<ITypeReference> ctorParameterTypes;
903
readonly IType attributeType;
906
volatile bool constructorResolved;
908
IList<ResolveResult> positionalArguments;
909
IList<KeyValuePair<IMember, ResolveResult>> namedArguments;
911
public CecilResolvedAttribute(ITypeResolveContext context, CecilUnresolvedAttribute unresolved)
913
this.context = context;
914
this.blob = unresolved.blob;
915
this.ctorParameterTypes = unresolved.ctorParameterTypes;
916
this.attributeType = unresolved.attributeType.Resolve(context);
919
public CecilResolvedAttribute(ITypeResolveContext context, IType attributeType)
921
this.context = context;
922
this.attributeType = attributeType;
923
this.ctorParameterTypes = EmptyList<ITypeReference>.Instance;
926
public DomRegion Region {
927
get { return DomRegion.Empty; }
930
public IType AttributeType {
931
get { return attributeType; }
934
public IMethod Constructor {
936
if (!constructorResolved) {
937
constructor = ResolveConstructor();
938
constructorResolved = true;
944
IMethod ResolveConstructor()
946
var parameterTypes = ctorParameterTypes.Resolve(context);
947
foreach (var ctor in attributeType.GetConstructors(m => m.Parameters.Count == parameterTypes.Count)) {
949
for (int i = 0; i < parameterTypes.Count; i++) {
950
if (!ctor.Parameters[i].Type.Equals(parameterTypes[i])) {
961
public IList<ResolveResult> PositionalArguments {
963
var result = LazyInit.VolatileRead(ref this.positionalArguments);
964
if (result != null) {
968
return positionalArguments;
972
public IList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
974
var result = LazyInit.VolatileRead(ref this.namedArguments);
975
if (result != null) {
979
return namedArguments;
983
public override string ToString()
985
return "[" + attributeType.ToString() + "(...)]";
990
var positionalArguments = new List<ResolveResult>();
991
var namedArguments = new List<KeyValuePair<IMember, ResolveResult>>();
992
DecodeBlob(positionalArguments, namedArguments);
993
Interlocked.CompareExchange(ref this.positionalArguments, positionalArguments, null);
994
Interlocked.CompareExchange(ref this.namedArguments, namedArguments, null);
997
void DecodeBlob(List<ResolveResult> positionalArguments, List<KeyValuePair<IMember, ResolveResult>> namedArguments)
1001
BlobReader reader = new BlobReader(blob, context.CurrentAssembly);
1002
if (reader.ReadUInt16() != 0x0001) {
1003
Debug.WriteLine("Unknown blob prolog");
1006
foreach (var ctorParameter in ctorParameterTypes.Resolve(context)) {
1007
ResolveResult arg = reader.ReadFixedArg(ctorParameter);
1008
positionalArguments.Add(arg);
1010
// After a decoding error, we must stop decoding the blob because
1011
// we might have read too few bytes due to the error.
1012
// Just fill up the remaining arguments with ErrorResolveResult:
1013
while (positionalArguments.Count < ctorParameterTypes.Count)
1014
positionalArguments.Add(ErrorResolveResult.UnknownError);
1018
ushort numNamed = reader.ReadUInt16();
1019
for (int i = 0; i < numNamed; i++) {
1020
var namedArg = reader.ReadNamedArg(attributeType);
1021
if (namedArg.Key != null)
1022
namedArguments.Add(namedArg);
1028
#region class BlobReader
1033
readonly IAssembly currentResolvedAssembly;
1035
public BlobReader(byte[] buffer, IAssembly currentResolvedAssembly)
1038
throw new ArgumentNullException("buffer");
1039
this.buffer = buffer;
1040
this.currentResolvedAssembly = currentResolvedAssembly;
1043
public byte ReadByte()
1045
return buffer[position++];
1048
public sbyte ReadSByte()
1051
return(sbyte) ReadByte();
1055
public byte[] ReadBytes(int length)
1057
var bytes = new byte[length];
1058
Buffer.BlockCopy(buffer, position, bytes, 0, length);
1063
public ushort ReadUInt16()
1066
ushort value =(ushort)(buffer[position]
1067
|(buffer[position + 1] << 8));
1073
public short ReadInt16()
1076
return(short) ReadUInt16();
1080
public uint ReadUInt32()
1083
uint value =(uint)(buffer[position]
1084
|(buffer[position + 1] << 8)
1085
|(buffer[position + 2] << 16)
1086
|(buffer[position + 3] << 24));
1092
public int ReadInt32()
1095
return(int) ReadUInt32();
1099
public ulong ReadUInt64()
1102
uint low = ReadUInt32();
1103
uint high = ReadUInt32();
1105
return(((ulong) high) << 32) | low;
1109
public long ReadInt64()
1112
return(long) ReadUInt64();
1116
public uint ReadCompressedUInt32()
1119
byte first = ReadByte();
1120
if((first & 0x80) == 0)
1123
if((first & 0x40) == 0)
1124
return((uint)(first & ~0x80) << 8)
1127
return((uint)(first & ~0xc0) << 24)
1128
|(uint) ReadByte() << 16
1129
|(uint) ReadByte() << 8
1134
public float ReadSingle()
1137
if(!BitConverter.IsLittleEndian) {
1138
var bytes = ReadBytes(4);
1139
Array.Reverse(bytes);
1140
return BitConverter.ToSingle(bytes, 0);
1143
float value = BitConverter.ToSingle(buffer, position);
1149
public double ReadDouble()
1152
if(!BitConverter.IsLittleEndian) {
1153
var bytes = ReadBytes(8);
1154
Array.Reverse(bytes);
1155
return BitConverter.ToDouble(bytes, 0);
1158
double value = BitConverter.ToDouble(buffer, position);
1164
public ResolveResult ReadFixedArg(IType argType)
1166
if (argType.Kind == TypeKind.Array) {
1167
if (((ArrayType)argType).Dimensions != 1) {
1168
// Only single-dimensional arrays are supported
1169
return ErrorResolveResult.UnknownError;
1171
IType elementType = ((ArrayType)argType).ElementType;
1172
uint numElem = ReadUInt32();
1173
if (numElem == 0xffffffff) {
1175
return new ConstantResolveResult(argType, null);
1177
ResolveResult[] elements = new ResolveResult[numElem];
1178
for (int i = 0; i < elements.Length; i++) {
1179
elements[i] = ReadElem(elementType);
1180
// Stop decoding when encountering an error:
1181
if (elements[i].IsError)
1182
return ErrorResolveResult.UnknownError;
1184
IType int32 = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Int32);
1185
ResolveResult[] sizeArgs = { new ConstantResolveResult(int32, elements.Length) };
1186
return new ArrayCreateResolveResult(argType, sizeArgs, elements);
1189
return ReadElem(argType);
1193
public ResolveResult ReadElem(IType elementType)
1195
ITypeDefinition underlyingType;
1196
if (elementType.Kind == TypeKind.Enum) {
1197
underlyingType = elementType.GetDefinition().EnumUnderlyingType.GetDefinition();
1199
underlyingType = elementType.GetDefinition();
1201
if (underlyingType == null)
1202
return ErrorResolveResult.UnknownError;
1203
KnownTypeCode typeCode = underlyingType.KnownTypeCode;
1204
if (typeCode == KnownTypeCode.Object) {
1206
IType boxedTyped = ReadCustomAttributeFieldOrPropType();
1207
ResolveResult elem = ReadElem(boxedTyped);
1208
if (elem.IsCompileTimeConstant && elem.ConstantValue == null)
1209
return new ConstantResolveResult(elementType, null);
1211
return new ConversionResolveResult(elementType, elem, Conversion.BoxingConversion);
1212
} else if (typeCode == KnownTypeCode.Type) {
1213
return new TypeOfResolveResult(underlyingType, ReadType());
1215
return new ConstantResolveResult(elementType, ReadElemValue(typeCode));
1219
object ReadElemValue(KnownTypeCode typeCode)
1222
case KnownTypeCode.Boolean:
1223
return ReadByte() != 0;
1224
case KnownTypeCode.Char:
1225
return (char)ReadUInt16();
1226
case KnownTypeCode.SByte:
1228
case KnownTypeCode.Byte:
1230
case KnownTypeCode.Int16:
1232
case KnownTypeCode.UInt16:
1233
return ReadUInt16();
1234
case KnownTypeCode.Int32:
1236
case KnownTypeCode.UInt32:
1237
return ReadUInt32();
1238
case KnownTypeCode.Int64:
1240
case KnownTypeCode.UInt64:
1241
return ReadUInt64();
1242
case KnownTypeCode.Single:
1243
return ReadSingle();
1244
case KnownTypeCode.Double:
1245
return ReadDouble();
1246
case KnownTypeCode.String:
1247
return ReadSerString();
1249
throw new NotSupportedException();
1253
public string ReadSerString ()
1255
if (buffer [position] == 0xff) {
1260
int length = (int) ReadCompressedUInt32();
1262
return string.Empty;
1264
string @string = System.Text.Encoding.UTF8.GetString(
1266
buffer [position + length - 1] == 0 ? length - 1 : length);
1272
public KeyValuePair<IMember, ResolveResult> ReadNamedArg(IType attributeType)
1274
EntityType memberType;
1278
memberType = EntityType.Field;
1281
memberType = EntityType.Property;
1284
throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b));
1286
IType type = ReadCustomAttributeFieldOrPropType();
1287
string name = ReadSerString();
1288
ResolveResult val = ReadFixedArg(type);
1289
IMember member = null;
1290
// Use last matching member, as GetMembers() returns members from base types first.
1291
foreach (IMember m in attributeType.GetMembers(m => m.EntityType == memberType && m.Name == name)) {
1292
if (m.ReturnType.Equals(type))
1295
return new KeyValuePair<IMember, ResolveResult>(member, val);
1298
IType ReadCustomAttributeFieldOrPropType()
1300
ICompilation compilation = currentResolvedAssembly.Compilation;
1304
return compilation.FindType(KnownTypeCode.Boolean);
1306
return compilation.FindType(KnownTypeCode.Char);
1308
return compilation.FindType(KnownTypeCode.SByte);
1310
return compilation.FindType(KnownTypeCode.Byte);
1312
return compilation.FindType(KnownTypeCode.Int16);
1314
return compilation.FindType(KnownTypeCode.UInt16);
1316
return compilation.FindType(KnownTypeCode.Int32);
1318
return compilation.FindType(KnownTypeCode.UInt32);
1320
return compilation.FindType(KnownTypeCode.Int64);
1322
return compilation.FindType(KnownTypeCode.UInt64);
1324
return compilation.FindType(KnownTypeCode.Single);
1326
return compilation.FindType(KnownTypeCode.Double);
1328
return compilation.FindType(KnownTypeCode.String);
1330
return new ArrayType(compilation, ReadCustomAttributeFieldOrPropType());
1332
return compilation.FindType(KnownTypeCode.Type);
1333
case 0x51: // boxed value type
1334
return compilation.FindType(KnownTypeCode.Object);
1338
throw new NotSupportedException(string.Format("Custom attribute type 0x{0:x} is not supported.", b));
1344
string typeName = ReadSerString();
1345
ITypeReference typeReference = ReflectionHelper.ParseReflectionName(typeName);
1346
IType typeInCurrentAssembly = typeReference.Resolve(new SimpleTypeResolveContext(currentResolvedAssembly));
1347
if (typeInCurrentAssembly.Kind != TypeKind.Unknown)
1348
return typeInCurrentAssembly;
1350
// look for the type in mscorlib
1351
ITypeDefinition systemObject = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Object).GetDefinition();
1352
if (systemObject != null) {
1353
return typeReference.Resolve(new SimpleTypeResolveContext(systemObject.ParentAssembly));
1355
// couldn't find corlib - return the unknown IType for the current assembly
1356
return typeInCurrentAssembly;
1362
#region Security Attributes
1363
static readonly ITypeReference securityActionTypeReference = typeof(System.Security.Permissions.SecurityAction).ToTypeReference();
1364
static readonly ITypeReference permissionSetAttributeTypeReference = typeof(System.Security.Permissions.PermissionSetAttribute).ToTypeReference();
1367
/// Reads a security declaration.
1369
[CLSCompliant(false)]
1370
public IList<IUnresolvedAttribute> ReadSecurityDeclaration(SecurityDeclaration secDecl)
1372
if (secDecl == null)
1373
throw new ArgumentNullException("secDecl");
1374
var result = new List<IUnresolvedAttribute>();
1375
AddSecurityAttributes(secDecl, result);
1379
void AddSecurityAttributes(Mono.Collections.Generic.Collection<SecurityDeclaration> securityDeclarations, IList<IUnresolvedAttribute> targetCollection)
1381
foreach (var secDecl in securityDeclarations) {
1382
AddSecurityAttributes(secDecl, targetCollection);
1386
void AddSecurityAttributes(SecurityDeclaration secDecl, IList<IUnresolvedAttribute> targetCollection)
1388
byte[] blob = secDecl.GetBlob();
1389
BlobReader reader = new BlobReader(blob, null);
1390
var securityAction = new SimpleConstantValue(securityActionTypeReference, (int)secDecl.Action);
1391
if (reader.ReadByte() == '.') {
1393
uint attributeCount = reader.ReadCompressedUInt32();
1394
UnresolvedSecurityDeclaration unresolvedSecDecl = new UnresolvedSecurityDeclaration(securityAction, blob);
1395
unresolvedSecDecl = interningProvider.Intern(unresolvedSecDecl);
1396
for (uint i = 0; i < attributeCount; i++) {
1397
targetCollection.Add(interningProvider.Intern(new UnresolvedSecurityAttribute(unresolvedSecDecl, (int)i)));
1400
// for backward compatibility with .NET 1.0: XML-encoded attribute
1401
var attr = new DefaultUnresolvedAttribute(permissionSetAttributeTypeReference);
1402
attr.ConstructorParameterTypes.Add(securityActionTypeReference);
1403
attr.PositionalArguments.Add(securityAction);
1404
string xml = System.Text.Encoding.Unicode.GetString(blob);
1405
attr.AddNamedPropertyArgument("XML", CreateSimpleConstantValue(KnownTypeReference.String, xml));
1406
targetCollection.Add(interningProvider.Intern(attr));
1410
[Serializable, FastSerializerVersion(cecilLoaderVersion)]
1411
sealed class UnresolvedSecurityDeclaration : ISupportsInterning
1413
readonly IConstantValue securityAction;
1414
readonly byte[] blob;
1416
public UnresolvedSecurityDeclaration(IConstantValue securityAction, byte[] blob)
1418
Debug.Assert(securityAction != null);
1419
Debug.Assert(blob != null);
1420
this.securityAction = securityAction;
1424
public IList<IAttribute> Resolve(IAssembly currentAssembly)
1426
// TODO: make this a per-assembly cache
1427
// CacheManager cache = currentAssembly.Compilation.CacheManager;
1428
// IList<IAttribute> result = (IList<IAttribute>)cache.GetShared(this);
1429
// if (result != null)
1432
ITypeResolveContext context = new SimpleTypeResolveContext(currentAssembly);
1433
BlobReader reader = new BlobReader(blob, currentAssembly);
1434
if (reader.ReadByte() != '.') {
1435
// should not use UnresolvedSecurityDeclaration for XML secdecls
1436
throw new InvalidOperationException();
1438
ResolveResult securityActionRR = securityAction.Resolve(context);
1439
uint attributeCount = reader.ReadCompressedUInt32();
1440
IAttribute[] attributes = new IAttribute[attributeCount];
1442
ReadSecurityBlob(reader, attributes, context, securityActionRR);
1443
} catch (NotSupportedException ex) {
1444
// ignore invalid blobs
1445
Debug.WriteLine(ex.ToString());
1447
for (int i = 0; i < attributes.Length; i++) {
1448
if (attributes[i] == null)
1449
attributes[i] = new CecilResolvedAttribute(context, SpecialType.UnknownType);
1452
// return (IList<IAttribute>)cache.GetOrAddShared(this, attributes);
1455
void ReadSecurityBlob(BlobReader reader, IAttribute[] attributes, ITypeResolveContext context, ResolveResult securityActionRR)
1457
for (int i = 0; i < attributes.Length; i++) {
1458
string attributeTypeName = reader.ReadSerString();
1459
ITypeReference attributeTypeRef = ReflectionHelper.ParseReflectionName(attributeTypeName);
1460
IType attributeType = attributeTypeRef.Resolve(context);
1462
reader.ReadCompressedUInt32(); // ??
1463
// The specification seems to be incorrect here, so I'm using the logic from Cecil instead.
1464
uint numNamed = reader.ReadCompressedUInt32();
1466
var namedArgs = new List<KeyValuePair<IMember, ResolveResult>>((int)numNamed);
1467
for (uint j = 0; j < numNamed; j++) {
1468
var namedArg = reader.ReadNamedArg(attributeType);
1469
if (namedArg.Key != null)
1470
namedArgs.Add(namedArg);
1473
attributes[i] = new DefaultAttribute(
1475
positionalArguments: new ResolveResult[] { securityActionRR },
1476
namedArguments: namedArgs);
1480
int ISupportsInterning.GetHashCodeForInterning()
1482
return securityAction.GetHashCode() ^ GetBlobHashCode(blob);
1485
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
1487
UnresolvedSecurityDeclaration o = other as UnresolvedSecurityDeclaration;
1488
return o != null && securityAction == o.securityAction && BlobEquals(blob, o.blob);
1492
[Serializable, FastSerializerVersion(cecilLoaderVersion)]
1493
sealed class UnresolvedSecurityAttribute : IUnresolvedAttribute, ISupportsInterning
1495
readonly UnresolvedSecurityDeclaration secDecl;
1498
public UnresolvedSecurityAttribute(UnresolvedSecurityDeclaration secDecl, int index)
1500
Debug.Assert(secDecl != null);
1501
this.secDecl = secDecl;
1505
DomRegion IUnresolvedAttribute.Region {
1506
get { return DomRegion.Empty; }
1509
IAttribute IUnresolvedAttribute.CreateResolvedAttribute(ITypeResolveContext context)
1511
return secDecl.Resolve(context.CurrentAssembly)[index];
1514
int ISupportsInterning.GetHashCodeForInterning()
1516
return index ^ secDecl.GetHashCode();
1519
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
1521
UnresolvedSecurityAttribute attr = other as UnresolvedSecurityAttribute;
1522
return attr != null && index == attr.index && secDecl == attr.secDecl;
1528
#region Read Type Definition
1529
DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinition typeDefinition)
1531
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(typeDefinition.Name);
1532
var td = new DefaultUnresolvedTypeDefinition(typeDefinition.Namespace, name);
1533
if (typeDefinition.HasGenericParameters)
1534
InitTypeParameters(typeDefinition, td.TypeParameters);
1538
static void InitTypeParameters(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters)
1540
// Type parameters are initialized within the constructor so that the class can be put into the type storage
1541
// before the rest of the initialization runs - this allows it to be available for early binding as soon as possible.
1542
for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) {
1543
if (typeDefinition.GenericParameters[i].Position != i)
1544
throw new InvalidOperationException("g.Position != i");
1545
typeParameters.Add(new DefaultUnresolvedTypeParameter(
1546
EntityType.TypeDefinition, i, typeDefinition.GenericParameters[i].Name));
1550
void InitTypeParameterConstraints(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters)
1552
for (int i = 0; i < typeParameters.Count; i++) {
1553
var tp = (DefaultUnresolvedTypeParameter)typeParameters[i];
1554
AddConstraints(tp, typeDefinition.GenericParameters[i]);
1555
tp.ApplyInterningProvider(interningProvider);
1559
void InitTypeDefinition(TypeDefinition typeDefinition, DefaultUnresolvedTypeDefinition td)
1561
td.Kind = GetTypeKind(typeDefinition);
1562
InitTypeModifiers(typeDefinition, td);
1563
InitTypeParameterConstraints(typeDefinition, td.TypeParameters);
1565
// nested types can be initialized only after generic parameters were created
1566
InitNestedTypes(typeDefinition, td, td.NestedTypes);
1567
AddAttributes(typeDefinition, td);
1568
td.HasExtensionMethods = HasExtensionAttribute(typeDefinition);
1570
InitBaseTypes(typeDefinition, td.BaseTypes);
1572
td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum);
1573
InitMembers(typeDefinition, td, td.Members);
1574
td.ApplyInterningProvider(interningProvider);
1576
RegisterCecilObject(td, typeDefinition);
1579
void InitBaseTypes(TypeDefinition typeDefinition, IList<ITypeReference> baseTypes)
1582
if (typeDefinition.IsEnum) {
1583
foreach (FieldDefinition enumField in typeDefinition.Fields) {
1584
if (!enumField.IsStatic) {
1585
baseTypes.Add(ReadTypeReference(enumField.FieldType));
1590
if (typeDefinition.BaseType != null) {
1591
baseTypes.Add(ReadTypeReference(typeDefinition.BaseType));
1593
if (typeDefinition.HasInterfaces) {
1594
foreach (TypeReference iface in typeDefinition.Interfaces) {
1595
baseTypes.Add(ReadTypeReference(iface));
1601
void InitNestedTypes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition declaringTypeDefinition, IList<IUnresolvedTypeDefinition> nestedTypes)
1603
if (!typeDefinition.HasNestedTypes)
1605
foreach (TypeDefinition nestedTypeDef in typeDefinition.NestedTypes) {
1606
TypeAttributes visibility = nestedTypeDef.Attributes & TypeAttributes.VisibilityMask;
1607
if (this.IncludeInternalMembers
1608
|| visibility == TypeAttributes.NestedPublic
1609
|| visibility == TypeAttributes.NestedFamily
1610
|| visibility == TypeAttributes.NestedFamORAssem)
1612
string name = nestedTypeDef.Name;
1613
int pos = name.LastIndexOf('/');
1615
name = name.Substring(pos + 1);
1616
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
1617
var nestedType = new DefaultUnresolvedTypeDefinition(declaringTypeDefinition, name);
1618
InitTypeParameters(nestedTypeDef, nestedType.TypeParameters);
1619
nestedTypes.Add(nestedType);
1620
InitTypeDefinition(nestedTypeDef, nestedType);
1625
static TypeKind GetTypeKind(TypeDefinition typeDefinition)
1628
if (typeDefinition.IsInterface) {
1629
return TypeKind.Interface;
1630
} else if (typeDefinition.IsEnum) {
1631
return TypeKind.Enum;
1632
} else if (typeDefinition.IsValueType) {
1633
return TypeKind.Struct;
1634
} else if (IsDelegate(typeDefinition)) {
1635
return TypeKind.Delegate;
1636
} else if (IsModule(typeDefinition)) {
1637
return TypeKind.Module;
1639
return TypeKind.Class;
1643
static void InitTypeModifiers(TypeDefinition typeDefinition, AbstractUnresolvedEntity td)
1645
td.IsSealed = typeDefinition.IsSealed;
1646
td.IsAbstract = typeDefinition.IsAbstract;
1647
switch (typeDefinition.Attributes & TypeAttributes.VisibilityMask) {
1648
case TypeAttributes.NotPublic:
1649
case TypeAttributes.NestedAssembly:
1650
td.Accessibility = Accessibility.Internal;
1652
case TypeAttributes.Public:
1653
case TypeAttributes.NestedPublic:
1654
td.Accessibility = Accessibility.Public;
1656
case TypeAttributes.NestedPrivate:
1657
td.Accessibility = Accessibility.Private;
1659
case TypeAttributes.NestedFamily:
1660
td.Accessibility = Accessibility.Protected;
1662
case TypeAttributes.NestedFamANDAssem:
1663
td.Accessibility = Accessibility.ProtectedAndInternal;
1665
case TypeAttributes.NestedFamORAssem:
1666
td.Accessibility = Accessibility.ProtectedOrInternal;
1671
static bool IsDelegate(TypeDefinition type)
1673
if (type.BaseType != null && type.BaseType.Namespace == "System") {
1674
if (type.BaseType.Name == "MulticastDelegate")
1676
if (type.BaseType.Name == "Delegate" && type.Name != "MulticastDelegate")
1682
static bool IsModule(TypeDefinition type)
1684
if (!type.HasCustomAttributes)
1686
foreach (var att in type.CustomAttributes) {
1687
if (att.AttributeType.FullName == "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute"
1688
|| att.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute")
1696
void InitMembers(TypeDefinition typeDefinition, IUnresolvedTypeDefinition td, IList<IUnresolvedMember> members)
1698
if (typeDefinition.HasMethods) {
1699
foreach (MethodDefinition method in typeDefinition.Methods) {
1700
if (IsVisible(method.Attributes) && !IsAccessor(method.SemanticsAttributes)) {
1701
EntityType type = EntityType.Method;
1702
if (method.IsSpecialName) {
1703
if (method.IsConstructor)
1704
type = EntityType.Constructor;
1705
else if (method.Name.StartsWith("op_", StringComparison.Ordinal))
1706
type = EntityType.Operator;
1708
members.Add(ReadMethod(method, td, type));
1712
if (typeDefinition.HasFields) {
1713
foreach (FieldDefinition field in typeDefinition.Fields) {
1714
if (IsVisible(field.Attributes) && !field.IsSpecialName) {
1715
members.Add(ReadField(field, td));
1719
if (typeDefinition.HasProperties) {
1720
string defaultMemberName = null;
1721
var defaultMemberAttribute = typeDefinition.CustomAttributes.FirstOrDefault(
1722
a => a.AttributeType.FullName == typeof(System.Reflection.DefaultMemberAttribute).FullName);
1723
if (defaultMemberAttribute != null && defaultMemberAttribute.ConstructorArguments.Count == 1) {
1724
defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string;
1726
foreach (PropertyDefinition property in typeDefinition.Properties) {
1727
bool getterVisible = property.GetMethod != null && IsVisible(property.GetMethod.Attributes);
1728
bool setterVisible = property.SetMethod != null && IsVisible(property.SetMethod.Attributes);
1729
if (getterVisible || setterVisible) {
1730
EntityType type = EntityType.Property;
1731
if (property.HasParameters) {
1732
// Try to detect indexer:
1733
if (property.Name == defaultMemberName) {
1734
type = EntityType.Indexer; // normal indexer
1735
} else if (property.Name.EndsWith(".Item", StringComparison.Ordinal) && (property.GetMethod ?? property.SetMethod).HasOverrides) {
1736
// explicit interface implementation of indexer
1737
type = EntityType.Indexer;
1738
// We can't really tell parameterized properties and indexers apart in this case without
1739
// resolving the interface, so we rely on the "Item" naming convention instead.
1742
members.Add(ReadProperty(property, td, type));
1746
if (typeDefinition.HasEvents) {
1747
foreach (EventDefinition ev in typeDefinition.Events) {
1748
if (ev.AddMethod != null && IsVisible(ev.AddMethod.Attributes)) {
1749
members.Add(ReadEvent(ev, td));
1755
static bool IsAccessor(MethodSemanticsAttributes semantics)
1757
return !(semantics == MethodSemanticsAttributes.None || semantics == MethodSemanticsAttributes.Other);
1761
#region Lazy-Loaded Type Definition
1762
sealed class LazyCecilTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition
1764
readonly CecilLoader loader;
1765
readonly string namespaceName;
1766
readonly TypeDefinition cecilTypeDef;
1767
readonly TypeKind kind;
1768
readonly IList<IUnresolvedTypeParameter> typeParameters;
1770
IList<ITypeReference> baseTypes;
1771
IList<IUnresolvedTypeDefinition> nestedTypes;
1772
IList<IUnresolvedMember> members;
1774
public LazyCecilTypeDefinition(CecilLoader loader, TypeDefinition typeDefinition)
1776
this.loader = loader;
1777
this.cecilTypeDef = typeDefinition;
1778
this.EntityType = EntityType.TypeDefinition;
1779
this.namespaceName = cecilTypeDef.Namespace;
1780
this.Name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(cecilTypeDef.Name);
1781
var tps = new List<IUnresolvedTypeParameter>();
1782
InitTypeParameters(cecilTypeDef, tps);
1783
this.typeParameters = FreezableHelper.FreezeList(tps);
1785
this.kind = GetTypeKind(typeDefinition);
1786
InitTypeModifiers(typeDefinition, this);
1787
loader.InitTypeParameterConstraints(typeDefinition, typeParameters);
1789
loader.AddAttributes(typeDefinition, this);
1790
flags[FlagHasExtensionMethods] = HasExtensionAttribute(typeDefinition);
1792
this.ApplyInterningProvider(loader.interningProvider);
1796
public override string Namespace {
1797
get { return namespaceName; }
1798
set { throw new NotSupportedException(); }
1801
public override string ReflectionName {
1802
get { return cecilTypeDef.FullName; }
1805
public FullTypeName FullTypeName {
1807
return new TopLevelTypeName(namespaceName, this.Name, typeParameters.Count);
1811
public TypeKind Kind {
1812
get { return kind; }
1815
public IList<IUnresolvedTypeParameter> TypeParameters {
1816
get { return typeParameters; }
1819
public IList<ITypeReference> BaseTypes {
1821
var result = LazyInit.VolatileRead(ref this.baseTypes);
1822
if (result != null) {
1825
lock (loader.currentModule) {
1826
result = new List<ITypeReference>();
1827
loader.InitBaseTypes(cecilTypeDef, result);
1828
return LazyInit.GetOrSet(ref this.baseTypes, FreezableHelper.FreezeList(result));
1833
public IList<IUnresolvedTypeDefinition> NestedTypes {
1835
var result = LazyInit.VolatileRead(ref this.nestedTypes);
1836
if (result != null) {
1839
lock (loader.currentModule) {
1840
if (this.nestedTypes != null)
1841
return this.nestedTypes;
1842
result = new List<IUnresolvedTypeDefinition>();
1843
loader.InitNestedTypes(cecilTypeDef, this, result);
1844
return LazyInit.GetOrSet(ref this.nestedTypes, FreezableHelper.FreezeList(result));
1849
public IList<IUnresolvedMember> Members {
1851
var result = LazyInit.VolatileRead(ref this.members);
1852
if (result != null) {
1855
lock (loader.currentModule) {
1856
if (this.members != null)
1857
return this.members;
1858
result = new List<IUnresolvedMember>();
1859
loader.InitMembers(cecilTypeDef, this, result);
1860
return LazyInit.GetOrSet(ref this.members, FreezableHelper.FreezeList(result));
1865
public IEnumerable<IUnresolvedMethod> Methods {
1866
get { return Members.OfType<IUnresolvedMethod>(); }
1869
public IEnumerable<IUnresolvedProperty> Properties {
1870
get { return Members.OfType<IUnresolvedProperty>(); }
1873
public IEnumerable<IUnresolvedField> Fields {
1874
get { return Members.OfType<IUnresolvedField>(); }
1877
public IEnumerable<IUnresolvedEvent> Events {
1878
get { return Members.OfType<IUnresolvedEvent>(); }
1881
public bool AddDefaultConstructorIfRequired {
1882
get { return kind == TypeKind.Struct || kind == TypeKind.Enum; }
1885
public bool? HasExtensionMethods {
1886
get { return flags[FlagHasExtensionMethods]; }
1887
// we always return true or false, never null.
1888
// FlagHasNoExtensionMethods is unused in LazyCecilTypeDefinition
1891
public override object Clone()
1893
throw new NotSupportedException();
1896
public IType Resolve(ITypeResolveContext context)
1898
if (context == null)
1899
throw new ArgumentNullException("context");
1900
if (context.CurrentAssembly == null)
1901
throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly.");
1902
return context.CurrentAssembly.GetTypeDefinition(this.FullTypeName)
1903
?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count);
1906
public ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext)
1908
return parentContext;
1914
[CLSCompliant(false)]
1915
public IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, EntityType methodType = EntityType.Method)
1917
return ReadMethod(method, parentType, methodType, null);
1920
IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, EntityType methodType, IUnresolvedMember accessorOwner)
1924
DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, method.Name);
1925
m.EntityType = methodType;
1926
m.AccessorOwner = accessorOwner;
1927
m.HasBody = method.HasBody;
1928
if (method.HasGenericParameters) {
1929
for (int i = 0; i < method.GenericParameters.Count; i++) {
1930
if (method.GenericParameters[i].Position != i)
1931
throw new InvalidOperationException("g.Position != i");
1932
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(
1933
EntityType.Method, i, method.GenericParameters[i].Name));
1935
for (int i = 0; i < method.GenericParameters.Count; i++) {
1936
var tp = (DefaultUnresolvedTypeParameter)m.TypeParameters[i];
1937
AddConstraints(tp, method.GenericParameters[i]);
1938
tp.ApplyInterningProvider(interningProvider);
1942
m.ReturnType = ReadTypeReference(method.ReturnType, typeAttributes: method.MethodReturnType);
1944
if (HasAnyAttributes(method))
1945
AddAttributes(method, m.Attributes, m.ReturnTypeAttributes);
1946
TranslateModifiers(method, m);
1948
if (method.HasParameters) {
1949
foreach (ParameterDefinition p in method.Parameters) {
1950
m.Parameters.Add(ReadParameter(p));
1954
// mark as extension method if the attribute is set
1955
if (method.IsStatic && HasExtensionAttribute(method)) {
1956
m.IsExtensionMethod = true;
1959
int lastDot = method.Name.LastIndexOf('.');
1960
if (lastDot >= 0 && method.HasOverrides) {
1961
// To be consistent with the parser-initialized type system, shorten the method name:
1962
m.Name = method.Name.Substring(lastDot + 1);
1963
m.IsExplicitInterfaceImplementation = true;
1964
foreach (var or in method.Overrides) {
1965
m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(
1966
accessorOwner != null ? EntityType.Accessor : EntityType.Method,
1967
ReadTypeReference(or.DeclaringType),
1968
or.Name, or.GenericParameters.Count, m.Parameters.Select(p => p.Type).ToList()));
1972
FinishReadMember(m, method);
1976
static bool HasExtensionAttribute(ICustomAttributeProvider provider)
1978
if (provider.HasCustomAttributes) {
1979
foreach (var attr in provider.CustomAttributes) {
1980
if (attr.AttributeType.Name == "ExtensionAttribute" && attr.AttributeType.Namespace == "System.Runtime.CompilerServices")
1987
bool IsVisible(MethodAttributes att)
1989
att &= MethodAttributes.MemberAccessMask;
1990
return IncludeInternalMembers
1991
|| att == MethodAttributes.Public
1992
|| att == MethodAttributes.Family
1993
|| att == MethodAttributes.FamORAssem;
1996
static Accessibility GetAccessibility(MethodAttributes attr)
1998
switch (attr & MethodAttributes.MemberAccessMask) {
1999
case MethodAttributes.Public:
2000
return Accessibility.Public;
2001
case MethodAttributes.FamANDAssem:
2002
return Accessibility.ProtectedAndInternal;
2003
case MethodAttributes.Assembly:
2004
return Accessibility.Internal;
2005
case MethodAttributes.Family:
2006
return Accessibility.Protected;
2007
case MethodAttributes.FamORAssem:
2008
return Accessibility.ProtectedOrInternal;
2010
return Accessibility.Private;
2014
void TranslateModifiers(MethodDefinition method, AbstractUnresolvedMember m)
2016
if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) {
2017
// interface members don't have modifiers, but we want to handle them as "public abstract"
2018
m.Accessibility = Accessibility.Public;
2019
m.IsAbstract = true;
2021
m.Accessibility = GetAccessibility(method.Attributes);
2022
if (method.IsAbstract) {
2023
m.IsAbstract = true;
2024
m.IsOverride = !method.IsNewSlot;
2025
} else if (method.IsFinal) {
2026
if (!method.IsNewSlot) {
2028
m.IsOverride = true;
2030
} else if (method.IsVirtual) {
2031
if (method.IsNewSlot)
2034
m.IsOverride = true;
2036
m.IsStatic = method.IsStatic;
2041
#region Read Parameter
2042
[CLSCompliant(false)]
2043
public IUnresolvedParameter ReadParameter(ParameterDefinition parameter)
2045
if (parameter == null)
2046
throw new ArgumentNullException("parameter");
2047
var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter);
2048
var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(parameter.Name));
2050
if (parameter.ParameterType is Mono.Cecil.ByReferenceType) {
2051
if (!parameter.IsIn && parameter.IsOut)
2056
AddAttributes(parameter, p);
2058
if (parameter.IsOptional) {
2059
p.DefaultValue = CreateSimpleConstantValue(type, parameter.Constant);
2062
if (parameter.ParameterType is Mono.Cecil.ArrayType) {
2063
foreach (CustomAttribute att in parameter.CustomAttributes) {
2064
if (att.AttributeType.FullName == typeof(ParamArrayAttribute).FullName) {
2071
return interningProvider.Intern(p);
2076
bool IsVisible(FieldAttributes att)
2078
att &= FieldAttributes.FieldAccessMask;
2079
return IncludeInternalMembers
2080
|| att == FieldAttributes.Public
2081
|| att == FieldAttributes.Family
2082
|| att == FieldAttributes.FamORAssem;
2085
decimal? TryDecodeDecimalConstantAttribute(CustomAttribute attribute)
2087
if (attribute.ConstructorArguments.Count != 5)
2090
BlobReader reader = new BlobReader(attribute.GetBlob(), null);
2091
if (reader.ReadUInt16() != 0x0001) {
2092
Debug.WriteLine("Unknown blob prolog");
2096
// DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
2097
// Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
2098
var ctorArgs = new object[attribute.ConstructorArguments.Count];
2099
for (int i = 0; i < ctorArgs.Length; i++) {
2100
switch (attribute.ConstructorArguments[i].Type.FullName) {
2102
ctorArgs[i] = reader.ReadByte();
2104
case "System.Int32":
2105
ctorArgs[i] = reader.ReadInt32();
2107
case "System.UInt32":
2108
ctorArgs[i] = unchecked((int)reader.ReadUInt32());
2115
if (!ctorArgs.Select(a => a.GetType()).SequenceEqual(new[] { typeof(byte), typeof(byte), typeof(int), typeof(int), typeof(int) }))
2118
return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]);
2121
[CLSCompliant(false)]
2122
public IUnresolvedField ReadField(FieldDefinition field, IUnresolvedTypeDefinition parentType)
2125
throw new ArgumentNullException("field");
2126
if (parentType == null)
2127
throw new ArgumentNullException("parentType");
2129
DefaultUnresolvedField f = new DefaultUnresolvedField(parentType, field.Name);
2130
f.Accessibility = GetAccessibility(field.Attributes);
2131
f.IsReadOnly = field.IsInitOnly;
2132
f.IsStatic = field.IsStatic;
2133
f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field);
2134
if (field.HasConstant) {
2135
f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, field.Constant);
2138
var decConstant = field.CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.DecimalConstantAttribute");
2139
if (decConstant != null) {
2140
var constValue = TryDecodeDecimalConstantAttribute(decConstant);
2141
if (constValue != null)
2142
f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, constValue);
2145
AddAttributes(field, f);
2147
RequiredModifierType modreq = field.FieldType as RequiredModifierType;
2148
if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName) {
2149
f.IsVolatile = true;
2152
FinishReadMember(f, field);
2156
static Accessibility GetAccessibility(FieldAttributes attr)
2158
switch (attr & FieldAttributes.FieldAccessMask) {
2159
case FieldAttributes.Public:
2160
return Accessibility.Public;
2161
case FieldAttributes.FamANDAssem:
2162
return Accessibility.ProtectedAndInternal;
2163
case FieldAttributes.Assembly:
2164
return Accessibility.Internal;
2165
case FieldAttributes.Family:
2166
return Accessibility.Protected;
2167
case FieldAttributes.FamORAssem:
2168
return Accessibility.ProtectedOrInternal;
2170
return Accessibility.Private;
2175
#region Type Parameter Constraints
2176
void AddConstraints(DefaultUnresolvedTypeParameter tp, GenericParameter g)
2178
switch (g.Attributes & GenericParameterAttributes.VarianceMask) {
2179
case GenericParameterAttributes.Contravariant:
2180
tp.Variance = VarianceModifier.Contravariant;
2182
case GenericParameterAttributes.Covariant:
2183
tp.Variance = VarianceModifier.Covariant;
2187
tp.HasReferenceTypeConstraint = g.HasReferenceTypeConstraint;
2188
tp.HasValueTypeConstraint = g.HasNotNullableValueTypeConstraint;
2189
tp.HasDefaultConstructorConstraint = g.HasDefaultConstructorConstraint;
2191
if (g.HasConstraints) {
2192
foreach (TypeReference constraint in g.Constraints) {
2193
tp.Constraints.Add(ReadTypeReference(constraint));
2199
#region Read Property
2201
[CLSCompliant(false)]
2202
public IUnresolvedProperty ReadProperty(PropertyDefinition property, IUnresolvedTypeDefinition parentType, EntityType propertyType = EntityType.Property)
2204
if (property == null)
2205
throw new ArgumentNullException("property");
2206
if (parentType == null)
2207
throw new ArgumentNullException("parentType");
2208
DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(parentType, property.Name);
2209
p.EntityType = propertyType;
2210
TranslateModifiers(property.GetMethod ?? property.SetMethod, p);
2211
p.ReturnType = ReadTypeReference(property.PropertyType, typeAttributes: property);
2213
p.Getter = ReadMethod(property.GetMethod, parentType, EntityType.Accessor, p);
2214
p.Setter = ReadMethod(property.SetMethod, parentType, EntityType.Accessor, p);
2216
if (property.HasParameters) {
2217
foreach (ParameterDefinition par in property.Parameters) {
2218
p.Parameters.Add(ReadParameter(par));
2221
AddAttributes(property, p);
2223
var accessor = p.Getter ?? p.Setter;
2224
if (accessor != null && accessor.IsExplicitInterfaceImplementation) {
2225
p.Name = property.Name.Substring(property.Name.LastIndexOf('.') + 1);
2226
p.IsExplicitInterfaceImplementation = true;
2227
foreach (var mr in accessor.ExplicitInterfaceImplementations) {
2228
p.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr));
2232
FinishReadMember(p, property);
2238
[CLSCompliant(false)]
2239
public IUnresolvedEvent ReadEvent(EventDefinition ev, IUnresolvedTypeDefinition parentType)
2242
throw new ArgumentNullException("ev");
2243
if (parentType == null)
2244
throw new ArgumentNullException("parentType");
2246
DefaultUnresolvedEvent e = new DefaultUnresolvedEvent(parentType, ev.Name);
2247
TranslateModifiers(ev.AddMethod, e);
2248
e.ReturnType = ReadTypeReference(ev.EventType, typeAttributes: ev);
2250
e.AddAccessor = ReadMethod(ev.AddMethod, parentType, EntityType.Accessor, e);
2251
e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, EntityType.Accessor, e);
2252
e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, EntityType.Accessor, e);
2254
AddAttributes(ev, e);
2256
var accessor = e.AddAccessor ?? e.RemoveAccessor ?? e.InvokeAccessor;
2257
if (accessor != null && accessor.IsExplicitInterfaceImplementation) {
2258
e.Name = ev.Name.Substring(ev.Name.LastIndexOf('.') + 1);
2259
e.IsExplicitInterfaceImplementation = true;
2260
foreach (var mr in accessor.ExplicitInterfaceImplementations) {
2261
e.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr));
2265
FinishReadMember(e, ev);
2271
#region FinishReadMember / Interning
2272
void FinishReadMember(AbstractUnresolvedMember member, MemberReference cecilDefinition)
2274
member.ApplyInterningProvider(interningProvider);
2276
RegisterCecilObject(member, cecilDefinition);
2280
#region Type system translation table
2281
readonly Dictionary<object, object> typeSystemTranslationTable;
2283
void RegisterCecilObject(IUnresolvedEntity typeSystemObject, MemberReference cecilObject)
2285
if (OnEntityLoaded != null)
2286
OnEntityLoaded(typeSystemObject, cecilObject);
2288
AddToTypeSystemTranslationTable(typeSystemObject, cecilObject);
2291
void AddToTypeSystemTranslationTable(object typeSystemObject, object cecilObject)
2293
if (typeSystemTranslationTable != null) {
2294
// When lazy-loading, the dictionary might be shared between multiple cecil-loaders that are used concurrently
2295
lock (typeSystemTranslationTable) {
2296
typeSystemTranslationTable[typeSystemObject] = cecilObject;
2301
T InternalGetCecilObject<T> (object typeSystemObject) where T : class
2303
if (typeSystemObject == null)
2304
throw new ArgumentNullException ("typeSystemObject");
2305
if (!HasCecilReferences)
2306
throw new NotSupportedException ("This instance contains no cecil references.");
2308
lock (typeSystemTranslationTable) {
2309
if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result))
2315
[CLSCompliant(false)]
2316
public AssemblyDefinition GetCecilObject (IUnresolvedAssembly content)
2318
return InternalGetCecilObject<AssemblyDefinition> (content);
2321
[CLSCompliant(false)]
2322
public TypeDefinition GetCecilObject (IUnresolvedTypeDefinition type)
2325
throw new ArgumentNullException ("type");
2326
return InternalGetCecilObject<TypeDefinition> (type);
2329
[CLSCompliant(false)]
2330
public MethodDefinition GetCecilObject (IUnresolvedMethod method)
2332
return InternalGetCecilObject<MethodDefinition> (method);
2335
[CLSCompliant(false)]
2336
public FieldDefinition GetCecilObject (IUnresolvedField field)
2338
return InternalGetCecilObject<FieldDefinition> (field);
2341
[CLSCompliant(false)]
2342
public EventDefinition GetCecilObject (IUnresolvedEvent evt)
2344
return InternalGetCecilObject<EventDefinition> (evt);
2347
[CLSCompliant(false)]
2348
public PropertyDefinition GetCecilObject (IUnresolvedProperty property)
2350
return InternalGetCecilObject<PropertyDefinition> (property);