Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RemoveBackwardsCompatibility/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.Cecil-5.5.0/CecilLoader.cs @ 18242

Last change on this file since 18242 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 67.0 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
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:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
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.
18
19using System;
20using System.Collections.Generic;
21using System.Diagnostics;
22using System.Linq;
23using System.Runtime.CompilerServices;
24using System.Runtime.InteropServices;
25using System.Threading;
26using ICSharpCode.NRefactory.Documentation;
27using ICSharpCode.NRefactory.Semantics;
28using ICSharpCode.NRefactory.TypeSystem.Implementation;
29using ICSharpCode.NRefactory.Utils;
30using Mono.Cecil;
31
32
33namespace ICSharpCode.NRefactory.TypeSystem
34{
35  /// <summary>
36  /// Allows loading an IProjectContent from an already compiled assembly.
37  /// </summary>
38  /// <remarks>Instance methods are not thread-safe; you need to create multiple instances of CecilLoader
39  /// if you want to load multiple project contents in parallel.</remarks>
40  public sealed class CecilLoader : AssemblyLoader
41  {
42    /// <summary>
43    /// Version number of the cecil loader.
44    /// Should be incremented when fixing bugs in the cecil loader so that project contents cached on disk
45    /// (which might be incorrect due to the bug) are re-created.
46    /// </summary>
47    const int cecilLoaderVersion = 1;
48   
49    #region Options
50    // Most options are defined in the AssemblyLoader base class
51   
52    /// <summary>
53    /// Specifies whether to use lazy loading. The default is false.
54    /// If this property is set to true, the CecilLoader will not copy all the relevant information
55    /// out of the Cecil object model, but will maintain references to the Cecil objects.
56    /// This speeds up the loading process and avoids loading unnecessary information, but it causes
57    /// the Cecil objects to stay in memory (which can significantly increase memory usage).
58    /// It also prevents serialization of the Cecil-loaded type system.
59    /// </summary>
60    /// <remarks>
61    /// Because the type system can be used on multiple threads, but Cecil is not
62    /// thread-safe for concurrent read access, the CecilLoader will lock on the <see cref="ModuleDefinition"/> instance
63    /// for every delay-loading operation.
64    /// If you access the Cecil objects directly in your application, you may need to take the same lock.
65    /// </remarks>
66    public bool LazyLoad { get; set; }
67   
68    /// <summary>
69    /// This delegate gets executed whenever an entity was loaded.
70    /// </summary>
71    /// <remarks>
72    /// This callback may be to build a dictionary that maps between
73    /// entities and cecil objects.
74    /// Warning: if delay-loading is used and the type system is accessed by multiple threads,
75    /// the callback may be invoked concurrently on multiple threads.
76    /// </remarks>
77    [CLSCompliant(false)]
78    public Action<IUnresolvedEntity, MemberReference> OnEntityLoaded { get; set; }
79   
80    /// <summary>
81    /// Gets a value indicating whether this instance stores references to the cecil objects.
82    /// </summary>
83    /// <value>
84    /// <c>true</c> if this instance has references to the cecil objects; otherwise, <c>false</c>.
85    /// </value>
86    public bool HasCecilReferences { get { return typeSystemTranslationTable != null; } }
87    #endregion
88   
89    ModuleDefinition currentModule;
90    CecilUnresolvedAssembly currentAssembly;
91   
92    /// <summary>
93    /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.CecilLoader"/> class.
94    /// </summary>
95    public CecilLoader()
96    {
97    }
98   
99    /// <summary>
100    /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.CecilLoader"/> class.
101    /// </summary>
102    /// <param name='createCecilReferences'>
103    /// If true references to the cecil objects are hold. In this case the cecil loader can do a type system -> cecil mapping.
104    /// </param>
105    [Obsolete("The built-in entity<->cecil mapping is obsolete. Use the OnEntityLoaded callback instead!")]
106    public CecilLoader(bool createCecilReferences) : this()
107    {
108      if (createCecilReferences)
109        typeSystemTranslationTable = new Dictionary<object, object> ();
110    }
111   
112    /// <summary>
113    /// Creates a nested CecilLoader for lazy-loading.
114    /// </summary>
115    private CecilLoader(CecilLoader loader)
116    {
117      // use a shared typeSystemTranslationTable
118      this.typeSystemTranslationTable = loader.typeSystemTranslationTable;
119      this.IncludeInternalMembers = loader.IncludeInternalMembers;
120      this.LazyLoad = loader.LazyLoad;
121      this.OnEntityLoaded = loader.OnEntityLoaded;
122      this.currentModule = loader.currentModule;
123      this.currentAssembly = loader.currentAssembly;
124      // don't use interning - the interning provider is most likely not thread-safe
125      this.interningProvider = InterningProvider.Dummy;
126      // don't use cancellation for delay-loaded members
127    }
128
129    #region Load From AssemblyDefinition
130    /// <summary>
131    /// Loads the assembly definition into a project content.
132    /// </summary>
133    /// <returns>Unresolved type system representing the assembly</returns>
134    [CLSCompliant(false)]
135    public IUnresolvedAssembly LoadAssembly(AssemblyDefinition assemblyDefinition)
136    {
137      if (assemblyDefinition == null)
138        throw new ArgumentNullException("assemblyDefinition");
139      return LoadModule(assemblyDefinition.MainModule);
140    }
141   
142    /// <summary>
143    /// Loads the module definition into a project content.
144    /// </summary>
145    /// <returns>Unresolved type system representing the assembly</returns>
146    [CLSCompliant(false)]
147    public IUnresolvedAssembly LoadModule(ModuleDefinition moduleDefinition)
148    {
149      if (moduleDefinition == null)
150        throw new ArgumentNullException("moduleDefinition");
151     
152      this.currentModule = moduleDefinition;
153     
154      // Read assembly and module attributes
155      IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>();
156      IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>();
157      AssemblyDefinition assemblyDefinition = moduleDefinition.Assembly;
158      if (assemblyDefinition != null) {
159        AddAttributes(assemblyDefinition, assemblyAttributes);
160      }
161      AddAttributes(moduleDefinition, moduleAttributes);
162     
163      assemblyAttributes = interningProvider.InternList(assemblyAttributes);
164      moduleAttributes = interningProvider.InternList(moduleAttributes);
165     
166      this.currentAssembly = new CecilUnresolvedAssembly(assemblyDefinition != null ? assemblyDefinition.Name.FullName : moduleDefinition.Name, this.DocumentationProvider);
167      currentAssembly.Location = moduleDefinition.FullyQualifiedName;
168      currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
169      currentAssembly.ModuleAttributes.AddRange(assemblyAttributes);
170     
171      // Register type forwarders:
172      foreach (ExportedType type in moduleDefinition.ExportedTypes) {
173        if (type.IsForwarder) {
174          int typeParameterCount;
175          string ns = type.Namespace;
176          string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
177          ns = interningProvider.Intern(ns);
178          name = interningProvider.Intern(name);
179          var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount);
180          typeRef = interningProvider.Intern(typeRef);
181          var key = new TopLevelTypeName(ns, name, typeParameterCount);
182          currentAssembly.AddTypeForwarder(key, typeRef);
183        }
184      }
185     
186      // Create and register all types:
187      CecilLoader cecilLoaderCloneForLazyLoading = LazyLoad ? new CecilLoader(this) : null;
188      List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>();
189      List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>();
190      foreach (TypeDefinition td in moduleDefinition.Types) {
191        this.CancellationToken.ThrowIfCancellationRequested();
192        if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
193          string name = td.Name;
194          if (name.Length == 0)
195            continue;
196         
197          if (this.LazyLoad) {
198            var t = new LazyCecilTypeDefinition(cecilLoaderCloneForLazyLoading, td);
199            currentAssembly.AddTypeDefinition(t);
200            RegisterCecilObject(t, td);
201          } else {
202            var t = CreateTopLevelTypeDefinition(td);
203            cecilTypeDefs.Add(td);
204            typeDefs.Add(t);
205            currentAssembly.AddTypeDefinition(t);
206            // The registration will happen after the members are initialized
207          }
208        }
209      }
210      // Initialize the type's members:
211      for (int i = 0; i < typeDefs.Count; i++) {
212        InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]);
213      }
214     
215      AddToTypeSystemTranslationTable(this.currentAssembly, assemblyDefinition);
216      // Freezing the assembly here is important:
217      // otherwise it will be frozen when a compilation is first created
218      // from it. But freezing has the effect of changing some collection instances
219      // (to ReadOnlyCollection). This hidden mutation was causing a crash
220      // when the FastSerializer was saving the assembly at the same time as
221      // the first compilation was created from it.
222      // By freezing the assembly now, we ensure it is usable on multiple
223      // threads without issues.
224      currentAssembly.Freeze();
225     
226      var result = this.currentAssembly;
227      this.currentAssembly = null;
228      this.currentModule = null;
229      return result;
230    }
231   
232    /// <summary>
233    /// Sets the current module.
234    /// This causes ReadTypeReference() to use <see cref="DefaultAssemblyReference.CurrentAssembly"/> for references
235    /// in that module.
236    /// </summary>
237    [CLSCompliant(false)]
238    public void SetCurrentModule(ModuleDefinition module)
239    {
240      this.currentModule = module;
241    }
242   
243    /// <summary>
244    /// Loads a type from Cecil.
245    /// </summary>
246    /// <param name="typeDefinition">The Cecil TypeDefinition.</param>
247    /// <returns>ITypeDefinition representing the Cecil type.</returns>
248    [CLSCompliant(false)]
249    public IUnresolvedTypeDefinition LoadType(TypeDefinition typeDefinition)
250    {
251      if (typeDefinition == null)
252        throw new ArgumentNullException("typeDefinition");
253      var td = CreateTopLevelTypeDefinition(typeDefinition);
254      InitTypeDefinition(typeDefinition, td);
255      return td;
256    }
257    #endregion
258   
259    #region IUnresolvedAssembly implementation
260    [Serializable, FastSerializerVersion(cecilLoaderVersion)]
261    sealed class CecilUnresolvedAssembly : DefaultUnresolvedAssembly, IDocumentationProvider
262    {
263      readonly IDocumentationProvider documentationProvider;
264     
265      public CecilUnresolvedAssembly(string fullAssemblyName, IDocumentationProvider documentationProvider)
266        : base(fullAssemblyName)
267      {
268        this.documentationProvider = documentationProvider;
269      }
270     
271      DocumentationComment IDocumentationProvider.GetDocumentation(IEntity entity)
272      {
273        if (documentationProvider != null)
274          return documentationProvider.GetDocumentation(entity);
275        else
276          return null;
277      }
278    }
279    #endregion
280   
281    #region Load Assembly From Disk
282    public override IUnresolvedAssembly LoadAssemblyFile(string fileName)
283    {
284      if (fileName == null)
285        throw new ArgumentNullException("fileName");
286      var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() };
287      ModuleDefinition module = ModuleDefinition.ReadModule(fileName, param);
288      return LoadModule(module);
289    }
290   
291    // used to prevent Cecil from loading referenced assemblies
292    sealed class DummyAssemblyResolver : IAssemblyResolver
293    {
294      public AssemblyDefinition Resolve(AssemblyNameReference name)
295      {
296        return null;
297      }
298     
299      public AssemblyDefinition Resolve(string fullName)
300      {
301        return null;
302      }
303     
304      public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
305      {
306        return null;
307      }
308     
309      public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters)
310      {
311        return null;
312      }
313    }
314    #endregion
315   
316    #region Read Type Reference
317    /// <summary>
318    /// Reads a type reference.
319    /// </summary>
320    /// <param name="type">The Cecil type reference that should be converted into
321    /// a type system type reference.</param>
322    /// <param name="typeAttributes">Attributes associated with the Cecil type reference.
323    /// This is used to support the 'dynamic' type.</param>
324    [CLSCompliant(false)]
325    public ITypeReference ReadTypeReference(TypeReference type, ICustomAttributeProvider typeAttributes = null)
326    {
327      int typeIndex = 0;
328      return CreateType(type, typeAttributes, ref typeIndex);
329    }
330   
331    ITypeReference CreateType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex)
332    {
333      while (type is OptionalModifierType || type is RequiredModifierType) {
334        type = ((TypeSpecification)type).ElementType;
335      }
336      if (type == null) {
337        return SpecialType.UnknownType;
338      }
339     
340      if (type is Mono.Cecil.ByReferenceType) {
341        typeIndex++;
342        return interningProvider.Intern(
343          new ByReferenceTypeReference(
344            CreateType(
345              (type as Mono.Cecil.ByReferenceType).ElementType,
346              typeAttributes, ref typeIndex)));
347      } else if (type is Mono.Cecil.PointerType) {
348        typeIndex++;
349        return interningProvider.Intern(
350          new PointerTypeReference(
351            CreateType(
352              (type as Mono.Cecil.PointerType).ElementType,
353              typeAttributes, ref typeIndex)));
354      } else if (type is Mono.Cecil.ArrayType) {
355        typeIndex++;
356        return interningProvider.Intern(
357          new ArrayTypeReference(
358            CreateType(
359              (type as Mono.Cecil.ArrayType).ElementType,
360              typeAttributes, ref typeIndex),
361            (type as Mono.Cecil.ArrayType).Rank));
362      } else if (type is GenericInstanceType) {
363        GenericInstanceType gType = (GenericInstanceType)type;
364        ITypeReference baseType = CreateType(gType.ElementType, typeAttributes, ref typeIndex);
365        ITypeReference[] para = new ITypeReference[gType.GenericArguments.Count];
366        for (int i = 0; i < para.Length; ++i) {
367          typeIndex++;
368          para[i] = CreateType(gType.GenericArguments[i], typeAttributes, ref typeIndex);
369        }
370        return interningProvider.Intern(new ParameterizedTypeReference(baseType, para));
371      } else if (type is GenericParameter) {
372        GenericParameter typeGP = (GenericParameter)type;
373        return TypeParameterReference.Create(typeGP.Owner is MethodDefinition ? SymbolKind.Method : SymbolKind.TypeDefinition, typeGP.Position);
374      } else if (type.IsNested) {
375        ITypeReference typeRef = CreateType(type.DeclaringType, typeAttributes, ref typeIndex);
376        int partTypeParameterCount;
377        string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out partTypeParameterCount);
378        namepart = interningProvider.Intern(namepart);
379        return interningProvider.Intern(new NestedTypeReference(typeRef, namepart, partTypeParameterCount));
380      } else {
381        string ns = interningProvider.Intern(type.Namespace ?? string.Empty);
382        string name = type.Name;
383        if (name == null)
384          throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
385       
386        if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
387          return SpecialType.Dynamic;
388        } else {
389          int typeParameterCount;
390          name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount);
391          name = interningProvider.Intern(name);
392          if (currentAssembly != null) {
393            IUnresolvedTypeDefinition c = currentAssembly.GetTypeDefinition(ns, name, typeParameterCount);
394            if (c != null)
395              return c;
396          }
397          return interningProvider.Intern(new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount));
398        }
399      }
400    }
401   
402    IAssemblyReference GetAssemblyReference(IMetadataScope scope)
403    {
404      if (scope == null || scope == currentModule)
405        return DefaultAssemblyReference.CurrentAssembly;
406      else
407        return interningProvider.Intern(new DefaultAssemblyReference(scope.Name));
408    }
409   
410    static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
411    {
412      if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
413        return false;
414      foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
415        TypeReference type = a.AttributeType;
416        if (type.Name == "DynamicAttribute" && type.Namespace == "System.Runtime.CompilerServices") {
417          if (a.ConstructorArguments.Count == 1) {
418            CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
419            if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
420              return (bool)values[typeIndex].Value;
421          }
422          return true;
423        }
424      }
425      return false;
426    }
427    #endregion
428   
429    #region Read Attributes
430    #region Assembly Attributes
431    static readonly ITypeReference assemblyVersionAttributeTypeRef = typeof(System.Reflection.AssemblyVersionAttribute).ToTypeReference();
432   
433    void AddAttributes(AssemblyDefinition assembly, IList<IUnresolvedAttribute> outputList)
434    {
435      if (assembly.HasCustomAttributes) {
436        AddCustomAttributes(assembly.CustomAttributes, outputList);
437      }
438      if (assembly.HasSecurityDeclarations) {
439        AddSecurityAttributes(assembly.SecurityDeclarations, outputList);
440      }
441     
442      // AssemblyVersionAttribute
443      if (assembly.Name.Version != null) {
444        var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String });
445        assemblyVersion.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString()));
446        outputList.Add(interningProvider.Intern(assemblyVersion));
447      }
448    }
449   
450    IConstantValue CreateSimpleConstantValue(ITypeReference type, object value)
451    {
452      return interningProvider.Intern(new SimpleConstantValue(type, interningProvider.InternValue(value)));
453    }
454    #endregion
455   
456    #region Module Attributes
457    void AddAttributes(ModuleDefinition module, IList<IUnresolvedAttribute> outputList)
458    {
459      if (module.HasCustomAttributes) {
460        AddCustomAttributes(module.CustomAttributes, outputList);
461      }
462    }
463    #endregion
464   
465    #region Parameter Attributes
466    static readonly IUnresolvedAttribute inAttribute = new DefaultUnresolvedAttribute(typeof(InAttribute).ToTypeReference());
467    static readonly IUnresolvedAttribute outAttribute = new DefaultUnresolvedAttribute(typeof(OutAttribute).ToTypeReference());
468   
469    void AddAttributes(ParameterDefinition parameter, DefaultUnresolvedParameter targetParameter)
470    {
471      if (!targetParameter.IsOut) {
472        if (parameter.IsIn)
473          targetParameter.Attributes.Add(inAttribute);
474        if (parameter.IsOut)
475          targetParameter.Attributes.Add(outAttribute);
476      }
477      if (parameter.HasCustomAttributes) {
478        AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes);
479      }
480      if (parameter.HasMarshalInfo) {
481        targetParameter.Attributes.Add(ConvertMarshalInfo(parameter.MarshalInfo));
482      }
483    }
484    #endregion
485   
486    #region Method Attributes
487    static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference();
488    static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true);
489    static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, false);
490    static readonly ITypeReference callingConventionTypeRef = typeof(CallingConvention).ToTypeReference();
491    static readonly IUnresolvedAttribute preserveSigAttribute = new DefaultUnresolvedAttribute(typeof(PreserveSigAttribute).ToTypeReference());
492    static readonly ITypeReference methodImplAttributeTypeRef = typeof(MethodImplAttribute).ToTypeReference();
493    static readonly ITypeReference methodImplOptionsTypeRef = typeof(MethodImplOptions).ToTypeReference();
494   
495    static bool HasAnyAttributes(MethodDefinition methodDefinition)
496    {
497      if (methodDefinition.HasPInvokeInfo)
498        return true;
499      if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0)
500        return true;
501      if (methodDefinition.MethodReturnType.HasFieldMarshal)
502        return true;
503      return methodDefinition.HasCustomAttributes || methodDefinition.MethodReturnType.HasCustomAttributes;
504    }
505   
506    void AddAttributes(MethodDefinition methodDefinition, IList<IUnresolvedAttribute> attributes, IList<IUnresolvedAttribute> returnTypeAttributes)
507    {
508      MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
509     
510      #region DllImportAttribute
511      if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
512        PInvokeInfo info = methodDefinition.PInvokeInfo;
513        var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String });
514        dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, info.Module.Name));
515       
516        if (info.IsBestFitDisabled)
517          dllImport.AddNamedFieldArgument("BestFitMapping", falseValue);
518        if (info.IsBestFitEnabled)
519          dllImport.AddNamedFieldArgument("BestFitMapping", trueValue);
520       
521        CallingConvention callingConvention;
522        switch (info.Attributes & PInvokeAttributes.CallConvMask) {
523          case (PInvokeAttributes)0:
524            Debug.WriteLine ("P/Invoke calling convention not set on:" + methodDefinition.FullName);
525            callingConvention = 0;
526            break;
527          case PInvokeAttributes.CallConvCdecl:
528            callingConvention = CallingConvention.Cdecl;
529            break;
530          case PInvokeAttributes.CallConvFastcall:
531            callingConvention = CallingConvention.FastCall;
532            break;
533          case PInvokeAttributes.CallConvStdCall:
534            callingConvention = CallingConvention.StdCall;
535            break;
536          case PInvokeAttributes.CallConvThiscall:
537            callingConvention = CallingConvention.ThisCall;
538            break;
539          case PInvokeAttributes.CallConvWinapi:
540            callingConvention = CallingConvention.Winapi;
541            break;
542          default:
543            throw new NotSupportedException("unknown calling convention");
544        }
545        if (callingConvention != CallingConvention.Winapi)
546          dllImport.AddNamedFieldArgument("CallingConvention", CreateSimpleConstantValue(callingConventionTypeRef, (int)callingConvention));
547       
548        CharSet charSet = CharSet.None;
549        switch (info.Attributes & PInvokeAttributes.CharSetMask) {
550          case PInvokeAttributes.CharSetAnsi:
551            charSet = CharSet.Ansi;
552            break;
553          case PInvokeAttributes.CharSetAuto:
554            charSet = CharSet.Auto;
555            break;
556          case PInvokeAttributes.CharSetUnicode:
557            charSet = CharSet.Unicode;
558            break;
559        }
560        if (charSet != CharSet.None)
561          dllImport.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet));
562       
563        if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name)
564          dllImport.AddNamedFieldArgument("EntryPoint", CreateSimpleConstantValue(KnownTypeReference.String, info.EntryPoint));
565       
566        if (info.IsNoMangle)
567          dllImport.AddNamedFieldArgument("ExactSpelling", trueValue);
568       
569        if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
570          implAttributes &= ~MethodImplAttributes.PreserveSig;
571        else
572          dllImport.AddNamedFieldArgument("PreserveSig", falseValue);
573       
574        if (info.SupportsLastError)
575          dllImport.AddNamedFieldArgument("SetLastError", trueValue);
576       
577        if (info.IsThrowOnUnmappableCharDisabled)
578          dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", falseValue);
579        if (info.IsThrowOnUnmappableCharEnabled)
580          dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", trueValue);
581       
582        attributes.Add(interningProvider.Intern(dllImport));
583      }
584      #endregion
585     
586      #region PreserveSigAttribute
587      if (implAttributes == MethodImplAttributes.PreserveSig) {
588        attributes.Add(preserveSigAttribute);
589        implAttributes = 0;
590      }
591      #endregion
592     
593      #region MethodImplAttribute
594      if (implAttributes != 0) {
595        var methodImpl = new DefaultUnresolvedAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef });
596        methodImpl.PositionalArguments.Add(CreateSimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes));
597        attributes.Add(interningProvider.Intern(methodImpl));
598      }
599      #endregion
600     
601      if (methodDefinition.HasCustomAttributes) {
602        AddCustomAttributes(methodDefinition.CustomAttributes, attributes);
603      }
604      if (methodDefinition.HasSecurityDeclarations) {
605        AddSecurityAttributes(methodDefinition.SecurityDeclarations, attributes);
606      }
607      if (methodDefinition.MethodReturnType.HasMarshalInfo) {
608        returnTypeAttributes.Add(ConvertMarshalInfo(methodDefinition.MethodReturnType.MarshalInfo));
609      }
610      if (methodDefinition.MethodReturnType.HasCustomAttributes) {
611        AddCustomAttributes(methodDefinition.MethodReturnType.CustomAttributes, returnTypeAttributes);
612      }
613    }
614    #endregion
615   
616    #region Type Attributes
617    static readonly DefaultUnresolvedAttribute serializableAttribute = new DefaultUnresolvedAttribute(typeof(SerializableAttribute).ToTypeReference());
618    static readonly DefaultUnresolvedAttribute comImportAttribute = new DefaultUnresolvedAttribute(typeof(ComImportAttribute).ToTypeReference());
619    static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference();
620    static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference();
621    static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference();
622   
623    void AddAttributes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition targetEntity)
624    {
625      // SerializableAttribute
626      if (typeDefinition.IsSerializable)
627        targetEntity.Attributes.Add(serializableAttribute);
628     
629      // ComImportAttribute
630      if (typeDefinition.IsImport)
631        targetEntity.Attributes.Add(comImportAttribute);
632     
633      #region StructLayoutAttribute
634      LayoutKind layoutKind = LayoutKind.Auto;
635      switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) {
636        case TypeAttributes.SequentialLayout:
637          layoutKind = LayoutKind.Sequential;
638          break;
639        case TypeAttributes.ExplicitLayout:
640          layoutKind = LayoutKind.Explicit;
641          break;
642      }
643      CharSet charSet = CharSet.None;
644      switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) {
645        case TypeAttributes.AnsiClass:
646          charSet = CharSet.Ansi;
647          break;
648        case TypeAttributes.AutoClass:
649          charSet = CharSet.Auto;
650          break;
651        case TypeAttributes.UnicodeClass:
652          charSet = CharSet.Unicode;
653          break;
654      }
655      LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto;
656      if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) {
657        DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef });
658        structLayout.PositionalArguments.Add(CreateSimpleConstantValue(layoutKindTypeRef, (int)layoutKind));
659        if (charSet != CharSet.Ansi) {
660          structLayout.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet));
661        }
662        if (typeDefinition.PackingSize > 0) {
663          structLayout.AddNamedFieldArgument("Pack", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.PackingSize));
664        }
665        if (typeDefinition.ClassSize > 0) {
666          structLayout.AddNamedFieldArgument("Size", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.ClassSize));
667        }
668        targetEntity.Attributes.Add(interningProvider.Intern(structLayout));
669      }
670      #endregion
671     
672      if (typeDefinition.HasCustomAttributes) {
673        AddCustomAttributes(typeDefinition.CustomAttributes, targetEntity.Attributes);
674      }
675      if (typeDefinition.HasSecurityDeclarations) {
676        AddSecurityAttributes(typeDefinition.SecurityDeclarations, targetEntity.Attributes);
677      }
678    }
679    #endregion
680   
681    #region Field Attributes
682    static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference();
683    static readonly IUnresolvedAttribute nonSerializedAttribute = new DefaultUnresolvedAttribute(typeof(NonSerializedAttribute).ToTypeReference());
684   
685    void AddAttributes(FieldDefinition fieldDefinition, IUnresolvedEntity targetEntity)
686    {
687      // FieldOffsetAttribute
688      if (fieldDefinition.HasLayoutInfo) {
689        DefaultUnresolvedAttribute fieldOffset = new DefaultUnresolvedAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 });
690        fieldOffset.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset));
691        targetEntity.Attributes.Add(interningProvider.Intern(fieldOffset));
692      }
693     
694      // NonSerializedAttribute
695      if (fieldDefinition.IsNotSerialized) {
696        targetEntity.Attributes.Add(nonSerializedAttribute);
697      }
698     
699      if (fieldDefinition.HasMarshalInfo) {
700        targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo));
701      }
702     
703      if (fieldDefinition.HasCustomAttributes) {
704        AddCustomAttributes(fieldDefinition.CustomAttributes, targetEntity.Attributes);
705      }
706    }
707    #endregion
708   
709    #region Event Attributes
710    void AddAttributes(EventDefinition eventDefinition, IUnresolvedEntity targetEntity)
711    {
712      if (eventDefinition.HasCustomAttributes) {
713        AddCustomAttributes(eventDefinition.CustomAttributes, targetEntity.Attributes);
714      }
715    }
716    #endregion
717   
718    #region Property Attributes
719    void AddAttributes(PropertyDefinition propertyDefinition, IUnresolvedEntity targetEntity)
720    {
721      if (propertyDefinition.HasCustomAttributes) {
722        AddCustomAttributes(propertyDefinition.CustomAttributes, targetEntity.Attributes);
723      }
724    }
725    #endregion
726   
727    #region MarshalAsAttribute (ConvertMarshalInfo)
728    static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference();
729    static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference();
730   
731    IUnresolvedAttribute ConvertMarshalInfo(MarshalInfo marshalInfo)
732    {
733      DefaultUnresolvedAttribute attr = new DefaultUnresolvedAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef });
734      attr.PositionalArguments.Add(CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType));
735     
736      FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
737      if (fami != null) {
738        attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)fami.Size));
739        if (fami.ElementType != NativeType.None)
740          attr.AddNamedFieldArgument("ArraySubType", CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)fami.ElementType));
741      }
742      SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
743      if (sami != null && sami.ElementType != VariantType.None) {
744        attr.AddNamedFieldArgument("SafeArraySubType", CreateSimpleConstantValue(typeof(VarEnum).ToTypeReference(), (int)sami.ElementType));
745      }
746      ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo;
747      if (ami != null) {
748        if (ami.ElementType != NativeType.Max)
749          attr.AddNamedFieldArgument("ArraySubType", CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)ami.ElementType));
750        if (ami.Size >= 0)
751          attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)ami.Size));
752        if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0)
753          attr.AddNamedFieldArgument("SizeParamIndex", CreateSimpleConstantValue(KnownTypeReference.Int16, (short)ami.SizeParameterIndex));
754      }
755      CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
756      if (cmi != null) {
757        if (cmi.ManagedType != null)
758          attr.AddNamedFieldArgument("MarshalType", CreateSimpleConstantValue(KnownTypeReference.String, cmi.ManagedType.FullName));
759        if (!string.IsNullOrEmpty(cmi.Cookie))
760          attr.AddNamedFieldArgument("MarshalCookie", CreateSimpleConstantValue(KnownTypeReference.String, cmi.Cookie));
761      }
762      FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo;
763      if (fssmi != null) {
764        attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)fssmi.Size));
765      }
766     
767      return InterningProvider.Intern(attr);
768    }
769    #endregion
770   
771    #region Custom Attributes (ReadAttribute)
772    void AddCustomAttributes(Mono.Collections.Generic.Collection<CustomAttribute> attributes, IList<IUnresolvedAttribute> targetCollection)
773    {
774      foreach (var cecilAttribute in attributes) {
775        TypeReference type = cecilAttribute.AttributeType;
776        if (type.Namespace == "System.Runtime.CompilerServices") {
777          if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute" || type.Name == "DecimalConstantAttribute")
778            continue;
779        } else if (type.Name == "ParamArrayAttribute" && type.Namespace == "System") {
780          continue;
781        }
782        targetCollection.Add(ReadAttribute(cecilAttribute));
783      }
784    }
785   
786    [CLSCompliant(false)]
787    public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute)
788    {
789      if (attribute == null)
790        throw new ArgumentNullException("attribute");
791      MethodReference ctor = attribute.Constructor;
792      ITypeReference attributeType = ReadTypeReference(attribute.AttributeType);
793      IList<ITypeReference> ctorParameterTypes = EmptyList<ITypeReference>.Instance;
794      if (ctor.HasParameters) {
795        ctorParameterTypes = new ITypeReference[ctor.Parameters.Count];
796        for (int i = 0; i < ctorParameterTypes.Count; i++) {
797          ctorParameterTypes[i] = ReadTypeReference(ctor.Parameters[i].ParameterType);
798        }
799        ctorParameterTypes = interningProvider.InternList(ctorParameterTypes);
800      }
801      return interningProvider.Intern(new UnresolvedAttributeBlob(attributeType, ctorParameterTypes, attribute.GetBlob()));
802    }
803    #endregion
804   
805    #region Security Attributes
806    /// <summary>
807    /// Reads a security declaration.
808    /// </summary>
809    [CLSCompliant(false)]
810    public IList<IUnresolvedAttribute> ReadSecurityDeclaration(SecurityDeclaration secDecl)
811    {
812      if (secDecl == null)
813        throw new ArgumentNullException("secDecl");
814      var result = new List<IUnresolvedAttribute>();
815      AddSecurityAttributes(secDecl, result);
816      return result;
817    }
818   
819    void AddSecurityAttributes(Mono.Collections.Generic.Collection<SecurityDeclaration> securityDeclarations, IList<IUnresolvedAttribute> targetCollection)
820    {
821      foreach (var secDecl in securityDeclarations) {
822        AddSecurityAttributes(secDecl, targetCollection);
823      }
824    }
825   
826    void AddSecurityAttributes(SecurityDeclaration secDecl, IList<IUnresolvedAttribute> targetCollection)
827    {
828      byte[] blob;
829      try {
830        blob = secDecl.GetBlob();
831      } catch (NotSupportedException) {
832        return; // https://github.com/icsharpcode/SharpDevelop/issues/284
833      }
834      var blobSecDecl = new UnresolvedSecurityDeclarationBlob((int)secDecl.Action, blob);
835      targetCollection.AddRange(blobSecDecl.UnresolvedAttributes);
836    }
837    #endregion
838    #endregion
839   
840    #region Read Type Definition
841    DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinition typeDefinition)
842    {
843      string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(typeDefinition.Name);
844      var td = new DefaultUnresolvedTypeDefinition(typeDefinition.Namespace, name);
845      if (typeDefinition.HasGenericParameters)
846        InitTypeParameters(typeDefinition, td.TypeParameters);
847      return td;
848    }
849   
850    static void InitTypeParameters(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters)
851    {
852      // Type parameters are initialized within the constructor so that the class can be put into the type storage
853      // before the rest of the initialization runs - this allows it to be available for early binding as soon as possible.
854      for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) {
855        if (typeDefinition.GenericParameters[i].Position != i)
856          throw new InvalidOperationException("g.Position != i");
857        typeParameters.Add(new DefaultUnresolvedTypeParameter(
858          SymbolKind.TypeDefinition, i, typeDefinition.GenericParameters[i].Name));
859      }
860    }
861   
862    void InitTypeParameterConstraints(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters)
863    {
864      for (int i = 0; i < typeParameters.Count; i++) {
865        var tp = (DefaultUnresolvedTypeParameter)typeParameters[i];
866        AddConstraints(tp, typeDefinition.GenericParameters[i]);
867        tp.ApplyInterningProvider(interningProvider);
868      }
869    }
870   
871    void InitTypeDefinition(TypeDefinition typeDefinition, DefaultUnresolvedTypeDefinition td)
872    {
873      td.Kind = GetTypeKind(typeDefinition);
874      InitTypeModifiers(typeDefinition, td);
875      InitTypeParameterConstraints(typeDefinition, td.TypeParameters);
876     
877      // nested types can be initialized only after generic parameters were created
878      InitNestedTypes(typeDefinition, td, td.NestedTypes);
879      AddAttributes(typeDefinition, td);
880      td.HasExtensionMethods = HasExtensionAttribute(typeDefinition);
881     
882      InitBaseTypes(typeDefinition, td.BaseTypes);
883     
884      td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum);
885      InitMembers(typeDefinition, td, td.Members);
886      td.ApplyInterningProvider(interningProvider);
887      td.Freeze();
888      RegisterCecilObject(td, typeDefinition);
889    }
890   
891    void InitBaseTypes(TypeDefinition typeDefinition, IList<ITypeReference> baseTypes)
892    {
893      // set base classes
894      if (typeDefinition.IsEnum) {
895        foreach (FieldDefinition enumField in typeDefinition.Fields) {
896          if (!enumField.IsStatic) {
897            baseTypes.Add(ReadTypeReference(enumField.FieldType));
898            break;
899          }
900        }
901      } else {
902        if (typeDefinition.BaseType != null) {
903          baseTypes.Add(ReadTypeReference(typeDefinition.BaseType));
904        }
905        if (typeDefinition.HasInterfaces) {
906          foreach (TypeReference iface in typeDefinition.Interfaces) {
907            baseTypes.Add(ReadTypeReference(iface));
908          }
909        }
910      }
911    }
912   
913    void InitNestedTypes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition declaringTypeDefinition, IList<IUnresolvedTypeDefinition> nestedTypes)
914    {
915      if (!typeDefinition.HasNestedTypes)
916        return;
917      foreach (TypeDefinition nestedTypeDef in typeDefinition.NestedTypes) {
918        TypeAttributes visibility = nestedTypeDef.Attributes & TypeAttributes.VisibilityMask;
919        if (this.IncludeInternalMembers
920            || visibility == TypeAttributes.NestedPublic
921            || visibility == TypeAttributes.NestedFamily
922            || visibility == TypeAttributes.NestedFamORAssem)
923        {
924          string name = nestedTypeDef.Name;
925          int pos = name.LastIndexOf('/');
926          if (pos > 0)
927            name = name.Substring(pos + 1);
928          name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
929          var nestedType = new DefaultUnresolvedTypeDefinition(declaringTypeDefinition, name);
930          InitTypeParameters(nestedTypeDef, nestedType.TypeParameters);
931          nestedTypes.Add(nestedType);
932          InitTypeDefinition(nestedTypeDef, nestedType);
933        }
934      }
935    }
936   
937    static TypeKind GetTypeKind(TypeDefinition typeDefinition)
938    {
939      // set classtype
940      if (typeDefinition.IsInterface) {
941        return TypeKind.Interface;
942      } else if (typeDefinition.IsEnum) {
943        return TypeKind.Enum;
944      } else if (typeDefinition.IsValueType) {
945        return TypeKind.Struct;
946      } else if (IsDelegate(typeDefinition)) {
947        return TypeKind.Delegate;
948      } else if (IsModule(typeDefinition)) {
949        return TypeKind.Module;
950      } else {
951        return TypeKind.Class;
952      }
953    }
954   
955    static void InitTypeModifiers(TypeDefinition typeDefinition, AbstractUnresolvedEntity td)
956    {
957      td.IsSealed = typeDefinition.IsSealed;
958      td.IsAbstract = typeDefinition.IsAbstract;
959      switch (typeDefinition.Attributes & TypeAttributes.VisibilityMask) {
960        case TypeAttributes.NotPublic:
961        case TypeAttributes.NestedAssembly:
962          td.Accessibility = Accessibility.Internal;
963          break;
964        case TypeAttributes.Public:
965        case TypeAttributes.NestedPublic:
966          td.Accessibility = Accessibility.Public;
967          break;
968        case TypeAttributes.NestedPrivate:
969          td.Accessibility = Accessibility.Private;
970          break;
971        case TypeAttributes.NestedFamily:
972          td.Accessibility = Accessibility.Protected;
973          break;
974        case TypeAttributes.NestedFamANDAssem:
975          td.Accessibility = Accessibility.ProtectedAndInternal;
976          break;
977        case TypeAttributes.NestedFamORAssem:
978          td.Accessibility = Accessibility.ProtectedOrInternal;
979          break;
980      }
981    }
982   
983    static bool IsDelegate(TypeDefinition type)
984    {
985      if (type.BaseType != null && type.BaseType.Namespace == "System") {
986        if (type.BaseType.Name == "MulticastDelegate")
987          return true;
988        if (type.BaseType.Name == "Delegate" && type.Name != "MulticastDelegate")
989          return true;
990      }
991      return false;
992    }
993   
994    static bool IsModule(TypeDefinition type)
995    {
996      if (!type.HasCustomAttributes)
997        return false;
998      foreach (var att in type.CustomAttributes) {
999        if (att.AttributeType.FullName == "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute"
1000            || att.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute")
1001        {
1002          return true;
1003        }
1004      }
1005      return false;
1006    }
1007   
1008    void InitMembers(TypeDefinition typeDefinition, IUnresolvedTypeDefinition td, IList<IUnresolvedMember> members)
1009    {
1010      if (typeDefinition.HasMethods) {
1011        foreach (MethodDefinition method in typeDefinition.Methods) {
1012          if (IsVisible(method.Attributes) && !IsAccessor(method.SemanticsAttributes)) {
1013            SymbolKind type = SymbolKind.Method;
1014            if (method.IsSpecialName) {
1015              if (method.IsConstructor)
1016                type = SymbolKind.Constructor;
1017              else if (method.Name.StartsWith("op_", StringComparison.Ordinal))
1018                type = SymbolKind.Operator;
1019            }
1020            members.Add(ReadMethod(method, td, type));
1021          }
1022        }
1023      }
1024      if (typeDefinition.HasFields) {
1025        foreach (FieldDefinition field in typeDefinition.Fields) {
1026          if (IsVisible(field.Attributes) && !field.IsSpecialName) {
1027            members.Add(ReadField(field, td));
1028          }
1029        }
1030      }
1031      if (typeDefinition.HasProperties) {
1032        string defaultMemberName = null;
1033        var defaultMemberAttribute = typeDefinition.CustomAttributes.FirstOrDefault(
1034          a => a.AttributeType.FullName == typeof(System.Reflection.DefaultMemberAttribute).FullName);
1035        if (defaultMemberAttribute != null && defaultMemberAttribute.ConstructorArguments.Count == 1) {
1036          defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string;
1037        }
1038        foreach (PropertyDefinition property in typeDefinition.Properties) {
1039          bool getterVisible = property.GetMethod != null && IsVisible(property.GetMethod.Attributes);
1040          bool setterVisible = property.SetMethod != null && IsVisible(property.SetMethod.Attributes);
1041          if (getterVisible || setterVisible) {
1042            SymbolKind type = SymbolKind.Property;
1043            if (property.HasParameters) {
1044              // Try to detect indexer:
1045              if (property.Name == defaultMemberName) {
1046                type = SymbolKind.Indexer; // normal indexer
1047              } else if (property.Name.EndsWith(".Item", StringComparison.Ordinal) && (property.GetMethod ?? property.SetMethod).HasOverrides) {
1048                // explicit interface implementation of indexer
1049                type = SymbolKind.Indexer;
1050                // We can't really tell parameterized properties and indexers apart in this case without
1051                // resolving the interface, so we rely on the "Item" naming convention instead.
1052              }
1053            }
1054            members.Add(ReadProperty(property, td, type));
1055          }
1056        }
1057      }
1058      if (typeDefinition.HasEvents) {
1059        foreach (EventDefinition ev in typeDefinition.Events) {
1060          if (ev.AddMethod != null && IsVisible(ev.AddMethod.Attributes)) {
1061            members.Add(ReadEvent(ev, td));
1062          }
1063        }
1064      }
1065    }
1066   
1067    static bool IsAccessor(MethodSemanticsAttributes semantics)
1068    {
1069      return !(semantics == MethodSemanticsAttributes.None || semantics == MethodSemanticsAttributes.Other);
1070    }
1071    #endregion
1072   
1073    #region Lazy-Loaded Type Definition
1074    /// <summary>
1075    /// Given an assembly that was created by the CecilLoader with lazy-loading enabled,
1076    /// this method will eagerly load all classes, and free any references to the source Cecil objects.
1077    ///
1078    /// The intended usage pattern for this method is:
1079    /// 1. use lazy-loading to improve the latency when new assemblies have to be loaded
1080    /// 2. later, when the CPU is idle, call FinishLazyLoading() to free up the memory consumed by the Cecil objects
1081    /// </summary>
1082    public static void FinishLazyLoading(IUnresolvedAssembly assembly)
1083    {
1084      if (assembly == null)
1085        throw new ArgumentNullException("assembly");
1086      foreach (var type in assembly.TopLevelTypeDefinitions) {
1087        var lctd = type as LazyCecilTypeDefinition;
1088        if (lctd != null)
1089          lctd.InitAndReleaseReferences();
1090      }
1091    }
1092   
1093    sealed class LazyCecilTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition
1094    {
1095      // loader + cecilTypeDef, used for lazy-loading; and set to null after lazy loading is complete
1096      CecilLoader loader;
1097      TypeDefinition cecilTypeDef;
1098     
1099      readonly string namespaceName;
1100      readonly TypeKind kind;
1101      readonly IList<IUnresolvedTypeParameter> typeParameters;
1102     
1103      // lazy-loaded fields
1104      IList<ITypeReference> baseTypes;
1105      IList<IUnresolvedTypeDefinition> nestedTypes;
1106      IList<IUnresolvedMember> members;
1107     
1108      public LazyCecilTypeDefinition(CecilLoader loader, TypeDefinition typeDefinition)
1109      {
1110        this.loader = loader;
1111        this.cecilTypeDef = typeDefinition;
1112        this.SymbolKind = SymbolKind.TypeDefinition;
1113        this.namespaceName = typeDefinition.Namespace;
1114        this.Name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(typeDefinition.Name);
1115        var tps = new List<IUnresolvedTypeParameter>();
1116        InitTypeParameters(typeDefinition, tps);
1117        this.typeParameters = FreezableHelper.FreezeList(tps);
1118       
1119        this.kind = GetTypeKind(typeDefinition);
1120        InitTypeModifiers(typeDefinition, this);
1121        loader.InitTypeParameterConstraints(typeDefinition, typeParameters);
1122       
1123        loader.AddAttributes(typeDefinition, this);
1124        flags[FlagHasExtensionMethods] = HasExtensionAttribute(typeDefinition);
1125       
1126        this.ApplyInterningProvider(loader.interningProvider);
1127        this.Freeze();
1128      }
1129     
1130      public override string Namespace {
1131        get { return namespaceName; }
1132        set { throw new NotSupportedException(); }
1133      }
1134     
1135      public override string ReflectionName {
1136        get { return this.FullTypeName.ReflectionName; }
1137      }
1138     
1139      public FullTypeName FullTypeName {
1140        get {
1141          return new TopLevelTypeName(namespaceName, this.Name, typeParameters.Count);
1142        }
1143      }
1144     
1145      public TypeKind Kind {
1146        get { return kind; }
1147      }
1148     
1149      public IList<IUnresolvedTypeParameter> TypeParameters {
1150        get { return typeParameters; }
1151      }
1152     
1153      public IList<ITypeReference> BaseTypes {
1154        get {
1155          var result = LazyInit.VolatileRead(ref this.baseTypes);
1156          if (result != null) {
1157            return result;
1158          } else {
1159            return LazyInit.GetOrSet(ref this.baseTypes, TryInitBaseTypes());
1160          }
1161        }
1162      }
1163     
1164      IList<ITypeReference> TryInitBaseTypes()
1165      {
1166        var loader = LazyInit.VolatileRead(ref this.loader);
1167        var cecilTypeDef = LazyInit.VolatileRead(ref this.cecilTypeDef);
1168        if (loader == null || cecilTypeDef == null) {
1169          // Cannot initialize because the references to loader/cecilTypeDef
1170          // have already been cleared.
1171          // This can only happen if the class was loaded by another thread concurrently to the TryInitBaseTypes() call,
1172          // so the GetOrSet() call in the property will retrieve the value set by the other thread.
1173          return null;
1174        }
1175        lock (loader.currentModule) {
1176          var result = new List<ITypeReference>();
1177          loader.InitBaseTypes(cecilTypeDef, result);
1178          return FreezableHelper.FreezeList(result);
1179        }
1180      }
1181     
1182      public IList<IUnresolvedTypeDefinition> NestedTypes {
1183        get {
1184          var result = LazyInit.VolatileRead(ref this.nestedTypes);
1185          if (result != null) {
1186            return result;
1187          } else {
1188            return LazyInit.GetOrSet(ref this.nestedTypes, TryInitNestedTypes());
1189          }
1190        }
1191      }
1192     
1193      IList<IUnresolvedTypeDefinition> TryInitNestedTypes()
1194      {
1195        var loader = LazyInit.VolatileRead(ref this.loader);
1196        var cecilTypeDef = LazyInit.VolatileRead(ref this.cecilTypeDef);
1197        if (loader == null || cecilTypeDef == null) {
1198          // Cannot initialize because the references to loader/cecilTypeDef
1199          // have already been cleared.
1200          // This can only happen if the class was loaded by another thread concurrently to the TryInitNestedTypes() call,
1201          // so the GetOrSet() call in the property will retrieve the value set by the other thread.
1202          return null;
1203        }
1204        lock (loader.currentModule) {
1205          var result = new List<IUnresolvedTypeDefinition>();
1206          loader.InitNestedTypes(cecilTypeDef, this, result);
1207          return FreezableHelper.FreezeList(result);
1208        }
1209      }
1210     
1211      public IList<IUnresolvedMember> Members {
1212        get {
1213          var result = LazyInit.VolatileRead(ref this.members);
1214          if (result != null) {
1215            return result;
1216          } else {
1217            return LazyInit.GetOrSet(ref this.members, TryInitMembers());
1218          }
1219        }
1220      }
1221     
1222      IList<IUnresolvedMember> TryInitMembers()
1223      {
1224        var loader = LazyInit.VolatileRead(ref this.loader);
1225        var cecilTypeDef = LazyInit.VolatileRead(ref this.cecilTypeDef);
1226        if (loader == null || cecilTypeDef == null) {
1227          // Cannot initialize because the references to loader/cecilTypeDef
1228          // have already been cleared.
1229          // This can only happen if the class was loaded by another thread concurrently to the TryInitMembers() call,
1230          // so the GetOrSet() call in the property will retrieve the value set by the other thread.
1231          return null;
1232        }
1233        lock (loader.currentModule) {
1234          if (this.members != null)
1235            return this.members;
1236          var result = new List<IUnresolvedMember>();
1237          loader.InitMembers(cecilTypeDef, this, result);
1238          return FreezableHelper.FreezeList(result);
1239        }
1240      }
1241     
1242      public void InitAndReleaseReferences()
1243      {
1244        if (LazyInit.VolatileRead(ref this.baseTypes) == null)
1245          LazyInit.GetOrSet(ref this.baseTypes, TryInitBaseTypes());
1246        if (LazyInit.VolatileRead(ref this.nestedTypes) == null)
1247          LazyInit.GetOrSet(ref this.nestedTypes, TryInitNestedTypes());
1248        if (LazyInit.VolatileRead(ref this.members) == null)
1249          LazyInit.GetOrSet(ref this.members, TryInitMembers());
1250        Thread.MemoryBarrier(); // commit lazily-initialized fields to memory before nulling out the references
1251        // Allow the GC to collect the cecil type definition
1252        loader = null;
1253        cecilTypeDef = null;
1254      }
1255     
1256      public IEnumerable<IUnresolvedMethod> Methods {
1257        get { return Members.OfType<IUnresolvedMethod>(); }
1258      }
1259     
1260      public IEnumerable<IUnresolvedProperty> Properties {
1261        get { return Members.OfType<IUnresolvedProperty>(); }
1262      }
1263     
1264      public IEnumerable<IUnresolvedField> Fields {
1265        get { return Members.OfType<IUnresolvedField>(); }
1266      }
1267     
1268      public IEnumerable<IUnresolvedEvent> Events {
1269        get { return Members.OfType<IUnresolvedEvent>(); }
1270      }
1271     
1272      public bool AddDefaultConstructorIfRequired {
1273        get { return kind == TypeKind.Struct || kind == TypeKind.Enum; }
1274      }
1275     
1276      public bool? HasExtensionMethods {
1277        get { return flags[FlagHasExtensionMethods]; }
1278        // we always return true or false, never null.
1279        // FlagHasNoExtensionMethods is unused in LazyCecilTypeDefinition
1280      }
1281     
1282      public bool IsPartial {
1283        get { return false; }
1284      }
1285     
1286      public override object Clone()
1287      {
1288        throw new NotSupportedException();
1289      }
1290     
1291      public IType Resolve(ITypeResolveContext context)
1292      {
1293        if (context == null)
1294          throw new ArgumentNullException("context");
1295        if (context.CurrentAssembly == null)
1296          throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly.");
1297        return context.CurrentAssembly.GetTypeDefinition(this.FullTypeName)
1298          ?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count);
1299      }
1300     
1301      public ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext)
1302      {
1303        return parentContext;
1304      }
1305    }
1306    #endregion
1307   
1308    #region Read Method
1309    [CLSCompliant(false)]
1310    public IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method)
1311    {
1312      return ReadMethod(method, parentType, methodType, null);
1313    }
1314   
1315    IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner)
1316    {
1317      if (method == null)
1318        return null;
1319      DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, method.Name);
1320      m.SymbolKind = methodType;
1321      m.AccessorOwner = accessorOwner;
1322      m.HasBody = method.HasBody;
1323      if (method.HasGenericParameters) {
1324        for (int i = 0; i < method.GenericParameters.Count; i++) {
1325          if (method.GenericParameters[i].Position != i)
1326            throw new InvalidOperationException("g.Position != i");
1327          m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(
1328            SymbolKind.Method, i, method.GenericParameters[i].Name));
1329        }
1330        for (int i = 0; i < method.GenericParameters.Count; i++) {
1331          var tp = (DefaultUnresolvedTypeParameter)m.TypeParameters[i];
1332          AddConstraints(tp, method.GenericParameters[i]);
1333          tp.ApplyInterningProvider(interningProvider);
1334        }
1335      }
1336     
1337      m.ReturnType = ReadTypeReference(method.ReturnType, typeAttributes: method.MethodReturnType);
1338     
1339      if (HasAnyAttributes(method))
1340        AddAttributes(method, m.Attributes, m.ReturnTypeAttributes);
1341      TranslateModifiers(method, m);
1342     
1343      if (method.HasParameters) {
1344        foreach (ParameterDefinition p in method.Parameters) {
1345          m.Parameters.Add(ReadParameter(p));
1346        }
1347      }
1348     
1349      // mark as extension method if the attribute is set
1350      if (method.IsStatic && HasExtensionAttribute(method)) {
1351        m.IsExtensionMethod = true;
1352      }
1353
1354      int lastDot = method.Name.LastIndexOf('.');
1355      if (lastDot >= 0 && method.HasOverrides) {
1356        // To be consistent with the parser-initialized type system, shorten the method name:
1357        m.Name = method.Name.Substring(lastDot + 1);
1358        m.IsExplicitInterfaceImplementation = true;
1359        foreach (var or in method.Overrides) {
1360          m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(
1361            accessorOwner != null ? SymbolKind.Accessor : SymbolKind.Method,
1362            ReadTypeReference(or.DeclaringType),
1363            or.Name, or.GenericParameters.Count, m.Parameters.Select(p => p.Type).ToList()));
1364        }
1365      }
1366
1367      FinishReadMember(m, method);
1368      return m;
1369    }
1370   
1371    static bool HasExtensionAttribute(ICustomAttributeProvider provider)
1372    {
1373      if (provider.HasCustomAttributes) {
1374        foreach (var attr in provider.CustomAttributes) {
1375          if (attr.AttributeType.Name == "ExtensionAttribute" && attr.AttributeType.Namespace == "System.Runtime.CompilerServices")
1376            return true;
1377        }
1378      }
1379      return false;
1380    }
1381   
1382    bool IsVisible(MethodAttributes att)
1383    {
1384      att &= MethodAttributes.MemberAccessMask;
1385      return IncludeInternalMembers
1386        || att == MethodAttributes.Public
1387        || att == MethodAttributes.Family
1388        || att == MethodAttributes.FamORAssem;
1389    }
1390   
1391    static Accessibility GetAccessibility(MethodAttributes attr)
1392    {
1393      switch (attr & MethodAttributes.MemberAccessMask) {
1394        case MethodAttributes.Public:
1395          return Accessibility.Public;
1396        case MethodAttributes.FamANDAssem:
1397          return Accessibility.ProtectedAndInternal;
1398        case MethodAttributes.Assembly:
1399          return Accessibility.Internal;
1400        case MethodAttributes.Family:
1401          return Accessibility.Protected;
1402        case MethodAttributes.FamORAssem:
1403          return Accessibility.ProtectedOrInternal;
1404        default:
1405          return Accessibility.Private;
1406      }
1407    }
1408   
1409    void TranslateModifiers(MethodDefinition method, AbstractUnresolvedMember m)
1410    {
1411      if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) {
1412        // interface members don't have modifiers, but we want to handle them as "public abstract"
1413        m.Accessibility = Accessibility.Public;
1414        m.IsAbstract = true;
1415      } else {
1416        m.Accessibility = GetAccessibility(method.Attributes);
1417        if (method.IsAbstract) {
1418          m.IsAbstract = true;
1419          m.IsOverride = !method.IsNewSlot;
1420        } else if (method.IsFinal) {
1421          if (!method.IsNewSlot) {
1422            m.IsSealed = true;
1423            m.IsOverride = true;
1424          }
1425        } else if (method.IsVirtual) {
1426          if (method.IsNewSlot)
1427            m.IsVirtual = true;
1428          else
1429            m.IsOverride = true;
1430        }
1431        m.IsStatic = method.IsStatic;
1432      }
1433    }
1434    #endregion
1435   
1436    #region Read Parameter
1437    [CLSCompliant(false)]
1438    public IUnresolvedParameter ReadParameter(ParameterDefinition parameter)
1439    {
1440      if (parameter == null)
1441        throw new ArgumentNullException("parameter");
1442      var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter);
1443      var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(parameter.Name));
1444     
1445      if (parameter.ParameterType is Mono.Cecil.ByReferenceType) {
1446        if (!parameter.IsIn && parameter.IsOut)
1447          p.IsOut = true;
1448        else
1449          p.IsRef = true;
1450      }
1451      AddAttributes(parameter, p);
1452     
1453      if (parameter.IsOptional) {
1454        p.DefaultValue = CreateSimpleConstantValue(type, parameter.Constant);
1455      }
1456     
1457      if (parameter.ParameterType is Mono.Cecil.ArrayType) {
1458        foreach (CustomAttribute att in parameter.CustomAttributes) {
1459          if (att.AttributeType.FullName == typeof(ParamArrayAttribute).FullName) {
1460            p.IsParams = true;
1461            break;
1462          }
1463        }
1464      }
1465     
1466      return interningProvider.Intern(p);
1467    }
1468    #endregion
1469   
1470    #region Read Field
1471    bool IsVisible(FieldAttributes att)
1472    {
1473      att &= FieldAttributes.FieldAccessMask;
1474      return IncludeInternalMembers
1475        || att == FieldAttributes.Public
1476        || att == FieldAttributes.Family
1477        || att == FieldAttributes.FamORAssem;
1478    }
1479
1480    decimal? TryDecodeDecimalConstantAttribute(CustomAttribute attribute)
1481    {
1482      if (attribute.ConstructorArguments.Count != 5)
1483        return null;
1484
1485      BlobReader reader = new BlobReader(attribute.GetBlob(), null);
1486      if (reader.ReadUInt16() != 0x0001) {
1487        Debug.WriteLine("Unknown blob prolog");
1488        return null;
1489      }
1490
1491      // 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)
1492      // Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
1493      var ctorArgs = new object[attribute.ConstructorArguments.Count];
1494      for (int i = 0; i < ctorArgs.Length; i++) {
1495        switch (attribute.ConstructorArguments[i].Type.FullName) {
1496          case "System.Byte":
1497            ctorArgs[i] = reader.ReadByte();
1498            break;
1499          case "System.Int32":
1500            ctorArgs[i] = reader.ReadInt32();
1501            break;
1502          case "System.UInt32":
1503            ctorArgs[i] = unchecked((int)reader.ReadUInt32());
1504            break;
1505          default:
1506            return null;
1507        }
1508      }
1509
1510      if (!ctorArgs.Select(a => a.GetType()).SequenceEqual(new[] { typeof(byte), typeof(byte), typeof(int), typeof(int), typeof(int) }))
1511        return null;
1512
1513      return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]);
1514    }
1515   
1516    [CLSCompliant(false)]
1517    public IUnresolvedField ReadField(FieldDefinition field, IUnresolvedTypeDefinition parentType)
1518    {
1519      if (field == null)
1520        throw new ArgumentNullException("field");
1521      if (parentType == null)
1522        throw new ArgumentNullException("parentType");
1523     
1524      DefaultUnresolvedField f = new DefaultUnresolvedField(parentType, field.Name);
1525      f.Accessibility = GetAccessibility(field.Attributes);
1526      f.IsReadOnly = field.IsInitOnly;
1527      f.IsStatic = field.IsStatic;
1528      f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field);
1529      if (field.HasConstant) {
1530        f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, field.Constant);
1531      }
1532      else {
1533        var decConstant = field.CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.DecimalConstantAttribute");
1534        if (decConstant != null) {
1535          var constValue = TryDecodeDecimalConstantAttribute(decConstant);
1536          if (constValue != null)
1537            f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, constValue);
1538        }
1539      }
1540      AddAttributes(field, f);
1541     
1542      RequiredModifierType modreq = field.FieldType as RequiredModifierType;
1543      if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName) {
1544        f.IsVolatile = true;
1545      }
1546     
1547      FinishReadMember(f, field);
1548      return f;
1549    }
1550   
1551    static Accessibility GetAccessibility(FieldAttributes attr)
1552    {
1553      switch (attr & FieldAttributes.FieldAccessMask) {
1554        case FieldAttributes.Public:
1555          return Accessibility.Public;
1556        case FieldAttributes.FamANDAssem:
1557          return Accessibility.ProtectedAndInternal;
1558        case FieldAttributes.Assembly:
1559          return Accessibility.Internal;
1560        case FieldAttributes.Family:
1561          return Accessibility.Protected;
1562        case FieldAttributes.FamORAssem:
1563          return Accessibility.ProtectedOrInternal;
1564        default:
1565          return Accessibility.Private;
1566      }
1567    }
1568    #endregion
1569   
1570    #region Type Parameter Constraints
1571    void AddConstraints(DefaultUnresolvedTypeParameter tp, GenericParameter g)
1572    {
1573      switch (g.Attributes & GenericParameterAttributes.VarianceMask) {
1574        case GenericParameterAttributes.Contravariant:
1575          tp.Variance = VarianceModifier.Contravariant;
1576          break;
1577        case GenericParameterAttributes.Covariant:
1578          tp.Variance = VarianceModifier.Covariant;
1579          break;
1580      }
1581     
1582      tp.HasReferenceTypeConstraint = g.HasReferenceTypeConstraint;
1583      tp.HasValueTypeConstraint = g.HasNotNullableValueTypeConstraint;
1584      tp.HasDefaultConstructorConstraint = g.HasDefaultConstructorConstraint;
1585     
1586      if (g.HasConstraints) {
1587        foreach (TypeReference constraint in g.Constraints) {
1588          tp.Constraints.Add(ReadTypeReference(constraint));
1589        }
1590      }
1591    }
1592    #endregion
1593   
1594    #region Read Property
1595
1596    Accessibility MergePropertyAccessibility (Accessibility left, Accessibility right)
1597    {
1598      if (left == Accessibility.Public || right == Accessibility.Public)
1599        return Accessibility.Public;
1600
1601      if (left == Accessibility.ProtectedOrInternal || right == Accessibility.ProtectedOrInternal)
1602        return Accessibility.ProtectedOrInternal;
1603
1604      if (left == Accessibility.Protected && right == Accessibility.Internal ||
1605          left == Accessibility.Internal && right == Accessibility.Protected)
1606        return Accessibility.ProtectedOrInternal;
1607
1608      if (left == Accessibility.Protected || right == Accessibility.Protected)
1609        return Accessibility.Protected;
1610
1611      if (left == Accessibility.Internal || right == Accessibility.Internal)
1612        return Accessibility.Internal;
1613
1614      if (left == Accessibility.ProtectedAndInternal || right == Accessibility.ProtectedAndInternal)
1615        return Accessibility.ProtectedAndInternal;
1616
1617      return left;
1618    }
1619
1620    [CLSCompliant(false)]
1621    public IUnresolvedProperty ReadProperty(PropertyDefinition property, IUnresolvedTypeDefinition parentType, SymbolKind propertyType = SymbolKind.Property)
1622    {
1623      if (property == null)
1624        throw new ArgumentNullException("property");
1625      if (parentType == null)
1626        throw new ArgumentNullException("parentType");
1627      DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(parentType, property.Name);
1628      p.SymbolKind = propertyType;
1629      TranslateModifiers(property.GetMethod ?? property.SetMethod, p);
1630      if (property.GetMethod != null && property.SetMethod != null)
1631        p.Accessibility = MergePropertyAccessibility (GetAccessibility (property.GetMethod.Attributes), GetAccessibility (property.SetMethod.Attributes));
1632
1633      p.ReturnType = ReadTypeReference(property.PropertyType, typeAttributes: property);
1634     
1635      p.Getter = ReadMethod(property.GetMethod, parentType, SymbolKind.Accessor, p);
1636      p.Setter = ReadMethod(property.SetMethod, parentType, SymbolKind.Accessor, p);
1637     
1638      if (property.HasParameters) {
1639        foreach (ParameterDefinition par in property.Parameters) {
1640          p.Parameters.Add(ReadParameter(par));
1641        }
1642      }
1643      AddAttributes(property, p);
1644
1645      var accessor = p.Getter ?? p.Setter;
1646      if (accessor != null && accessor.IsExplicitInterfaceImplementation) {
1647        p.Name = property.Name.Substring(property.Name.LastIndexOf('.') + 1);
1648        p.IsExplicitInterfaceImplementation = true;
1649        foreach (var mr in accessor.ExplicitInterfaceImplementations) {
1650          p.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr));
1651        }
1652      }
1653
1654      FinishReadMember(p, property);
1655      return p;
1656    }
1657    #endregion
1658   
1659    #region Read Event
1660    [CLSCompliant(false)]
1661    public IUnresolvedEvent ReadEvent(EventDefinition ev, IUnresolvedTypeDefinition parentType)
1662    {
1663      if (ev == null)
1664        throw new ArgumentNullException("ev");
1665      if (parentType == null)
1666        throw new ArgumentNullException("parentType");
1667     
1668      DefaultUnresolvedEvent e = new DefaultUnresolvedEvent(parentType, ev.Name);
1669      TranslateModifiers(ev.AddMethod, e);
1670      e.ReturnType = ReadTypeReference(ev.EventType, typeAttributes: ev);
1671     
1672      e.AddAccessor    = ReadMethod(ev.AddMethod,    parentType, SymbolKind.Accessor, e);
1673      e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, SymbolKind.Accessor, e);
1674      e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, SymbolKind.Accessor, e);
1675     
1676      AddAttributes(ev, e);
1677     
1678      var accessor = e.AddAccessor ?? e.RemoveAccessor ?? e.InvokeAccessor;
1679      if (accessor != null && accessor.IsExplicitInterfaceImplementation) {
1680        e.Name = ev.Name.Substring(ev.Name.LastIndexOf('.') + 1);
1681        e.IsExplicitInterfaceImplementation = true;
1682        foreach (var mr in accessor.ExplicitInterfaceImplementations) {
1683          e.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr));
1684        }
1685      }
1686
1687      FinishReadMember(e, ev);
1688     
1689      return e;
1690    }
1691    #endregion
1692   
1693    #region FinishReadMember / Interning
1694    void FinishReadMember(AbstractUnresolvedMember member, MemberReference cecilDefinition)
1695    {
1696      member.ApplyInterningProvider(interningProvider);
1697      member.Freeze();
1698      RegisterCecilObject(member, cecilDefinition);
1699    }
1700    #endregion
1701   
1702    #region Type system translation table
1703    readonly Dictionary<object, object> typeSystemTranslationTable;
1704   
1705    void RegisterCecilObject(IUnresolvedEntity typeSystemObject, MemberReference cecilObject)
1706    {
1707      if (OnEntityLoaded != null)
1708        OnEntityLoaded(typeSystemObject, cecilObject);
1709     
1710      AddToTypeSystemTranslationTable(typeSystemObject, cecilObject);
1711    }
1712   
1713    void AddToTypeSystemTranslationTable(object typeSystemObject, object cecilObject)
1714    {
1715      if (typeSystemTranslationTable != null) {
1716        // When lazy-loading, the dictionary might be shared between multiple cecil-loaders that are used concurrently
1717        lock (typeSystemTranslationTable) {
1718          typeSystemTranslationTable[typeSystemObject] = cecilObject;
1719        }
1720      }
1721    }
1722   
1723    T InternalGetCecilObject<T> (object typeSystemObject) where T : class
1724    {
1725      if (typeSystemObject == null)
1726        throw new ArgumentNullException ("typeSystemObject");
1727      if (!HasCecilReferences)
1728        throw new NotSupportedException ("This instance contains no cecil references.");
1729      object result;
1730      lock (typeSystemTranslationTable) {
1731        if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result))
1732          return null;
1733      }
1734      return result as T;
1735    }
1736   
1737    [CLSCompliant(false)]
1738    public AssemblyDefinition GetCecilObject (IUnresolvedAssembly content)
1739    {
1740      return InternalGetCecilObject<AssemblyDefinition> (content);
1741    }
1742   
1743    [CLSCompliant(false)]
1744    public TypeDefinition GetCecilObject (IUnresolvedTypeDefinition type)
1745    {
1746      if (type == null)
1747        throw new ArgumentNullException ("type");
1748      return InternalGetCecilObject<TypeDefinition> (type);
1749    }
1750   
1751    [CLSCompliant(false)]
1752    public MethodDefinition GetCecilObject (IUnresolvedMethod method)
1753    {
1754      return InternalGetCecilObject<MethodDefinition> (method);
1755    }
1756   
1757    [CLSCompliant(false)]
1758    public FieldDefinition GetCecilObject (IUnresolvedField field)
1759    {
1760      return InternalGetCecilObject<FieldDefinition> (field);
1761    }
1762   
1763    [CLSCompliant(false)]
1764    public EventDefinition GetCecilObject (IUnresolvedEvent evt)
1765    {
1766      return InternalGetCecilObject<EventDefinition> (evt);
1767    }
1768   
1769    [CLSCompliant(false)]
1770    public PropertyDefinition GetCecilObject (IUnresolvedProperty property)
1771    {
1772      return InternalGetCecilObject<PropertyDefinition> (property);
1773    }
1774    #endregion
1775  }
1776}
Note: See TracBrowser for help on using the repository browser.