1
ļ»æ// Copyright (c) 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.Collections.ObjectModel;
22
using System.Diagnostics;
25
using System.Runtime.CompilerServices;
26
using System.Runtime.InteropServices;
27
using System.Runtime.Serialization;
28
using System.Threading;
29
using ICSharpCode.NRefactory.Documentation;
30
using ICSharpCode.NRefactory.Semantics;
31
using ICSharpCode.NRefactory.TypeSystem.Implementation;
32
using ICSharpCode.NRefactory.Utils;
35
namespace ICSharpCode.NRefactory.TypeSystem
38
/// Allows loading an IProjectContent from an already compiled assembly.
40
/// <remarks>Instance methods are not thread-safe; you need to create multiple instances of CecilLoader
41
/// if you want to load multiple project contents in parallel.</remarks>
42
public class CecilLoader
46
/// Specifies whether to include internal members. The default is false.
48
public bool IncludeInternalMembers { get; set; }
51
/// Gets/Sets the documentation provider that is used to retrieve the XML documentation for all members.
53
public IDocumentationProvider DocumentationProvider { get; set; }
56
/// Gets/Sets the interning provider.
58
public IInterningProvider InterningProvider { get; set; }
61
/// Gets/Sets the cancellation token used by the cecil loader.
63
public CancellationToken CancellationToken { get; set; }
66
/// Gets a value indicating whether this instance stores references to the cecil objects.
69
/// <c>true</c> if this instance has references to the cecil objects; otherwise, <c>false</c>.
71
public bool HasCecilReferences { get { return typeSystemTranslationTable != null; } }
74
ModuleDefinition currentModule;
75
CecilUnresolvedAssembly currentAssembly;
78
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.CecilLoader"/> class.
80
/// <param name='createCecilReferences'>
81
/// If true references to the cecil objects are hold. In this case the cecil loader can do a type system -> cecil mapping.
83
public CecilLoader (bool createCecilReferences = false)
85
if (createCecilReferences)
86
typeSystemTranslationTable = new Dictionary<object, object> ();
88
// Enable interning by default.
89
this.InterningProvider = new SimpleInterningProvider();
92
#region Load From AssemblyDefinition
94
/// Loads the assembly definition into a project content.
96
/// <returns>IProjectContent that represents the assembly</returns>
98
public IUnresolvedAssembly LoadAssembly(AssemblyDefinition assemblyDefinition)
100
if (assemblyDefinition == null)
101
throw new ArgumentNullException("assemblyDefinition");
103
this.currentModule = assemblyDefinition.MainModule;
105
// Read assembly and module attributes
106
IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>();
107
IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>();
108
AddAttributes(assemblyDefinition, assemblyAttributes);
109
AddAttributes(assemblyDefinition.MainModule, moduleAttributes);
111
if (this.InterningProvider != null) {
112
assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes);
113
moduleAttributes = this.InterningProvider.InternList(moduleAttributes);
116
this.currentAssembly = new CecilUnresolvedAssembly(assemblyDefinition.Name.Name, this.DocumentationProvider);
117
currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
118
currentAssembly.ModuleAttributes.AddRange(assemblyAttributes);
120
// Register type forwarders:
121
foreach (ExportedType type in assemblyDefinition.MainModule.ExportedTypes) {
122
if (type.IsForwarder) {
123
int typeParameterCount;
124
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
125
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), type.Namespace, name, typeParameterCount);
126
typeRef = this.InterningProvider.Intern(typeRef);
127
var key = new FullNameAndTypeParameterCount(type.Namespace, name, typeParameterCount);
128
currentAssembly.AddTypeForwarder(key, typeRef);
132
// Create and register all types:
133
List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>();
134
List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>();
135
foreach (ModuleDefinition module in assemblyDefinition.Modules) {
136
foreach (TypeDefinition td in module.Types) {
137
this.CancellationToken.ThrowIfCancellationRequested();
138
if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
139
string name = td.Name;
140
if (name.Length == 0 || name[0] == '<')
143
var t = CreateTopLevelTypeDefinition(td);
144
cecilTypeDefs.Add(td);
146
currentAssembly.AddTypeDefinition(t);
150
// Initialize the type's members:
151
for (int i = 0; i < typeDefs.Count; i++) {
152
InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]);
155
if (HasCecilReferences)
156
typeSystemTranslationTable[this.currentAssembly] = assemblyDefinition;
158
var result = this.currentAssembly;
159
this.currentAssembly = null;
160
this.currentModule = null;
165
/// Loads a type from Cecil.
167
/// <param name="typeDefinition">The Cecil TypeDefinition.</param>
168
/// <returns>ITypeDefinition representing the Cecil type.</returns>
169
[CLSCompliant(false)]
170
public IUnresolvedTypeDefinition LoadType(TypeDefinition typeDefinition)
172
if (typeDefinition == null)
173
throw new ArgumentNullException("typeDefinition");
174
var td = CreateTopLevelTypeDefinition(typeDefinition);
175
InitTypeDefinition(typeDefinition, td);
180
#region IUnresolvedAssembly implementation
182
sealed class CecilUnresolvedAssembly : DefaultUnresolvedAssembly, IDocumentationProvider, IDocumentationProviderContainer
185
IDocumentationProvider documentationProvider;
187
public IDocumentationProvider DocumentationProvider {
189
return documentationProvider;
192
documentationProvider = value;
196
public CecilUnresolvedAssembly(string assemblyName, IDocumentationProvider documentationProvider)
199
Debug.Assert(assemblyName != null);
200
this.documentationProvider = documentationProvider;
203
DocumentationComment IDocumentationProvider.GetDocumentation(IEntity entity)
205
if (documentationProvider != null)
206
return documentationProvider.GetDocumentation(entity);
213
#region Load Assembly From Disk
214
public IUnresolvedAssembly LoadAssemblyFile(string fileName)
216
if (fileName == null)
217
throw new ArgumentNullException("fileName");
218
var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() };
219
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(fileName, param);
220
var result = LoadAssembly(asm);
221
if (HasCecilReferences)
222
typeSystemTranslationTable[result] = asm;
226
// used to prevent Cecil from loading referenced assemblies
227
sealed class DummyAssemblyResolver : IAssemblyResolver
229
public AssemblyDefinition Resolve(AssemblyNameReference name)
234
public AssemblyDefinition Resolve(string fullName)
239
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
244
public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters)
251
#region Read Type Reference
253
/// Reads a type reference.
255
/// <param name="type">The Cecil type reference that should be converted into
256
/// a type system type reference.</param>
257
/// <param name="typeAttributes">Attributes associated with the Cecil type reference.
258
/// This is used to support the 'dynamic' type.</param>
259
[CLSCompliant(false)]
260
public ITypeReference ReadTypeReference(TypeReference type, ICustomAttributeProvider typeAttributes = null)
263
return CreateType(type, typeAttributes, ref typeIndex);
266
ITypeReference CreateType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex)
268
while (type is OptionalModifierType || type is RequiredModifierType) {
269
type = ((TypeSpecification)type).ElementType;
272
return SpecialType.UnknownType;
275
if (type is Mono.Cecil.ByReferenceType) {
277
return new ByReferenceTypeReference(
279
(type as Mono.Cecil.ByReferenceType).ElementType,
280
typeAttributes, ref typeIndex));
281
} else if (type is Mono.Cecil.PointerType) {
283
return new PointerTypeReference(
285
(type as Mono.Cecil.PointerType).ElementType,
286
typeAttributes, ref typeIndex));
287
} else if (type is Mono.Cecil.ArrayType) {
289
return new ArrayTypeReference(
291
(type as Mono.Cecil.ArrayType).ElementType,
292
typeAttributes, ref typeIndex),
293
(type as Mono.Cecil.ArrayType).Rank);
294
} else if (type is GenericInstanceType) {
295
GenericInstanceType gType = (GenericInstanceType)type;
296
ITypeReference baseType = CreateType(gType.ElementType, typeAttributes, ref typeIndex);
297
ITypeReference[] para = new ITypeReference[gType.GenericArguments.Count];
298
for (int i = 0; i < para.Length; ++i) {
300
para[i] = CreateType(gType.GenericArguments[i], typeAttributes, ref typeIndex);
302
return new ParameterizedTypeReference(baseType, para);
303
} else if (type is GenericParameter) {
304
GenericParameter typeGP = (GenericParameter)type;
305
return new TypeParameterReference(typeGP.Owner is MethodDefinition ? EntityType.Method : EntityType.TypeDefinition, typeGP.Position);
306
} else if (type.IsNested) {
307
ITypeReference typeRef = CreateType(type.DeclaringType, typeAttributes, ref typeIndex);
308
int partTypeParameterCount;
309
string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out partTypeParameterCount);
310
return new NestedTypeReference(typeRef, namepart, partTypeParameterCount);
312
string ns = type.Namespace ?? string.Empty;
313
string name = type.Name;
315
throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
317
if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
318
return SpecialType.Dynamic;
320
int typeParameterCount;
321
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount);
322
if (currentAssembly != null) {
323
IUnresolvedTypeDefinition c = currentAssembly.GetTypeDefinition(ns, name, typeParameterCount);
327
return new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount);
332
IAssemblyReference GetAssemblyReference(IMetadataScope scope)
334
if (scope == null || scope == currentModule)
335
return DefaultAssemblyReference.CurrentAssembly;
337
return new DefaultAssemblyReference(scope.Name);
340
static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
342
if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
344
foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
345
TypeReference type = a.AttributeType;
346
if (type.Name == "DynamicAttribute" && type.Namespace == "System.Runtime.CompilerServices") {
347
if (a.ConstructorArguments.Count == 1) {
348
CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
349
if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
350
return (bool)values[typeIndex].Value;
359
#region Read Attributes
360
#region Assembly Attributes
361
static readonly ITypeReference assemblyVersionAttributeTypeRef = typeof(System.Reflection.AssemblyVersionAttribute).ToTypeReference();
363
void AddAttributes(AssemblyDefinition assembly, IList<IUnresolvedAttribute> outputList)
365
if (assembly.HasCustomAttributes) {
366
AddCustomAttributes(assembly.CustomAttributes, outputList);
368
if (assembly.HasSecurityDeclarations) {
369
AddSecurityAttributes(assembly.SecurityDeclarations, outputList);
372
// AssemblyVersionAttribute
373
if (assembly.Name.Version != null) {
374
var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String });
375
assemblyVersion.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString()));
376
outputList.Add(assemblyVersion);
381
#region Module Attributes
382
void AddAttributes(ModuleDefinition module, IList<IUnresolvedAttribute> outputList)
384
if (module.HasCustomAttributes) {
385
AddCustomAttributes(module.CustomAttributes, outputList);
390
#region Parameter Attributes
391
static readonly IUnresolvedAttribute inAttribute = new DefaultUnresolvedAttribute(typeof(InAttribute).ToTypeReference());
392
static readonly IUnresolvedAttribute outAttribute = new DefaultUnresolvedAttribute(typeof(OutAttribute).ToTypeReference());
394
void AddAttributes(ParameterDefinition parameter, DefaultUnresolvedParameter targetParameter)
396
if (!targetParameter.IsOut) {
398
targetParameter.Attributes.Add(inAttribute);
400
targetParameter.Attributes.Add(outAttribute);
402
if (parameter.HasCustomAttributes) {
403
AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes);
405
if (parameter.HasMarshalInfo) {
406
targetParameter.Attributes.Add(ConvertMarshalInfo(parameter.MarshalInfo));
411
#region Method Attributes
412
static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference();
413
static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true);
414
static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, false);
415
static readonly ITypeReference callingConventionTypeRef = typeof(CallingConvention).ToTypeReference();
416
static readonly IUnresolvedAttribute preserveSigAttribute = new DefaultUnresolvedAttribute(typeof(PreserveSigAttribute).ToTypeReference());
417
static readonly ITypeReference methodImplAttributeTypeRef = typeof(MethodImplAttribute).ToTypeReference();
418
static readonly ITypeReference methodImplOptionsTypeRef = typeof(MethodImplOptions).ToTypeReference();
420
static bool HasAnyAttributes(MethodDefinition methodDefinition)
422
if (methodDefinition.HasPInvokeInfo)
424
if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0)
426
if (methodDefinition.MethodReturnType.HasFieldMarshal)
428
return methodDefinition.HasCustomAttributes || methodDefinition.MethodReturnType.HasCustomAttributes;
431
void AddAttributes(MethodDefinition methodDefinition, IList<IUnresolvedAttribute> attributes, IList<IUnresolvedAttribute> returnTypeAttributes)
433
MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
435
#region DllImportAttribute
436
if (methodDefinition.HasPInvokeInfo) {
437
PInvokeInfo info = methodDefinition.PInvokeInfo;
438
var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String });
439
dllImport.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, info.Module.Name));
441
if (info.IsBestFitDisabled)
442
dllImport.AddNamedFieldArgument("BestFitMapping", falseValue);
443
if (info.IsBestFitEnabled)
444
dllImport.AddNamedFieldArgument("BestFitMapping", trueValue);
446
CallingConvention callingConvention;
447
switch (info.Attributes & PInvokeAttributes.CallConvMask) {
448
case (PInvokeAttributes)0:
449
Debug.WriteLine ("P/Invoke calling convention not set on:" + methodDefinition.FullName);
450
callingConvention = CallingConvention.StdCall;
452
case PInvokeAttributes.CallConvCdecl:
453
callingConvention = CallingConvention.Cdecl;
455
case PInvokeAttributes.CallConvFastcall:
456
callingConvention = CallingConvention.FastCall;
458
case PInvokeAttributes.CallConvStdCall:
459
callingConvention = CallingConvention.StdCall;
461
case PInvokeAttributes.CallConvThiscall:
462
callingConvention = CallingConvention.ThisCall;
464
case PInvokeAttributes.CallConvWinapi:
465
callingConvention = CallingConvention.Winapi;
468
throw new NotSupportedException("unknown calling convention");
470
if (callingConvention != CallingConvention.Winapi)
471
dllImport.AddNamedFieldArgument("CallingConvention", callingConventionTypeRef, (int)callingConvention);
473
CharSet charSet = CharSet.None;
474
switch (info.Attributes & PInvokeAttributes.CharSetMask) {
475
case PInvokeAttributes.CharSetAnsi:
476
charSet = CharSet.Ansi;
478
case PInvokeAttributes.CharSetAuto:
479
charSet = CharSet.Auto;
481
case PInvokeAttributes.CharSetUnicode:
482
charSet = CharSet.Unicode;
485
if (charSet != CharSet.None)
486
dllImport.AddNamedFieldArgument("CharSet", charSetTypeRef, (int)charSet);
488
if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name)
489
dllImport.AddNamedFieldArgument("EntryPoint", KnownTypeReference.String, info.EntryPoint);
492
dllImport.AddNamedFieldArgument("ExactSpelling", trueValue);
494
if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
495
implAttributes &= ~MethodImplAttributes.PreserveSig;
497
dllImport.AddNamedFieldArgument("PreserveSig", falseValue);
499
if (info.SupportsLastError)
500
dllImport.AddNamedFieldArgument("SetLastError", trueValue);
502
if (info.IsThrowOnUnmappableCharDisabled)
503
dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", falseValue);
504
if (info.IsThrowOnUnmappableCharEnabled)
505
dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", trueValue);
507
attributes.Add(dllImport);
511
#region PreserveSigAttribute
512
if (implAttributes == MethodImplAttributes.PreserveSig) {
513
attributes.Add(preserveSigAttribute);
518
#region MethodImplAttribute
519
if (implAttributes != 0) {
520
var methodImpl = new DefaultUnresolvedAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef });
521
methodImpl.PositionalArguments.Add(new SimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes));
522
attributes.Add(methodImpl);
526
if (methodDefinition.HasCustomAttributes) {
527
AddCustomAttributes(methodDefinition.CustomAttributes, attributes);
529
if (methodDefinition.HasSecurityDeclarations) {
530
AddSecurityAttributes(methodDefinition.SecurityDeclarations, attributes);
532
if (methodDefinition.MethodReturnType.HasMarshalInfo) {
533
returnTypeAttributes.Add(ConvertMarshalInfo(methodDefinition.MethodReturnType.MarshalInfo));
535
if (methodDefinition.MethodReturnType.HasCustomAttributes) {
536
AddCustomAttributes(methodDefinition.MethodReturnType.CustomAttributes, returnTypeAttributes);
541
#region Type Attributes
542
static readonly DefaultUnresolvedAttribute serializableAttribute = new DefaultUnresolvedAttribute(typeof(SerializableAttribute).ToTypeReference());
543
static readonly DefaultUnresolvedAttribute comImportAttribute = new DefaultUnresolvedAttribute(typeof(ComImportAttribute).ToTypeReference());
544
static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference();
545
static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference();
546
static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference();
548
void AddAttributes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition targetEntity)
550
// SerializableAttribute
551
if (typeDefinition.IsSerializable)
552
targetEntity.Attributes.Add(serializableAttribute);
554
// ComImportAttribute
555
if (typeDefinition.IsImport)
556
targetEntity.Attributes.Add(comImportAttribute);
558
#region StructLayoutAttribute
559
LayoutKind layoutKind = LayoutKind.Auto;
560
switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) {
561
case TypeAttributes.SequentialLayout:
562
layoutKind = LayoutKind.Sequential;
564
case TypeAttributes.ExplicitLayout:
565
layoutKind = LayoutKind.Explicit;
568
CharSet charSet = CharSet.None;
569
switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) {
570
case TypeAttributes.AnsiClass:
571
charSet = CharSet.Ansi;
573
case TypeAttributes.AutoClass:
574
charSet = CharSet.Auto;
576
case TypeAttributes.UnicodeClass:
577
charSet = CharSet.Unicode;
580
LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto;
581
if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) {
582
DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef });
583
structLayout.PositionalArguments.Add(new SimpleConstantValue(layoutKindTypeRef, (int)layoutKind));
584
if (charSet != CharSet.Ansi) {
585
structLayout.AddNamedFieldArgument("CharSet", charSetTypeRef, (int)charSet);
587
if (typeDefinition.PackingSize > 0) {
588
structLayout.AddNamedFieldArgument("Pack", KnownTypeReference.Int32, (int)typeDefinition.PackingSize);
590
if (typeDefinition.ClassSize > 0) {
591
structLayout.AddNamedFieldArgument("Size", KnownTypeReference.Int32, (int)typeDefinition.ClassSize);
593
targetEntity.Attributes.Add(structLayout);
597
if (typeDefinition.HasCustomAttributes) {
598
AddCustomAttributes(typeDefinition.CustomAttributes, targetEntity.Attributes);
600
if (typeDefinition.HasSecurityDeclarations) {
601
AddSecurityAttributes(typeDefinition.SecurityDeclarations, targetEntity.Attributes);
606
#region Field Attributes
607
static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference();
608
static readonly IUnresolvedAttribute nonSerializedAttribute = new DefaultUnresolvedAttribute(typeof(NonSerializedAttribute).ToTypeReference());
610
void AddAttributes(FieldDefinition fieldDefinition, IUnresolvedEntity targetEntity)
612
// FieldOffsetAttribute
613
if (fieldDefinition.HasLayoutInfo) {
614
DefaultUnresolvedAttribute fieldOffset = new DefaultUnresolvedAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 });
615
fieldOffset.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset));
616
targetEntity.Attributes.Add(fieldOffset);
619
// NonSerializedAttribute
620
if (fieldDefinition.IsNotSerialized) {
621
targetEntity.Attributes.Add(nonSerializedAttribute);
624
if (fieldDefinition.HasMarshalInfo) {
625
targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo));
628
if (fieldDefinition.HasCustomAttributes) {
629
AddCustomAttributes(fieldDefinition.CustomAttributes, targetEntity.Attributes);
634
#region Event Attributes
635
void AddAttributes(EventDefinition eventDefinition, IUnresolvedEntity targetEntity)
637
if (eventDefinition.HasCustomAttributes) {
638
AddCustomAttributes(eventDefinition.CustomAttributes, targetEntity.Attributes);
643
#region Property Attributes
644
void AddAttributes(PropertyDefinition propertyDefinition, IUnresolvedEntity targetEntity)
646
if (propertyDefinition.HasCustomAttributes) {
647
AddCustomAttributes(propertyDefinition.CustomAttributes, targetEntity.Attributes);
652
#region MarshalAsAttribute (ConvertMarshalInfo)
653
static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference();
654
static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference();
656
static IUnresolvedAttribute ConvertMarshalInfo(MarshalInfo marshalInfo)
658
DefaultUnresolvedAttribute attr = new DefaultUnresolvedAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef });
659
attr.PositionalArguments.Add(new SimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType));
661
FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
663
attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)fami.Size);
664
if (fami.ElementType != NativeType.None)
665
attr.AddNamedFieldArgument("ArraySubType", unmanagedTypeTypeRef, (int)fami.ElementType);
667
SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
668
if (sami != null && sami.ElementType != VariantType.None) {
669
attr.AddNamedFieldArgument("SafeArraySubType", typeof(VarEnum).ToTypeReference(), (int)sami.ElementType);
671
ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo;
673
if (ami.ElementType != NativeType.Max)
674
attr.AddNamedFieldArgument("ArraySubType", unmanagedTypeTypeRef, (int)ami.ElementType);
676
attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)ami.Size);
677
if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0)
678
attr.AddNamedFieldArgument("SizeParamIndex", KnownTypeReference.Int16, (short)ami.SizeParameterIndex);
680
CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
682
attr.AddNamedFieldArgument("MarshalType", KnownTypeReference.String, cmi.ManagedType.FullName);
683
if (!string.IsNullOrEmpty(cmi.Cookie))
684
attr.AddNamedFieldArgument("MarshalCookie", KnownTypeReference.String, cmi.Cookie);
686
FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo;
688
attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)fssmi.Size);
695
#region Custom Attributes (ReadAttribute)
696
void AddCustomAttributes(Mono.Collections.Generic.Collection<CustomAttribute> attributes, IList<IUnresolvedAttribute> targetCollection)
698
foreach (var cecilAttribute in attributes) {
699
TypeReference type = cecilAttribute.AttributeType;
700
if (type.Namespace == "System.Runtime.CompilerServices") {
701
if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute")
703
} else if (type.Name == "ParamArrayAttribute" && type.Namespace == "System") {
706
targetCollection.Add(ReadAttribute(cecilAttribute));
710
[CLSCompliant(false)]
711
public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute)
713
if (attribute == null)
714
throw new ArgumentNullException("attribute");
715
MethodReference ctor = attribute.Constructor;
716
ITypeReference attributeType = ReadTypeReference(attribute.AttributeType);
717
IList<ITypeReference> ctorParameterTypes = null;
718
if (ctor.HasParameters) {
719
ctorParameterTypes = new ITypeReference[ctor.Parameters.Count];
720
for (int i = 0; i < ctorParameterTypes.Count; i++) {
721
ctorParameterTypes[i] = ReadTypeReference(ctor.Parameters[i].ParameterType);
724
if (this.InterningProvider != null) {
725
attributeType = this.InterningProvider.Intern(attributeType);
726
ctorParameterTypes = this.InterningProvider.InternList(ctorParameterTypes);
728
return new CecilUnresolvedAttribute(attributeType, ctorParameterTypes ?? EmptyList<ITypeReference>.Instance, attribute.GetBlob());
732
#region CecilUnresolvedAttribute
733
static int GetBlobHashCode(byte[] blob)
737
foreach (byte b in blob) {
745
static bool BlobEquals(byte[] a, byte[] b)
747
if (a.Length != b.Length)
749
for (int i = 0; i < a.Length; i++) {
757
sealed class CecilUnresolvedAttribute : IUnresolvedAttribute, ISupportsInterning
759
internal readonly ITypeReference attributeType;
760
internal readonly IList<ITypeReference> ctorParameterTypes;
761
internal readonly byte[] blob;
763
public CecilUnresolvedAttribute(ITypeReference attributeType, IList<ITypeReference> ctorParameterTypes, byte[] blob)
765
Debug.Assert(attributeType != null);
766
Debug.Assert(ctorParameterTypes != null);
767
Debug.Assert(blob != null);
768
this.attributeType = attributeType;
769
this.ctorParameterTypes = ctorParameterTypes;
773
DomRegion IUnresolvedAttribute.Region {
774
get { return DomRegion.Empty; }
777
IAttribute IUnresolvedAttribute.CreateResolvedAttribute(ITypeResolveContext context)
779
if (context.CurrentAssembly == null)
780
throw new InvalidOperationException("Cannot resolve CecilUnresolvedAttribute without a parent assembly");
781
return new CecilResolvedAttribute(context, this);
784
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
786
// We already interned our child elements in ReadAttribute().
789
int ISupportsInterning.GetHashCodeForInterning()
791
return attributeType.GetHashCode() ^ ctorParameterTypes.GetHashCode() ^ GetBlobHashCode(blob);
794
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
796
CecilUnresolvedAttribute o = other as CecilUnresolvedAttribute;
797
return o != null && attributeType == o.attributeType && ctorParameterTypes == o.ctorParameterTypes
798
&& BlobEquals(blob, o.blob);
803
#region CecilResolvedAttribute
804
sealed class CecilResolvedAttribute : IAttribute
806
readonly ITypeResolveContext context;
807
readonly byte[] blob;
808
readonly IList<ITypeReference> ctorParameterTypes;
809
readonly IType attributeType;
812
volatile bool constructorResolved;
814
IList<ResolveResult> positionalArguments;
815
IList<KeyValuePair<IMember, ResolveResult>> namedArguments;
817
public CecilResolvedAttribute(ITypeResolveContext context, CecilUnresolvedAttribute unresolved)
819
this.context = context;
820
this.blob = unresolved.blob;
821
this.ctorParameterTypes = unresolved.ctorParameterTypes;
822
this.attributeType = unresolved.attributeType.Resolve(context);
825
public CecilResolvedAttribute(ITypeResolveContext context, IType attributeType)
827
this.context = context;
828
this.attributeType = attributeType;
829
this.ctorParameterTypes = EmptyList<ITypeReference>.Instance;
832
public DomRegion Region {
833
get { return DomRegion.Empty; }
836
public IType AttributeType {
837
get { return attributeType; }
840
public IMethod Constructor {
842
if (!constructorResolved) {
843
constructor = ResolveConstructor();
844
constructorResolved = true;
850
IMethod ResolveConstructor()
852
var parameterTypes = ctorParameterTypes.Resolve(context);
853
foreach (var ctor in attributeType.GetConstructors(m => m.Parameters.Count == parameterTypes.Count)) {
855
for (int i = 0; i < parameterTypes.Count; i++) {
856
if (!ctor.Parameters[i].Type.Equals(parameterTypes[i])) {
867
public IList<ResolveResult> PositionalArguments {
869
var result = LazyInit.VolatileRead(ref this.positionalArguments);
870
if (result != null) {
874
return positionalArguments;
878
public IList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
880
var result = LazyInit.VolatileRead(ref this.namedArguments);
881
if (result != null) {
885
return namedArguments;
889
public override string ToString()
891
return "[" + attributeType.ToString() + "(...)]";
896
var positionalArguments = new List<ResolveResult>();
897
var namedArguments = new List<KeyValuePair<IMember, ResolveResult>>();
898
DecodeBlob(positionalArguments, namedArguments);
899
Interlocked.CompareExchange(ref this.positionalArguments, positionalArguments, null);
900
Interlocked.CompareExchange(ref this.namedArguments, namedArguments, null);
903
void DecodeBlob(List<ResolveResult> positionalArguments, List<KeyValuePair<IMember, ResolveResult>> namedArguments)
907
BlobReader reader = new BlobReader(blob, context.CurrentAssembly);
908
if (reader.ReadUInt16() != 0x0001) {
909
Debug.WriteLine("Unknown blob prolog");
912
foreach (var ctorParameter in ctorParameterTypes.Resolve(context)) {
913
positionalArguments.Add(reader.ReadFixedArg(ctorParameter));
915
ushort numNamed = reader.ReadUInt16();
916
for (int i = 0; i < numNamed; i++) {
917
var namedArg = reader.ReadNamedArg(attributeType);
918
if (namedArg.Key != null)
919
namedArguments.Add(namedArg);
925
#region class BlobReader
930
readonly IAssembly currentResolvedAssembly;
932
public BlobReader(byte[] buffer, IAssembly currentResolvedAssembly)
935
throw new ArgumentNullException("buffer");
936
this.buffer = buffer;
937
this.currentResolvedAssembly = currentResolvedAssembly;
940
public byte ReadByte()
942
return buffer[position++];
945
public sbyte ReadSByte()
948
return(sbyte) ReadByte();
952
public byte[] ReadBytes(int length)
954
var bytes = new byte[length];
955
Buffer.BlockCopy(buffer, position, bytes, 0, length);
960
public ushort ReadUInt16()
963
ushort value =(ushort)(buffer[position]
964
|(buffer[position + 1] << 8));
970
public short ReadInt16()
973
return(short) ReadUInt16();
977
public uint ReadUInt32()
980
uint value =(uint)(buffer[position]
981
|(buffer[position + 1] << 8)
982
|(buffer[position + 2] << 16)
983
|(buffer[position + 3] << 24));
989
public int ReadInt32()
992
return(int) ReadUInt32();
996
public ulong ReadUInt64()
999
uint low = ReadUInt32();
1000
uint high = ReadUInt32();
1002
return(((ulong) high) << 32) | low;
1006
public long ReadInt64()
1009
return(long) ReadUInt64();
1013
public uint ReadCompressedUInt32()
1016
byte first = ReadByte();
1017
if((first & 0x80) == 0)
1020
if((first & 0x40) == 0)
1021
return((uint)(first & ~0x80) << 8)
1024
return((uint)(first & ~0xc0) << 24)
1025
|(uint) ReadByte() << 16
1026
|(uint) ReadByte() << 8
1031
public float ReadSingle()
1034
if(!BitConverter.IsLittleEndian) {
1035
var bytes = ReadBytes(4);
1036
Array.Reverse(bytes);
1037
return BitConverter.ToSingle(bytes, 0);
1040
float value = BitConverter.ToSingle(buffer, position);
1046
public double ReadDouble()
1049
if(!BitConverter.IsLittleEndian) {
1050
var bytes = ReadBytes(8);
1051
Array.Reverse(bytes);
1052
return BitConverter.ToDouble(bytes, 0);
1055
double value = BitConverter.ToDouble(buffer, position);
1061
public ResolveResult ReadFixedArg(IType argType)
1063
if (argType.Kind == TypeKind.Array) {
1064
if (((ArrayType)argType).Dimensions != 1) {
1065
// Only single-dimensional arrays are supported
1066
return ErrorResolveResult.UnknownError;
1068
IType elementType = ((ArrayType)argType).ElementType;
1069
uint numElem = ReadUInt32();
1070
if (numElem == 0xffffffff) {
1072
return new ConstantResolveResult(argType, null);
1074
ResolveResult[] elements = new ResolveResult[numElem];
1075
for (int i = 0; i < elements.Length; i++) {
1076
elements[i] = ReadElem(elementType);
1078
return new ArrayCreateResolveResult(argType, null, elements);
1081
return ReadElem(argType);
1085
public ResolveResult ReadElem(IType elementType)
1087
ITypeDefinition underlyingType;
1088
if (elementType.Kind == TypeKind.Enum) {
1089
underlyingType = elementType.GetDefinition().EnumUnderlyingType.GetDefinition();
1091
underlyingType = elementType.GetDefinition();
1093
if (underlyingType == null)
1094
return ErrorResolveResult.UnknownError;
1095
KnownTypeCode typeCode = underlyingType.KnownTypeCode;
1096
if (typeCode == KnownTypeCode.Object) {
1098
IType boxedTyped = ReadCustomAttributeFieldOrPropType();
1099
ResolveResult elem = ReadElem(boxedTyped);
1100
if (elem.IsCompileTimeConstant && elem.ConstantValue == null)
1101
return new ConstantResolveResult(elementType, null);
1103
return new ConversionResolveResult(elementType, elem, Conversion.BoxingConversion);
1104
} else if (typeCode == KnownTypeCode.Type) {
1105
return new TypeOfResolveResult(underlyingType, ReadType());
1107
return new ConstantResolveResult(elementType, ReadElemValue(typeCode));
1111
object ReadElemValue(KnownTypeCode typeCode)
1114
case KnownTypeCode.Boolean:
1115
return ReadByte() != 0;
1116
case KnownTypeCode.Char:
1117
return (char)ReadUInt16();
1118
case KnownTypeCode.SByte:
1120
case KnownTypeCode.Byte:
1122
case KnownTypeCode.Int16:
1124
case KnownTypeCode.UInt16:
1125
return ReadUInt16();
1126
case KnownTypeCode.Int32:
1128
case KnownTypeCode.UInt32:
1129
return ReadUInt32();
1130
case KnownTypeCode.Int64:
1132
case KnownTypeCode.UInt64:
1133
return ReadUInt64();
1134
case KnownTypeCode.Single:
1135
return ReadSingle();
1136
case KnownTypeCode.Double:
1137
return ReadDouble();
1138
case KnownTypeCode.String:
1139
return ReadSerString();
1141
throw new NotSupportedException();
1145
public string ReadSerString ()
1147
if (buffer [position] == 0xff) {
1152
int length = (int) ReadCompressedUInt32();
1154
return string.Empty;
1156
string @string = System.Text.Encoding.UTF8.GetString(
1158
buffer [position + length - 1] == 0 ? length - 1 : length);
1164
public KeyValuePair<IMember, ResolveResult> ReadNamedArg(IType attributeType)
1166
EntityType memberType;
1167
switch (ReadByte()) {
1169
memberType = EntityType.Field;
1172
memberType = EntityType.Property;
1175
throw new NotSupportedException();
1177
IType type = ReadCustomAttributeFieldOrPropType();
1178
string name = ReadSerString();
1179
ResolveResult val = ReadFixedArg(type);
1180
IMember member = null;
1181
// Use last matching member, as GetMembers() returns members from base types first.
1182
foreach (IMember m in attributeType.GetMembers(m => m.EntityType == memberType && m.Name == name)) {
1183
if (m.ReturnType.Equals(type))
1186
return new KeyValuePair<IMember, ResolveResult>(member, val);
1189
IType ReadCustomAttributeFieldOrPropType()
1191
ICompilation compilation = currentResolvedAssembly.Compilation;
1195
return compilation.FindType(KnownTypeCode.Boolean);
1197
return compilation.FindType(KnownTypeCode.Char);
1199
return compilation.FindType(KnownTypeCode.SByte);
1201
return compilation.FindType(KnownTypeCode.Byte);
1203
return compilation.FindType(KnownTypeCode.Int16);
1205
return compilation.FindType(KnownTypeCode.UInt16);
1207
return compilation.FindType(KnownTypeCode.Int32);
1209
return compilation.FindType(KnownTypeCode.UInt32);
1211
return compilation.FindType(KnownTypeCode.Int64);
1213
return compilation.FindType(KnownTypeCode.UInt64);
1215
return compilation.FindType(KnownTypeCode.Single);
1217
return compilation.FindType(KnownTypeCode.Double);
1219
return compilation.FindType(KnownTypeCode.String);
1221
return new ArrayType(compilation, ReadCustomAttributeFieldOrPropType());
1223
return compilation.FindType(KnownTypeCode.Type);
1224
case 0x51: // boxed value type
1225
return compilation.FindType(KnownTypeCode.Object);
1229
throw new NotSupportedException(string.Format("Custom attribute type 0x{0:x} is not supported.", b));
1235
string typeName = ReadSerString();
1236
ITypeReference typeReference = ReflectionHelper.ParseReflectionName(typeName);
1237
IType typeInCurrentAssembly = typeReference.Resolve(new SimpleTypeResolveContext(currentResolvedAssembly));
1238
if (typeInCurrentAssembly.Kind != TypeKind.Unknown)
1239
return typeInCurrentAssembly;
1241
// look for the type in mscorlib
1242
ITypeDefinition systemObject = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Object).GetDefinition();
1243
if (systemObject != null) {
1244
return typeReference.Resolve(new SimpleTypeResolveContext(systemObject.ParentAssembly));
1246
// couldn't find corlib - return the unknown IType for the current assembly
1247
return typeInCurrentAssembly;
1253
#region Security Attributes
1254
static readonly ITypeReference securityActionTypeReference = typeof(System.Security.Permissions.SecurityAction).ToTypeReference();
1255
static readonly ITypeReference permissionSetAttributeTypeReference = typeof(System.Security.Permissions.PermissionSetAttribute).ToTypeReference();
1258
/// Reads a security declaration.
1260
[CLSCompliant(false)]
1261
public IList<IUnresolvedAttribute> ReadSecurityDeclaration(SecurityDeclaration secDecl)
1263
if (secDecl == null)
1264
throw new ArgumentNullException("secDecl");
1265
var result = new List<IUnresolvedAttribute>();
1266
AddSecurityAttributes(secDecl, result);
1270
void AddSecurityAttributes(Mono.Collections.Generic.Collection<SecurityDeclaration> securityDeclarations, IList<IUnresolvedAttribute> targetCollection)
1272
foreach (var secDecl in securityDeclarations) {
1273
AddSecurityAttributes(secDecl, targetCollection);
1277
void AddSecurityAttributes(SecurityDeclaration secDecl, IList<IUnresolvedAttribute> targetCollection)
1279
byte[] blob = secDecl.GetBlob();
1280
BlobReader reader = new BlobReader(blob, null);
1281
var securityAction = new SimpleConstantValue(securityActionTypeReference, (int)secDecl.Action);
1282
if (reader.ReadByte() == '.') {
1284
uint attributeCount = reader.ReadCompressedUInt32();
1285
UnresolvedSecurityDeclaration unresolvedSecDecl = new UnresolvedSecurityDeclaration(securityAction, blob);
1286
if (this.InterningProvider != null) {
1287
unresolvedSecDecl = this.InterningProvider.Intern(unresolvedSecDecl);
1289
for (uint i = 0; i < attributeCount; i++) {
1290
targetCollection.Add(new UnresolvedSecurityAttribute(unresolvedSecDecl, (int)i));
1293
// for backward compatibility with .NET 1.0: XML-encoded attribute
1294
var attr = new DefaultUnresolvedAttribute(permissionSetAttributeTypeReference);
1295
attr.ConstructorParameterTypes.Add(securityActionTypeReference);
1296
attr.PositionalArguments.Add(securityAction);
1297
string xml = System.Text.Encoding.Unicode.GetString(blob);
1298
attr.AddNamedPropertyArgument("XML", KnownTypeReference.String, xml);
1299
targetCollection.Add(attr);
1304
sealed class UnresolvedSecurityDeclaration : ISupportsInterning
1306
IConstantValue securityAction;
1309
public UnresolvedSecurityDeclaration(IConstantValue securityAction, byte[] blob)
1311
Debug.Assert(securityAction != null);
1312
Debug.Assert(blob != null);
1313
this.securityAction = securityAction;
1317
public IList<IAttribute> Resolve(IAssembly currentAssembly)
1319
// TODO: make this a per-assembly cache
1320
// CacheManager cache = currentAssembly.Compilation.CacheManager;
1321
// IList<IAttribute> result = (IList<IAttribute>)cache.GetShared(this);
1322
// if (result != null)
1325
ITypeResolveContext context = new SimpleTypeResolveContext(currentAssembly);
1326
BlobReader reader = new BlobReader(blob, currentAssembly);
1327
if (reader.ReadByte() != '.') {
1328
// should not use UnresolvedSecurityDeclaration for XML secdecls
1329
throw new InvalidOperationException();
1331
ResolveResult securityActionRR = securityAction.Resolve(context);
1332
uint attributeCount = reader.ReadCompressedUInt32();
1333
IAttribute[] attributes = new IAttribute[attributeCount];
1335
ReadSecurityBlob(reader, attributes, context, securityActionRR);
1336
} catch (NotSupportedException ex) {
1337
// ignore invalid blobs
1338
Debug.WriteLine(ex.ToString());
1340
for (int i = 0; i < attributes.Length; i++) {
1341
if (attributes[i] == null)
1342
attributes[i] = new CecilResolvedAttribute(context, SpecialType.UnknownType);
1345
// return (IList<IAttribute>)cache.GetOrAddShared(this, attributes);
1348
void ReadSecurityBlob(BlobReader reader, IAttribute[] attributes, ITypeResolveContext context, ResolveResult securityActionRR)
1350
for (int i = 0; i < attributes.Length; i++) {
1351
string attributeTypeName = reader.ReadSerString();
1352
ITypeReference attributeTypeRef = ReflectionHelper.ParseReflectionName(attributeTypeName);
1353
IType attributeType = attributeTypeRef.Resolve(context);
1355
reader.ReadCompressedUInt32(); // ??
1356
// The specification seems to be incorrect here, so I'm using the logic from Cecil instead.
1357
uint numNamed = reader.ReadCompressedUInt32();
1359
var namedArgs = new List<KeyValuePair<IMember, ResolveResult>>((int)numNamed);
1360
for (uint j = 0; j < numNamed; j++) {
1361
var namedArg = reader.ReadNamedArg(attributeType);
1362
if (namedArg.Key != null)
1363
namedArgs.Add(namedArg);
1366
attributes[i] = new ResolvedSecurityAttribute {
1367
AttributeType = attributeType,
1368
NamedArguments = namedArgs,
1369
PositionalArguments = new ResolveResult[] { securityActionRR }
1374
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
1376
securityAction = provider.Intern(securityAction);
1379
int ISupportsInterning.GetHashCodeForInterning()
1381
return securityAction.GetHashCode() ^ GetBlobHashCode(blob);
1384
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
1386
UnresolvedSecurityDeclaration o = other as UnresolvedSecurityDeclaration;
1387
return o != null && securityAction == o.securityAction && BlobEquals(blob, o.blob);
1392
sealed class UnresolvedSecurityAttribute : IUnresolvedAttribute
1394
readonly UnresolvedSecurityDeclaration secDecl;
1397
public UnresolvedSecurityAttribute(UnresolvedSecurityDeclaration secDecl, int index)
1399
Debug.Assert(secDecl != null);
1400
this.secDecl = secDecl;
1404
DomRegion IUnresolvedAttribute.Region {
1405
get { return DomRegion.Empty; }
1408
IAttribute IUnresolvedAttribute.CreateResolvedAttribute(ITypeResolveContext context)
1410
return secDecl.Resolve(context.CurrentAssembly)[index];
1414
sealed class ResolvedSecurityAttribute : IAttribute
1416
public IType AttributeType { get; internal set; }
1418
DomRegion IAttribute.Region {
1419
get { return DomRegion.Empty; }
1422
volatile IMethod constructor;
1424
public IMethod Constructor {
1426
IMethod ctor = this.constructor;
1428
foreach (IMethod candidate in this.AttributeType.GetConstructors(m => m.Parameters.Count == 1)) {
1429
if (candidate.Parameters[0].Type.Equals(this.PositionalArguments[0].Type)) {
1434
this.constructor = ctor;
1440
public IList<ResolveResult> PositionalArguments { get; internal set; }
1442
public IList<KeyValuePair<IMember, ResolveResult>> NamedArguments { get; internal set; }
1447
#region Read Type Definition
1448
DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinition typeDefinition)
1450
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(typeDefinition.Name);
1451
var td = new DefaultUnresolvedTypeDefinition(typeDefinition.Namespace, name);
1452
InitTypeParameters(typeDefinition, td);
1456
static void InitTypeParameters(TypeDefinition typeDefinition, DefaultUnresolvedTypeDefinition td)
1458
// Type parameters are initialized within the constructor so that the class can be put into the type storage
1459
// before the rest of the initialization runs - this allows it to be available for early binding as soon as possible.
1460
for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) {
1461
if (typeDefinition.GenericParameters[i].Position != i)
1462
throw new InvalidOperationException("g.Position != i");
1463
td.TypeParameters.Add(new DefaultUnresolvedTypeParameter(
1464
EntityType.TypeDefinition, i, typeDefinition.GenericParameters[i].Name));
1468
void InitTypeDefinition(TypeDefinition typeDefinition, DefaultUnresolvedTypeDefinition td)
1470
InitTypeModifiers(typeDefinition, td);
1472
if (typeDefinition.HasGenericParameters) {
1473
for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) {
1474
AddConstraints((DefaultUnresolvedTypeParameter)td.TypeParameters[i], typeDefinition.GenericParameters[i]);
1478
InitNestedTypes(typeDefinition, td); // nested types can be initialized only after generic parameters were created
1479
AddAttributes(typeDefinition, td);
1480
td.HasExtensionMethods = HasExtensionAttribute(typeDefinition);
1483
if (typeDefinition.IsEnum) {
1484
foreach (FieldDefinition enumField in typeDefinition.Fields) {
1485
if (!enumField.IsStatic) {
1486
td.BaseTypes.Add(ReadTypeReference(enumField.FieldType));
1491
if (typeDefinition.BaseType != null) {
1492
td.BaseTypes.Add(ReadTypeReference(typeDefinition.BaseType));
1494
if (typeDefinition.HasInterfaces) {
1495
foreach (TypeReference iface in typeDefinition.Interfaces) {
1496
td.BaseTypes.Add(ReadTypeReference(iface));
1501
InitMembers(typeDefinition, td);
1502
if (HasCecilReferences)
1503
typeSystemTranslationTable[td] = typeDefinition;
1504
if (this.InterningProvider != null) {
1505
td.ApplyInterningProvider(this.InterningProvider);
1510
void InitNestedTypes(TypeDefinition typeDefinition, DefaultUnresolvedTypeDefinition td)
1512
if (!typeDefinition.HasNestedTypes)
1514
foreach (TypeDefinition nestedTypeDef in typeDefinition.NestedTypes) {
1515
TypeAttributes visibility = nestedTypeDef.Attributes & TypeAttributes.VisibilityMask;
1516
if (this.IncludeInternalMembers
1517
|| visibility == TypeAttributes.NestedPublic
1518
|| visibility == TypeAttributes.NestedFamily
1519
|| visibility == TypeAttributes.NestedFamORAssem)
1521
string name = nestedTypeDef.Name;
1522
int pos = name.LastIndexOf('/');
1524
name = name.Substring(pos + 1);
1525
if (name.Length == 0 || name[0] == '<')
1527
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
1528
var nestedType = new DefaultUnresolvedTypeDefinition(td, name);
1529
InitTypeParameters(nestedTypeDef, nestedType);
1530
td.NestedTypes.Add(nestedType);
1531
InitTypeDefinition(nestedTypeDef, nestedType);
1536
static void InitTypeModifiers(TypeDefinition typeDefinition, DefaultUnresolvedTypeDefinition td)
1539
if (typeDefinition.IsInterface) {
1540
td.Kind = TypeKind.Interface;
1541
} else if (typeDefinition.IsEnum) {
1542
td.Kind = TypeKind.Enum;
1543
} else if (typeDefinition.IsValueType) {
1544
td.Kind = TypeKind.Struct;
1545
} else if (IsDelegate(typeDefinition)) {
1546
td.Kind = TypeKind.Delegate;
1547
} else if (IsModule(typeDefinition)) {
1548
td.Kind = TypeKind.Module;
1550
td.Kind = TypeKind.Class;
1552
td.IsSealed = typeDefinition.IsSealed;
1553
td.IsAbstract = typeDefinition.IsAbstract;
1554
switch (typeDefinition.Attributes & TypeAttributes.VisibilityMask) {
1555
case TypeAttributes.NotPublic:
1556
case TypeAttributes.NestedAssembly:
1557
td.Accessibility = Accessibility.Internal;
1559
case TypeAttributes.Public:
1560
case TypeAttributes.NestedPublic:
1561
td.Accessibility = Accessibility.Public;
1563
case TypeAttributes.NestedPrivate:
1564
td.Accessibility = Accessibility.Private;
1566
case TypeAttributes.NestedFamily:
1567
td.Accessibility = Accessibility.Protected;
1569
case TypeAttributes.NestedFamANDAssem:
1570
td.Accessibility = Accessibility.ProtectedAndInternal;
1572
case TypeAttributes.NestedFamORAssem:
1573
td.Accessibility = Accessibility.ProtectedOrInternal;
1578
static bool IsDelegate(TypeDefinition type)
1580
if (type.BaseType == null)
1583
return type.BaseType.FullName == "System.Delegate"
1584
|| type.BaseType.FullName == "System.MulticastDelegate";
1587
static bool IsModule(TypeDefinition type)
1589
if (!type.HasCustomAttributes)
1591
foreach (var att in type.CustomAttributes) {
1592
if (att.AttributeType.FullName == "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute"
1593
|| att.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute")
1601
void InitMembers(TypeDefinition typeDefinition, DefaultUnresolvedTypeDefinition td)
1603
td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum);
1604
if (typeDefinition.HasMethods) {
1605
foreach (MethodDefinition method in typeDefinition.Methods) {
1606
if (IsVisible(method.Attributes) && !IsAccessor(method.SemanticsAttributes)) {
1607
EntityType type = EntityType.Method;
1608
if (method.IsSpecialName) {
1609
if (method.IsConstructor)
1610
type = EntityType.Constructor;
1611
else if (method.Name.StartsWith("op_", StringComparison.Ordinal))
1612
type = EntityType.Operator;
1614
td.Members.Add(ReadMethod(method, td, type));
1618
if (typeDefinition.HasFields) {
1619
foreach (FieldDefinition field in typeDefinition.Fields) {
1620
if (IsVisible(field.Attributes) && !field.IsSpecialName) {
1621
td.Members.Add(ReadField(field, td));
1625
if (typeDefinition.HasProperties) {
1626
string defaultMemberName = null;
1627
var defaultMemberAttribute = typeDefinition.CustomAttributes.FirstOrDefault(
1628
a => a.AttributeType.FullName == typeof(System.Reflection.DefaultMemberAttribute).FullName);
1629
if (defaultMemberAttribute != null && defaultMemberAttribute.ConstructorArguments.Count == 1) {
1630
defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string;
1632
foreach (PropertyDefinition property in typeDefinition.Properties) {
1633
bool getterVisible = property.GetMethod != null && IsVisible(property.GetMethod.Attributes);
1634
bool setterVisible = property.SetMethod != null && IsVisible(property.SetMethod.Attributes);
1635
if (getterVisible || setterVisible) {
1636
EntityType type = property.Name == defaultMemberName ? EntityType.Indexer : EntityType.Property;
1637
td.Members.Add(ReadProperty(property, td, type));
1641
if (typeDefinition.HasEvents) {
1642
foreach (EventDefinition ev in typeDefinition.Events) {
1643
if (ev.AddMethod != null && IsVisible(ev.AddMethod.Attributes)) {
1644
td.Members.Add(ReadEvent(ev, td));
1650
static bool IsAccessor(MethodSemanticsAttributes semantics)
1652
return !(semantics == MethodSemanticsAttributes.None || semantics == MethodSemanticsAttributes.Other);
1657
[CLSCompliant(false)]
1658
public IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, EntityType methodType = EntityType.Method)
1662
DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, method.Name);
1663
m.EntityType = methodType;
1664
if (method.HasGenericParameters) {
1665
for (int i = 0; i < method.GenericParameters.Count; i++) {
1666
if (method.GenericParameters[i].Position != i)
1667
throw new InvalidOperationException("g.Position != i");
1668
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(
1669
EntityType.Method, i, method.GenericParameters[i].Name));
1671
for (int i = 0; i < method.GenericParameters.Count; i++) {
1672
AddConstraints((DefaultUnresolvedTypeParameter)m.TypeParameters[i], method.GenericParameters[i]);
1676
m.ReturnType = ReadTypeReference(method.ReturnType, typeAttributes: method.MethodReturnType);
1678
if (HasAnyAttributes(method))
1679
AddAttributes(method, m.Attributes, m.ReturnTypeAttributes);
1680
TranslateModifiers(method, m);
1682
if (method.HasParameters) {
1683
foreach (ParameterDefinition p in method.Parameters) {
1684
m.Parameters.Add(ReadParameter(p));
1688
// mark as extension method if the attribute is set
1689
if (method.IsStatic && HasExtensionAttribute(method)) {
1690
m.IsExtensionMethod = true;
1693
FinishReadMember(m, method);
1697
static bool HasExtensionAttribute(ICustomAttributeProvider provider)
1699
if (provider.HasCustomAttributes) {
1700
foreach (var attr in provider.CustomAttributes) {
1701
if (attr.AttributeType.Name == "ExtensionAttribute" && attr.AttributeType.Namespace == "System.Runtime.CompilerServices")
1708
bool IsVisible(MethodAttributes att)
1710
att &= MethodAttributes.MemberAccessMask;
1711
return IncludeInternalMembers
1712
|| att == MethodAttributes.Public
1713
|| att == MethodAttributes.Family
1714
|| att == MethodAttributes.FamORAssem;
1717
static Accessibility GetAccessibility(MethodAttributes attr)
1719
switch (attr & MethodAttributes.MemberAccessMask) {
1720
case MethodAttributes.Public:
1721
return Accessibility.Public;
1722
case MethodAttributes.FamANDAssem:
1723
return Accessibility.ProtectedAndInternal;
1724
case MethodAttributes.Assembly:
1725
return Accessibility.Internal;
1726
case MethodAttributes.Family:
1727
return Accessibility.Protected;
1728
case MethodAttributes.FamORAssem:
1729
return Accessibility.ProtectedOrInternal;
1731
return Accessibility.Private;
1735
void TranslateModifiers(MethodDefinition method, AbstractUnresolvedMember m)
1737
if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) {
1738
// interface members don't have modifiers, but we want to handle them as "public abstract"
1739
m.Accessibility = Accessibility.Public;
1740
m.IsAbstract = true;
1742
m.Accessibility = GetAccessibility(method.Attributes);
1743
if (method.IsAbstract) {
1744
m.IsAbstract = true;
1745
m.IsOverride = !method.IsNewSlot;
1746
} else if (method.IsFinal) {
1747
if (!method.IsNewSlot) {
1749
m.IsOverride = true;
1751
} else if (method.IsVirtual) {
1752
if (method.IsNewSlot)
1755
m.IsOverride = true;
1757
m.IsStatic = method.IsStatic;
1762
#region Read Parameter
1763
[CLSCompliant(false)]
1764
public IUnresolvedParameter ReadParameter(ParameterDefinition parameter)
1766
if (parameter == null)
1767
throw new ArgumentNullException("parameter");
1768
var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter);
1769
var p = new DefaultUnresolvedParameter(type, parameter.Name);
1771
if (parameter.ParameterType is Mono.Cecil.ByReferenceType) {
1772
if (!parameter.IsIn && parameter.IsOut)
1777
AddAttributes(parameter, p);
1779
if (parameter.IsOptional) {
1780
p.DefaultValue = new SimpleConstantValue(type, parameter.Constant);
1783
if (parameter.ParameterType is Mono.Cecil.ArrayType) {
1784
foreach (CustomAttribute att in parameter.CustomAttributes) {
1785
if (att.AttributeType.FullName == typeof(ParamArrayAttribute).FullName) {
1797
bool IsVisible(FieldAttributes att)
1799
att &= FieldAttributes.FieldAccessMask;
1800
return IncludeInternalMembers
1801
|| att == FieldAttributes.Public
1802
|| att == FieldAttributes.Family
1803
|| att == FieldAttributes.FamORAssem;
1806
[CLSCompliant(false)]
1807
public IUnresolvedField ReadField(FieldDefinition field, IUnresolvedTypeDefinition parentType)
1810
throw new ArgumentNullException("field");
1811
if (parentType == null)
1812
throw new ArgumentNullException("parentType");
1814
DefaultUnresolvedField f = new DefaultUnresolvedField(parentType, field.Name);
1815
f.Accessibility = GetAccessibility(field.Attributes);
1816
f.IsReadOnly = field.IsInitOnly;
1817
f.IsStatic = field.IsStatic;
1818
f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field);
1819
if (field.HasConstant) {
1820
f.ConstantValue = new SimpleConstantValue(f.ReturnType, field.Constant);
1822
AddAttributes(field, f);
1824
RequiredModifierType modreq = field.FieldType as RequiredModifierType;
1825
if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName) {
1826
f.IsVolatile = true;
1829
FinishReadMember(f, field);
1833
static Accessibility GetAccessibility(FieldAttributes attr)
1835
switch (attr & FieldAttributes.FieldAccessMask) {
1836
case FieldAttributes.Public:
1837
return Accessibility.Public;
1838
case FieldAttributes.FamANDAssem:
1839
return Accessibility.ProtectedAndInternal;
1840
case FieldAttributes.Assembly:
1841
return Accessibility.Internal;
1842
case FieldAttributes.Family:
1843
return Accessibility.Protected;
1844
case FieldAttributes.FamORAssem:
1845
return Accessibility.ProtectedOrInternal;
1847
return Accessibility.Private;
1852
#region Type Parameter Constraints
1853
void AddConstraints(DefaultUnresolvedTypeParameter tp, GenericParameter g)
1855
switch (g.Attributes & GenericParameterAttributes.VarianceMask) {
1856
case GenericParameterAttributes.Contravariant:
1857
tp.Variance = VarianceModifier.Contravariant;
1859
case GenericParameterAttributes.Covariant:
1860
tp.Variance = VarianceModifier.Covariant;
1864
tp.HasReferenceTypeConstraint = g.HasReferenceTypeConstraint;
1865
tp.HasValueTypeConstraint = g.HasNotNullableValueTypeConstraint;
1866
tp.HasDefaultConstructorConstraint = g.HasDefaultConstructorConstraint;
1868
if (g.HasConstraints) {
1869
foreach (TypeReference constraint in g.Constraints) {
1870
tp.Constraints.Add(ReadTypeReference(constraint));
1876
#region Read Property
1877
[CLSCompliant(false)]
1878
public IUnresolvedProperty ReadProperty(PropertyDefinition property, IUnresolvedTypeDefinition parentType, EntityType propertyType = EntityType.Property)
1880
if (property == null)
1881
throw new ArgumentNullException("property");
1882
if (parentType == null)
1883
throw new ArgumentNullException("parentType");
1884
DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(parentType, property.Name);
1885
p.EntityType = propertyType;
1886
TranslateModifiers(property.GetMethod ?? property.SetMethod, p);
1887
p.ReturnType = ReadTypeReference(property.PropertyType, typeAttributes: property);
1889
p.Getter = ReadMethod(property.GetMethod, parentType);
1890
p.Setter = ReadMethod(property.SetMethod, parentType);
1892
if (property.HasParameters) {
1893
foreach (ParameterDefinition par in property.Parameters) {
1894
p.Parameters.Add(ReadParameter(par));
1897
AddAttributes(property, p);
1899
FinishReadMember(p, property);
1905
[CLSCompliant(false)]
1906
public IUnresolvedEvent ReadEvent(EventDefinition ev, IUnresolvedTypeDefinition parentType)
1909
throw new ArgumentNullException("ev");
1910
if (parentType == null)
1911
throw new ArgumentNullException("parentType");
1913
DefaultUnresolvedEvent e = new DefaultUnresolvedEvent(parentType, ev.Name);
1914
TranslateModifiers(ev.AddMethod, e);
1915
e.ReturnType = ReadTypeReference(ev.EventType, typeAttributes: ev);
1917
e.AddAccessor = ReadMethod(ev.AddMethod, parentType);
1918
e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType);
1919
e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType);
1921
AddAttributes(ev, e);
1923
FinishReadMember(e, ev);
1929
void FinishReadMember(AbstractUnresolvedMember member, object cecilDefinition)
1931
member.ApplyInterningProvider(this.InterningProvider);
1933
if (HasCecilReferences)
1934
typeSystemTranslationTable[member] = cecilDefinition;
1937
#region Type system translation table
1938
Dictionary<object, object> typeSystemTranslationTable;
1940
T InternalGetCecilObject<T> (object typeSystemObject) where T : class
1942
if (typeSystemObject == null)
1943
throw new ArgumentNullException ("typeSystemObject");
1944
if (!HasCecilReferences)
1945
throw new NotSupportedException ("This instance contains no cecil references.");
1947
if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result))
1952
[CLSCompliant(false)]
1953
public AssemblyDefinition GetCecilObject (IUnresolvedAssembly content)
1955
return InternalGetCecilObject<AssemblyDefinition> (content);
1958
[CLSCompliant(false)]
1959
public TypeDefinition GetCecilObject (IUnresolvedTypeDefinition type)
1962
throw new ArgumentNullException ("type");
1963
return InternalGetCecilObject<TypeDefinition> (type);
1966
[CLSCompliant(false)]
1967
public MethodDefinition GetCecilObject (IUnresolvedMethod method)
1969
return InternalGetCecilObject<MethodDefinition> (method);
1972
[CLSCompliant(false)]
1973
public FieldDefinition GetCecilObject (IUnresolvedField field)
1975
return InternalGetCecilObject<FieldDefinition> (field);
1978
[CLSCompliant(false)]
1979
public EventDefinition GetCecilObject (IUnresolvedEvent evt)
1981
return InternalGetCecilObject<EventDefinition> (evt);
1984
[CLSCompliant(false)]
1985
public PropertyDefinition GetCecilObject (IUnresolvedProperty property)
1987
return InternalGetCecilObject<PropertyDefinition> (property);