PageRenderTime 116ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs

https://gitlab.com/sharadag/Roslyn
C# | 258 lines | 186 code | 38 blank | 34 comment | 19 complexity | b753f1d08f9629e25deffbb35cf42347 MD5 | raw file
  1. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Collections.Immutable;
  5. using System.Diagnostics;
  6. namespace Microsoft.CodeAnalysis
  7. {
  8. internal abstract class TypeNameDecoder<ModuleSymbol, TypeSymbol>
  9. where ModuleSymbol : class
  10. where TypeSymbol : class
  11. {
  12. private readonly SymbolFactory<ModuleSymbol, TypeSymbol> _factory;
  13. protected readonly ModuleSymbol moduleSymbol;
  14. internal TypeNameDecoder(SymbolFactory<ModuleSymbol, TypeSymbol> factory, ModuleSymbol moduleSymbol)
  15. {
  16. _factory = factory;
  17. this.moduleSymbol = moduleSymbol;
  18. }
  19. protected abstract bool IsContainingAssembly(AssemblyIdentity identity);
  20. /// <summary>
  21. /// Lookup a type defined in this module.
  22. /// </summary>
  23. protected abstract TypeSymbol LookupTopLevelTypeDefSymbol(ref MetadataTypeName emittedName, out bool isNoPiaLocalType);
  24. /// <summary>
  25. /// Lookup a type defined in referenced assembly.
  26. /// </summary>
  27. protected abstract TypeSymbol LookupTopLevelTypeDefSymbol(int referencedAssemblyIndex, ref MetadataTypeName emittedName);
  28. protected abstract TypeSymbol LookupNestedTypeDefSymbol(TypeSymbol container, ref MetadataTypeName emittedName);
  29. /// <summary>
  30. /// Given the identity of an assembly referenced by this module, finds
  31. /// the index of that assembly in the list of assemblies referenced by
  32. /// the current module.
  33. /// </summary>
  34. protected abstract int GetIndexOfReferencedAssembly(AssemblyIdentity identity);
  35. internal TypeSymbol GetTypeSymbolForSerializedType(string s)
  36. {
  37. if (string.IsNullOrEmpty(s))
  38. {
  39. return GetUnsupportedMetadataTypeSymbol();
  40. }
  41. MetadataHelpers.AssemblyQualifiedTypeName fullName = MetadataHelpers.DecodeTypeName(s);
  42. bool refersToNoPiaLocalType;
  43. return GetTypeSymbol(fullName, out refersToNoPiaLocalType);
  44. }
  45. protected TypeSymbol GetUnsupportedMetadataTypeSymbol(BadImageFormatException exception = null)
  46. {
  47. return _factory.GetUnsupportedMetadataTypeSymbol(this.moduleSymbol, exception);
  48. }
  49. protected TypeSymbol GetSZArrayTypeSymbol(TypeSymbol elementType, ImmutableArray<ModifierInfo<TypeSymbol>> customModifiers)
  50. {
  51. return _factory.GetSZArrayTypeSymbol(this.moduleSymbol, elementType, customModifiers);
  52. }
  53. protected TypeSymbol GetMDArrayTypeSymbol(int rank, TypeSymbol elementType, ImmutableArray<ModifierInfo<TypeSymbol>> customModifiers, ImmutableArray<int> sizes, ImmutableArray<int> lowerBounds)
  54. {
  55. return _factory.GetMDArrayTypeSymbol(this.moduleSymbol, rank, elementType, customModifiers, sizes, lowerBounds);
  56. }
  57. protected TypeSymbol GetByRefReturnTypeSymbol(TypeSymbol referencedType, ushort countOfCustomModifiersPrecedingByRef)
  58. {
  59. return _factory.GetByRefReturnTypeSymbol(this.moduleSymbol, referencedType, countOfCustomModifiersPrecedingByRef);
  60. }
  61. protected TypeSymbol MakePointerTypeSymbol(TypeSymbol type, ImmutableArray<ModifierInfo<TypeSymbol>> customModifiers)
  62. {
  63. return _factory.MakePointerTypeSymbol(this.moduleSymbol, type, customModifiers);
  64. }
  65. protected TypeSymbol GetSpecialType(SpecialType specialType)
  66. {
  67. return _factory.GetSpecialType(this.moduleSymbol, specialType);
  68. }
  69. protected TypeSymbol SystemTypeSymbol
  70. {
  71. get { return _factory.GetSystemTypeSymbol(this.moduleSymbol); }
  72. }
  73. protected TypeSymbol GetEnumUnderlyingType(TypeSymbol type)
  74. {
  75. return _factory.GetEnumUnderlyingType(this.moduleSymbol, type);
  76. }
  77. protected bool IsVolatileModifierType(TypeSymbol type)
  78. {
  79. return _factory.IsVolatileModifierType(this.moduleSymbol, type);
  80. }
  81. protected Microsoft.Cci.PrimitiveTypeCode GetPrimitiveTypeCode(TypeSymbol type)
  82. {
  83. return _factory.GetPrimitiveTypeCode(this.moduleSymbol, type);
  84. }
  85. protected TypeSymbol SubstituteWithUnboundIfGeneric(TypeSymbol type)
  86. {
  87. return _factory.MakeUnboundIfGeneric(this.moduleSymbol, type);
  88. }
  89. protected TypeSymbol SubstituteTypeParameters(TypeSymbol genericType, ImmutableArray<KeyValuePair<TypeSymbol, ImmutableArray<ModifierInfo<TypeSymbol>>>> arguments, ImmutableArray<bool> refersToNoPiaLocalType)
  90. {
  91. return _factory.SubstituteTypeParameters(this.moduleSymbol, genericType, arguments, refersToNoPiaLocalType);
  92. }
  93. internal TypeSymbol GetTypeSymbol(MetadataHelpers.AssemblyQualifiedTypeName fullName, out bool refersToNoPiaLocalType)
  94. {
  95. //
  96. // Section 23.3 (Custom Attributes) of CLI Spec Partition II:
  97. //
  98. // If the parameter kind is System.Type, (also, the middle line in above diagram) its value is
  99. // stored as a SerString (as defined in the previous paragraph), representing its canonical name.
  100. // The canonical name is its full type name, followed optionally by the assembly where it is defined,
  101. // its version, culture and public-key-token. If the assembly name is omitted, the CLI looks first
  102. // in the current assembly, and then in the system library (mscorlib); in these two special cases,
  103. // it is permitted to omit the assembly-name, version, culture and public-key-token.
  104. int referencedAssemblyIndex;
  105. if (fullName.AssemblyName != null)
  106. {
  107. AssemblyIdentity identity;
  108. if (!AssemblyIdentity.TryParseDisplayName(fullName.AssemblyName, out identity))
  109. {
  110. refersToNoPiaLocalType = false;
  111. return GetUnsupportedMetadataTypeSymbol();
  112. }
  113. // the assembly name has to be a full name:
  114. referencedAssemblyIndex = GetIndexOfReferencedAssembly(identity);
  115. if (referencedAssemblyIndex == -1)
  116. {
  117. // In rare cases (e.g. assemblies emitted by Reflection.Emit) the identity
  118. // might be the identity of the containing assembly. The metadata spec doesn't disallow this.
  119. if (!this.IsContainingAssembly(identity))
  120. {
  121. refersToNoPiaLocalType = false;
  122. return GetUnsupportedMetadataTypeSymbol();
  123. }
  124. }
  125. }
  126. else
  127. {
  128. // Use this assembly
  129. referencedAssemblyIndex = -1;
  130. }
  131. // Find the top level type
  132. Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.TopLevelType));
  133. var mdName = MetadataTypeName.FromFullName(fullName.TopLevelType);
  134. TypeSymbol container = LookupTopLevelTypeDefSymbol(ref mdName, referencedAssemblyIndex, out refersToNoPiaLocalType);
  135. // Process any nested types
  136. if (fullName.NestedTypes != null)
  137. {
  138. if (refersToNoPiaLocalType)
  139. {
  140. // Types nested into local types are not supported.
  141. refersToNoPiaLocalType = false;
  142. return GetUnsupportedMetadataTypeSymbol();
  143. }
  144. for (int i = 0; i < fullName.NestedTypes.Length; i++)
  145. {
  146. Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.NestedTypes[i]));
  147. mdName = MetadataTypeName.FromTypeName(fullName.NestedTypes[i]);
  148. // Find nested type in the container
  149. container = LookupNestedTypeDefSymbol(container, ref mdName);
  150. }
  151. }
  152. // Substitute type arguments if any
  153. if (fullName.TypeArguments != null)
  154. {
  155. ImmutableArray<bool> argumentRefersToNoPiaLocalType;
  156. var typeArguments = ResolveTypeArguments(fullName.TypeArguments, out argumentRefersToNoPiaLocalType);
  157. container = SubstituteTypeParameters(container, typeArguments, argumentRefersToNoPiaLocalType);
  158. foreach (bool flag in argumentRefersToNoPiaLocalType)
  159. {
  160. if (flag)
  161. {
  162. refersToNoPiaLocalType = true;
  163. break;
  164. }
  165. }
  166. }
  167. else
  168. {
  169. container = SubstituteWithUnboundIfGeneric(container);
  170. }
  171. for (int i = 0; i < fullName.PointerCount; i++)
  172. {
  173. container = MakePointerTypeSymbol(container, ImmutableArray<ModifierInfo<TypeSymbol>>.Empty);
  174. }
  175. // Process any array type ranks
  176. if (fullName.ArrayRanks != null)
  177. {
  178. foreach (int rank in fullName.ArrayRanks)
  179. {
  180. Debug.Assert(rank > 0);
  181. container = rank == 1 ?
  182. GetSZArrayTypeSymbol(container, default(ImmutableArray<ModifierInfo<TypeSymbol>>)) :
  183. GetMDArrayTypeSymbol(rank, container, default(ImmutableArray<ModifierInfo<TypeSymbol>>), ImmutableArray<int>.Empty, default(ImmutableArray<int>));
  184. }
  185. }
  186. return container;
  187. }
  188. private ImmutableArray<KeyValuePair<TypeSymbol, ImmutableArray<ModifierInfo<TypeSymbol>>>> ResolveTypeArguments(MetadataHelpers.AssemblyQualifiedTypeName[] arguments, out ImmutableArray<bool> refersToNoPiaLocalType)
  189. {
  190. int count = arguments.Length;
  191. var typeArgumentsBuilder = ArrayBuilder<KeyValuePair<TypeSymbol, ImmutableArray<ModifierInfo<TypeSymbol>>>>.GetInstance(count);
  192. var refersToNoPiaBuilder = ArrayBuilder<bool>.GetInstance(count);
  193. foreach (var argument in arguments)
  194. {
  195. bool refersToNoPia;
  196. typeArgumentsBuilder.Add(new KeyValuePair<TypeSymbol, ImmutableArray<ModifierInfo<TypeSymbol>>>(GetTypeSymbol(argument, out refersToNoPia), ImmutableArray<ModifierInfo<TypeSymbol>>.Empty));
  197. refersToNoPiaBuilder.Add(refersToNoPia);
  198. }
  199. refersToNoPiaLocalType = refersToNoPiaBuilder.ToImmutableAndFree();
  200. return typeArgumentsBuilder.ToImmutableAndFree();
  201. }
  202. private TypeSymbol LookupTopLevelTypeDefSymbol(ref MetadataTypeName emittedName, int referencedAssemblyIndex, out bool isNoPiaLocalType)
  203. {
  204. TypeSymbol container;
  205. if (referencedAssemblyIndex >= 0)
  206. {
  207. // Find top level type in referenced assembly
  208. isNoPiaLocalType = false;
  209. container = LookupTopLevelTypeDefSymbol(referencedAssemblyIndex, ref emittedName);
  210. }
  211. else
  212. {
  213. // TODO : lookup in mscorlib
  214. // Find top level type in this assembly or mscorlib:
  215. container = LookupTopLevelTypeDefSymbol(ref emittedName, out isNoPiaLocalType);
  216. }
  217. return container;
  218. }
  219. }
  220. }