/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs

http://github.com/icsharpcode/ILSpy · C# · 2021 lines · 1450 code · 348 blank · 223 comment · 338 complexity · e7bf41e3000348d501bc0a9cc8fc9872 MD5 · raw file

  1. //
  2. // typespec.cs: Type specification
  3. //
  4. // Authors: Marek Safar (marek.safar@gmail.com)
  5. //
  6. // Dual licensed under the terms of the MIT X11 or GNU GPL
  7. //
  8. // Copyright 2010 Novell, Inc
  9. // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  10. //
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Text;
  14. using System.Linq;
  15. #if STATIC
  16. using MetaType = IKVM.Reflection.Type;
  17. using IKVM.Reflection;
  18. #else
  19. using MetaType = System.Type;
  20. using System.Reflection;
  21. #endif
  22. namespace Mono.CSharp
  23. {
  24. //
  25. // Inflated or non-inflated representation of any type.
  26. //
  27. public class TypeSpec : MemberSpec
  28. {
  29. protected MetaType info;
  30. protected MemberCache cache;
  31. protected IList<TypeSpec> ifaces;
  32. TypeSpec base_type;
  33. Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
  34. public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
  35. #if !STATIC
  36. // Reflection Emit hacking
  37. static readonly Type TypeBuilder;
  38. static readonly Type GenericTypeBuilder;
  39. static TypeSpec ()
  40. {
  41. var assembly = typeof (object).Assembly;
  42. TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
  43. GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
  44. if (GenericTypeBuilder == null)
  45. GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
  46. }
  47. #endif
  48. public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers)
  49. : base (kind, declaringType, definition, modifiers)
  50. {
  51. this.declaringType = declaringType;
  52. this.info = info;
  53. if (definition != null && definition.TypeParametersCount > 0)
  54. state |= StateFlags.IsGeneric;
  55. }
  56. #region Properties
  57. public override int Arity {
  58. get {
  59. return MemberDefinition.TypeParametersCount;
  60. }
  61. }
  62. public virtual TypeSpec BaseType {
  63. get {
  64. return base_type;
  65. }
  66. set {
  67. base_type = value;
  68. }
  69. }
  70. public virtual BuiltinTypeSpec.Type BuiltinType {
  71. get {
  72. return BuiltinTypeSpec.Type.None;
  73. }
  74. }
  75. public bool HasDynamicElement {
  76. get {
  77. return (state & StateFlags.HasDynamicElement) != 0;
  78. }
  79. }
  80. //
  81. // Returns a list of all interfaces including
  82. // interfaces from base type or base interfaces
  83. //
  84. public virtual IList<TypeSpec> Interfaces {
  85. get {
  86. if ((state & StateFlags.InterfacesImported) == 0) {
  87. state |= StateFlags.InterfacesImported;
  88. //
  89. // Delay interfaces expansion to save memory and once all
  90. // base types has been imported to avoid problems where
  91. // interface references type before its base was imported
  92. //
  93. var imported = MemberDefinition as ImportedTypeDefinition;
  94. if (imported != null && Kind != MemberKind.MissingType)
  95. imported.DefineInterfaces (this);
  96. }
  97. return ifaces;
  98. }
  99. set {
  100. ifaces = value;
  101. }
  102. }
  103. public bool IsArray {
  104. get {
  105. return Kind == MemberKind.ArrayType;
  106. }
  107. }
  108. public bool IsAttribute {
  109. get {
  110. if (!IsClass)
  111. return false;
  112. var type = this;
  113. do {
  114. if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute)
  115. return true;
  116. if (type.IsGeneric)
  117. return false;
  118. type = type.base_type;
  119. } while (type != null);
  120. return false;
  121. }
  122. }
  123. public bool IsInterface {
  124. get {
  125. return Kind == MemberKind.Interface;
  126. }
  127. }
  128. public bool IsClass {
  129. get {
  130. return Kind == MemberKind.Class;
  131. }
  132. }
  133. public bool IsConstantCompatible {
  134. get {
  135. if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
  136. return true;
  137. switch (BuiltinType) {
  138. case BuiltinTypeSpec.Type.Int:
  139. case BuiltinTypeSpec.Type.UInt:
  140. case BuiltinTypeSpec.Type.Long:
  141. case BuiltinTypeSpec.Type.ULong:
  142. case BuiltinTypeSpec.Type.Float:
  143. case BuiltinTypeSpec.Type.Double:
  144. case BuiltinTypeSpec.Type.Char:
  145. case BuiltinTypeSpec.Type.Short:
  146. case BuiltinTypeSpec.Type.Decimal:
  147. case BuiltinTypeSpec.Type.Bool:
  148. case BuiltinTypeSpec.Type.SByte:
  149. case BuiltinTypeSpec.Type.Byte:
  150. case BuiltinTypeSpec.Type.UShort:
  151. case BuiltinTypeSpec.Type.Dynamic:
  152. return true;
  153. }
  154. return false;
  155. }
  156. }
  157. public bool IsDelegate {
  158. get {
  159. return Kind == MemberKind.Delegate;
  160. }
  161. }
  162. //
  163. // Returns true for instances of Expression<T>
  164. //
  165. public virtual bool IsExpressionTreeType {
  166. get {
  167. return false;
  168. }
  169. set {
  170. state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType;
  171. }
  172. }
  173. public bool IsEnum {
  174. get {
  175. return Kind == MemberKind.Enum;
  176. }
  177. }
  178. //
  179. // Returns true for instances of IList<T>, IEnumerable<T>, ICollection<T>
  180. //
  181. public virtual bool IsArrayGenericInterface {
  182. get {
  183. return false;
  184. }
  185. set {
  186. state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface;
  187. }
  188. }
  189. //
  190. // Returns true for instances of System.Threading.Tasks.Task<T>
  191. //
  192. public virtual bool IsGenericTask {
  193. get {
  194. return false;
  195. }
  196. set {
  197. state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask;
  198. }
  199. }
  200. // TODO: Should probably do
  201. // IsGenericType -- recursive
  202. // HasTypeParameter -- non-recursive
  203. public bool IsGenericOrParentIsGeneric {
  204. get {
  205. var ts = this;
  206. do {
  207. if (ts.IsGeneric)
  208. return true;
  209. ts = ts.declaringType;
  210. } while (ts != null);
  211. return false;
  212. }
  213. }
  214. public bool IsGenericParameter {
  215. get {
  216. return Kind == MemberKind.TypeParameter;
  217. }
  218. }
  219. //
  220. // Returns true for instances of Nullable<T>
  221. //
  222. public virtual bool IsNullableType {
  223. get {
  224. return false;
  225. }
  226. set {
  227. state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType;
  228. }
  229. }
  230. public bool IsNested {
  231. get { return declaringType != null && Kind != MemberKind.TypeParameter; }
  232. }
  233. public bool IsPointer {
  234. get {
  235. return Kind == MemberKind.PointerType;
  236. }
  237. }
  238. public bool IsSealed {
  239. get { return (Modifiers & Modifiers.SEALED) != 0; }
  240. }
  241. public bool IsSpecialRuntimeType {
  242. get {
  243. return (state & StateFlags.SpecialRuntimeType) != 0;
  244. }
  245. set {
  246. state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType;
  247. }
  248. }
  249. public bool IsStruct {
  250. get {
  251. return Kind == MemberKind.Struct;
  252. }
  253. }
  254. public bool IsStructOrEnum {
  255. get {
  256. return (Kind & (MemberKind.Struct | MemberKind.Enum)) != 0;
  257. }
  258. }
  259. public bool IsTypeBuilder {
  260. get {
  261. #if STATIC
  262. return true;
  263. #else
  264. var meta = GetMetaInfo().GetType ();
  265. return meta == TypeBuilder || meta == GenericTypeBuilder;
  266. #endif
  267. }
  268. }
  269. //
  270. // Whether a type is unmanaged. This is used by the unsafe code
  271. //
  272. public bool IsUnmanaged {
  273. get {
  274. if (IsPointer)
  275. return ((ElementTypeSpec) this).Element.IsUnmanaged;
  276. var ds = MemberDefinition as TypeDefinition;
  277. if (ds != null)
  278. return ds.IsUnmanagedType ();
  279. if (Kind == MemberKind.Void)
  280. return true;
  281. if (Kind == MemberKind.TypeParameter)
  282. return false;
  283. if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
  284. return false;
  285. return IsValueType (this);
  286. }
  287. }
  288. //
  289. // A cache of all type members (including nested types)
  290. //
  291. public MemberCache MemberCache {
  292. get {
  293. if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
  294. InitializeMemberCache (false);
  295. return cache;
  296. }
  297. set {
  298. if (cache != null)
  299. throw new InternalErrorException ("Membercache reset");
  300. cache = value;
  301. }
  302. }
  303. public MemberCache MemberCacheTypes {
  304. get {
  305. if (cache == null)
  306. InitializeMemberCache (true);
  307. return cache;
  308. }
  309. }
  310. public new ITypeDefinition MemberDefinition {
  311. get {
  312. return (ITypeDefinition) definition;
  313. }
  314. }
  315. // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
  316. // remove the property, YES IT WOULD !!!
  317. public virtual TypeSpec[] TypeArguments {
  318. get { return TypeSpec.EmptyTypes; }
  319. }
  320. #endregion
  321. public virtual bool AddInterface (TypeSpec iface)
  322. {
  323. if ((state & StateFlags.InterfacesExpanded) != 0)
  324. throw new InternalErrorException ("Modifying expanded interface list");
  325. if (ifaces == null) {
  326. ifaces = new List<TypeSpec> { iface };
  327. return true;
  328. }
  329. if (!ifaces.Contains (iface)) {
  330. ifaces.Add (iface);
  331. return true;
  332. }
  333. return false;
  334. }
  335. //
  336. // Special version used during type definition
  337. //
  338. public bool AddInterfaceDefined (TypeSpec iface)
  339. {
  340. if (!AddInterface (iface))
  341. return false;
  342. //
  343. // We can get into a situation where a type is inflated before
  344. // its interfaces are resoved. Consider this situation
  345. //
  346. // class A<T> : X<A<int>>, IFoo {}
  347. //
  348. // When resolving base class of X`1 we inflate context type A`1
  349. // All this happens before we even hit IFoo resolve. Without
  350. // additional expansion any inside usage of A<T> would miss IFoo
  351. // interface because it comes from early inflated A`1 definition.
  352. //
  353. if (inflated_instances != null) {
  354. //
  355. // Inflate only existing instances not any new instances added
  356. // during AddInterface
  357. //
  358. var inflated_existing = inflated_instances.Values.ToArray ();
  359. foreach (var inflated in inflated_existing) {
  360. inflated.AddInterface (iface);
  361. }
  362. }
  363. return true;
  364. }
  365. //
  366. // Returns all type arguments, usefull for nested types
  367. //
  368. public static TypeSpec[] GetAllTypeArguments (TypeSpec type)
  369. {
  370. IList<TypeSpec> targs = TypeSpec.EmptyTypes;
  371. do {
  372. if (type.Arity > 0) {
  373. if (targs.Count == 0) {
  374. targs = type.TypeArguments;
  375. } else {
  376. var list = targs as List<TypeSpec> ?? new List<TypeSpec> (targs);
  377. list.AddRange (type.TypeArguments);
  378. targs = list;
  379. }
  380. }
  381. type = type.declaringType;
  382. } while (type != null);
  383. return targs as TypeSpec[] ?? ((List<TypeSpec>) targs).ToArray ();
  384. }
  385. public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
  386. {
  387. if (Kind != MemberKind.Class)
  388. throw new InternalErrorException ();
  389. if (!pa.IsDefined)
  390. return Attribute.DefaultUsageAttribute;
  391. AttributeUsageAttribute aua = null;
  392. var type = this;
  393. while (type != null) {
  394. aua = type.MemberDefinition.GetAttributeUsage (pa);
  395. if (aua != null)
  396. break;
  397. type = type.BaseType;
  398. }
  399. return aua;
  400. }
  401. //
  402. // Return metadata information used during emit to describe the type
  403. //
  404. public virtual MetaType GetMetaInfo ()
  405. {
  406. return info;
  407. }
  408. public virtual TypeSpec GetDefinition ()
  409. {
  410. return this;
  411. }
  412. //
  413. // Text representation of type used by documentation writer
  414. //
  415. public override string GetSignatureForDocumentation ()
  416. {
  417. StringBuilder sb = new StringBuilder ();
  418. if (IsNested) {
  419. sb.Append (DeclaringType.GetSignatureForDocumentation ());
  420. } else {
  421. sb.Append (MemberDefinition.Namespace);
  422. }
  423. if (sb.Length != 0)
  424. sb.Append (".");
  425. sb.Append (Name);
  426. if (Arity > 0) {
  427. if (this is InflatedTypeSpec) {
  428. sb.Append ("{");
  429. for (int i = 0; i < Arity; ++i) {
  430. if (i > 0)
  431. sb.Append (",");
  432. sb.Append (TypeArguments[i].GetSignatureForDocumentation ());
  433. }
  434. sb.Append ("}");
  435. } else {
  436. sb.Append ("`");
  437. sb.Append (Arity.ToString ());
  438. }
  439. }
  440. return sb.ToString ();
  441. }
  442. public string GetExplicitNameSignatureForDocumentation ()
  443. {
  444. StringBuilder sb = new StringBuilder ();
  445. if (IsNested) {
  446. sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ());
  447. } else if (MemberDefinition.Namespace != null) {
  448. sb.Append (MemberDefinition.Namespace.Replace ('.', '#'));
  449. }
  450. if (sb.Length != 0)
  451. sb.Append ("#");
  452. sb.Append (Name);
  453. if (Arity > 0) {
  454. sb.Append ("{");
  455. for (int i = 0; i < Arity; ++i) {
  456. if (i > 0)
  457. sb.Append (",");
  458. sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ());
  459. }
  460. sb.Append ("}");
  461. }
  462. return sb.ToString ();
  463. }
  464. public override string GetSignatureForError ()
  465. {
  466. string s;
  467. if (IsNested) {
  468. s = DeclaringType.GetSignatureForError ();
  469. } else if (MemberDefinition is AnonymousTypeClass) {
  470. return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
  471. } else {
  472. s = MemberDefinition.Namespace;
  473. }
  474. if (!string.IsNullOrEmpty (s))
  475. s += ".";
  476. return s + Name + GetTypeNameSignature ();
  477. }
  478. public string GetSignatureForErrorIncludingAssemblyName ()
  479. {
  480. return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName);
  481. }
  482. protected virtual string GetTypeNameSignature ()
  483. {
  484. if (!IsGeneric)
  485. return null;
  486. return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
  487. }
  488. public bool ImplementsInterface (TypeSpec iface, bool variantly)
  489. {
  490. var ifaces = Interfaces;
  491. if (ifaces != null) {
  492. for (int i = 0; i < ifaces.Count; ++i) {
  493. if (TypeSpecComparer.IsEqual (ifaces[i], iface))
  494. return true;
  495. if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface))
  496. return true;
  497. }
  498. }
  499. return false;
  500. }
  501. protected virtual void InitializeMemberCache (bool onlyTypes)
  502. {
  503. try {
  504. MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
  505. } catch (Exception e) {
  506. throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ());
  507. }
  508. if (onlyTypes)
  509. state |= StateFlags.PendingMemberCacheMembers;
  510. else
  511. state &= ~StateFlags.PendingMemberCacheMembers;
  512. }
  513. //
  514. // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
  515. // comparison is used to hide differences between `object' and `dynamic' for generic
  516. // types. Should not be used for comparisons where G<object> != G<dynamic>
  517. //
  518. public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
  519. {
  520. if (dynamicIsObject && baseClass.IsGeneric) {
  521. //
  522. // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
  523. //
  524. // class B : A<object> {}
  525. //
  526. type = type.BaseType;
  527. while (type != null) {
  528. if (TypeSpecComparer.IsEqual (type, baseClass))
  529. return true;
  530. type = type.BaseType;
  531. }
  532. return false;
  533. }
  534. while (type != null) {
  535. type = type.BaseType;
  536. if (type == baseClass)
  537. return true;
  538. }
  539. return false;
  540. }
  541. public static bool IsReferenceType (TypeSpec t)
  542. {
  543. switch (t.Kind) {
  544. case MemberKind.TypeParameter:
  545. return ((TypeParameterSpec) t).IsReferenceType;
  546. case MemberKind.Struct:
  547. case MemberKind.Enum:
  548. case MemberKind.Void:
  549. case MemberKind.PointerType:
  550. return false;
  551. case MemberKind.InternalCompilerType:
  552. //
  553. // Null is considered to be a reference type
  554. //
  555. return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
  556. default:
  557. return true;
  558. }
  559. }
  560. public static bool IsNonNullableValueType (TypeSpec t)
  561. {
  562. switch (t.Kind) {
  563. case MemberKind.TypeParameter:
  564. return ((TypeParameterSpec) t).IsValueType;
  565. case MemberKind.Struct:
  566. return !t.IsNullableType;
  567. case MemberKind.Enum:
  568. return true;
  569. default:
  570. return false;
  571. }
  572. }
  573. public static bool IsValueType (TypeSpec t)
  574. {
  575. switch (t.Kind) {
  576. case MemberKind.TypeParameter:
  577. return ((TypeParameterSpec) t).IsValueType;
  578. case MemberKind.Struct:
  579. case MemberKind.Enum:
  580. return true;
  581. default:
  582. return false;
  583. }
  584. }
  585. public override MemberSpec InflateMember (TypeParameterInflator inflator)
  586. {
  587. var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
  588. //
  589. // When inflating nested type from inside the type instance will be same
  590. // because type parameters are same for all nested types
  591. //
  592. if (DeclaringType == inflator.TypeInstance) {
  593. return MakeGenericType (inflator.Context, targs);
  594. }
  595. return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs);
  596. }
  597. //
  598. // Inflates current type using specific type arguments
  599. //
  600. public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs)
  601. {
  602. if (targs.Length == 0 && !IsNested)
  603. throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
  604. InflatedTypeSpec instance;
  605. if (inflated_instances == null) {
  606. inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
  607. if (IsNested) {
  608. instance = this as InflatedTypeSpec;
  609. if (instance != null) {
  610. //
  611. // Nested types could be inflated on already inflated instances
  612. // Caching this type ensured we are using same instance for
  613. // inside/outside inflation using local type parameters
  614. //
  615. inflated_instances.Add (TypeArguments, instance);
  616. }
  617. }
  618. }
  619. if (!inflated_instances.TryGetValue (targs, out instance)) {
  620. if (GetDefinition () != this && !IsNested)
  621. throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
  622. GetSignatureForError ());
  623. instance = new InflatedTypeSpec (context, this, declaringType, targs);
  624. inflated_instances.Add (targs, instance);
  625. }
  626. return instance;
  627. }
  628. public virtual TypeSpec Mutate (TypeParameterMutator mutator)
  629. {
  630. return this;
  631. }
  632. public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
  633. {
  634. List<MissingTypeSpecReference> missing = null;
  635. if (Kind == MemberKind.MissingType) {
  636. missing = new List<MissingTypeSpecReference> ();
  637. missing.Add (new MissingTypeSpecReference (this, caller));
  638. return missing;
  639. }
  640. foreach (var targ in TypeArguments) {
  641. if (targ.Kind == MemberKind.MissingType) {
  642. if (missing == null)
  643. missing = new List<MissingTypeSpecReference> ();
  644. missing.Add (new MissingTypeSpecReference (targ, caller));
  645. }
  646. }
  647. if (Interfaces != null) {
  648. foreach (var iface in Interfaces) {
  649. if (iface.Kind == MemberKind.MissingType) {
  650. if (missing == null)
  651. missing = new List<MissingTypeSpecReference> ();
  652. missing.Add (new MissingTypeSpecReference (iface, caller));
  653. }
  654. }
  655. }
  656. if (MemberDefinition.TypeParametersCount > 0) {
  657. foreach (var tp in MemberDefinition.TypeParameters) {
  658. var tp_missing = tp.GetMissingDependencies (this);
  659. if (tp_missing != null) {
  660. if (missing == null)
  661. missing = new List<MissingTypeSpecReference> ();
  662. missing.AddRange (tp_missing);
  663. }
  664. }
  665. }
  666. if (missing != null || BaseType == null)
  667. return missing;
  668. return BaseType.ResolveMissingDependencies (this);
  669. }
  670. public void SetMetaInfo (MetaType info)
  671. {
  672. if (this.info != null)
  673. throw new InternalErrorException ("MetaInfo reset");
  674. this.info = info;
  675. }
  676. public void SetExtensionMethodContainer ()
  677. {
  678. modifiers |= Modifiers.METHOD_EXTENSION;
  679. }
  680. public void UpdateInflatedInstancesBaseType ()
  681. {
  682. //
  683. // When nested class has a partial part the situation where parent type
  684. // is inflated before its base type is defined can occur. In such case
  685. // all inflated (should be only 1) instansted need to be updated
  686. //
  687. // partial class A<T> {
  688. // partial class B : A<int> { }
  689. // }
  690. //
  691. // partial class A<T> : X {}
  692. //
  693. if (inflated_instances == null)
  694. return;
  695. foreach (var inflated in inflated_instances) {
  696. //
  697. // Don't need to inflate possible generic type because for now the method
  698. // is always used from within the nested type
  699. //
  700. inflated.Value.BaseType = base_type;
  701. }
  702. }
  703. }
  704. //
  705. // Special version used for types which must exist in corlib or
  706. // the compiler cannot work
  707. //
  708. public sealed class BuiltinTypeSpec : TypeSpec
  709. {
  710. public enum Type
  711. {
  712. None = 0,
  713. // Ordered carefully for fast compares
  714. FirstPrimitive = 1,
  715. Bool = 1,
  716. Byte = 2,
  717. SByte = 3,
  718. Char = 4,
  719. Short = 5,
  720. UShort = 6,
  721. Int = 7,
  722. UInt = 8,
  723. Long = 9,
  724. ULong = 10,
  725. Float = 11,
  726. Double = 12,
  727. LastPrimitive = 12,
  728. Decimal = 13,
  729. IntPtr = 14,
  730. UIntPtr = 15,
  731. Object = 16,
  732. Dynamic = 17,
  733. String = 18,
  734. Type = 19,
  735. ValueType = 20,
  736. Enum = 21,
  737. Delegate = 22,
  738. MulticastDelegate = 23,
  739. Array = 24,
  740. IEnumerator,
  741. IEnumerable,
  742. IDisposable,
  743. Exception,
  744. Attribute,
  745. Other,
  746. }
  747. readonly Type type;
  748. readonly string ns;
  749. readonly string name;
  750. public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind)
  751. : base (kind, null, null, null, Modifiers.PUBLIC)
  752. {
  753. this.type = builtinKind;
  754. this.ns = ns;
  755. this.name = name;
  756. }
  757. public BuiltinTypeSpec (string name, Type builtinKind)
  758. : this (MemberKind.InternalCompilerType, "", name, builtinKind)
  759. {
  760. // Make all internal types CLS-compliant, non-obsolete, compact
  761. state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
  762. }
  763. #region Properties
  764. public override int Arity {
  765. get {
  766. return 0;
  767. }
  768. }
  769. public override BuiltinTypeSpec.Type BuiltinType {
  770. get {
  771. return type;
  772. }
  773. }
  774. public string FullName {
  775. get {
  776. return ns + '.' + name;
  777. }
  778. }
  779. public override string Name {
  780. get {
  781. return name;
  782. }
  783. }
  784. public string Namespace {
  785. get {
  786. return ns;
  787. }
  788. }
  789. #endregion
  790. public static bool IsPrimitiveType (TypeSpec type)
  791. {
  792. return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive;
  793. }
  794. public static bool IsPrimitiveTypeOrDecimal (TypeSpec type)
  795. {
  796. return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal;
  797. }
  798. public override string GetSignatureForError ()
  799. {
  800. switch (Name) {
  801. case "Int32": return "int";
  802. case "Int64": return "long";
  803. case "String": return "string";
  804. case "Boolean": return "bool";
  805. case "Void": return "void";
  806. case "Object": return "object";
  807. case "UInt32": return "uint";
  808. case "Int16": return "short";
  809. case "UInt16": return "ushort";
  810. case "UInt64": return "ulong";
  811. case "Single": return "float";
  812. case "Double": return "double";
  813. case "Decimal": return "decimal";
  814. case "Char": return "char";
  815. case "Byte": return "byte";
  816. case "SByte": return "sbyte";
  817. }
  818. if (ns.Length == 0)
  819. return name;
  820. return FullName;
  821. }
  822. //
  823. // Returns the size of type if known, otherwise, 0
  824. //
  825. public static int GetSize (TypeSpec type)
  826. {
  827. switch (type.BuiltinType) {
  828. case Type.Int:
  829. case Type.UInt:
  830. case Type.Float:
  831. return 4;
  832. case Type.Long:
  833. case Type.ULong:
  834. case Type.Double:
  835. return 8;
  836. case Type.Byte:
  837. case Type.SByte:
  838. case Type.Bool:
  839. return 1;
  840. case Type.Short:
  841. case Type.Char:
  842. case Type.UShort:
  843. return 2;
  844. case Type.Decimal:
  845. return 16;
  846. default:
  847. return 0;
  848. }
  849. }
  850. public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
  851. {
  852. this.definition = td;
  853. this.info = type;
  854. this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
  855. }
  856. public void SetDefinition (TypeSpec ts)
  857. {
  858. this.definition = ts.MemberDefinition;
  859. this.info = ts.GetMetaInfo ();
  860. this.BaseType = ts.BaseType;
  861. this.Interfaces = ts.Interfaces;
  862. this.modifiers = ts.Modifiers;
  863. }
  864. }
  865. //
  866. // Various type comparers used by compiler
  867. //
  868. static class TypeSpecComparer
  869. {
  870. //
  871. // Does strict reference comparion only
  872. //
  873. public static readonly DefaultImpl Default = new DefaultImpl ();
  874. public class DefaultImpl : IEqualityComparer<TypeSpec[]>
  875. {
  876. #region IEqualityComparer<TypeSpec[]> Members
  877. bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
  878. {
  879. if (x == y)
  880. return true;
  881. if (x.Length != y.Length)
  882. return false;
  883. for (int i = 0; i < x.Length; ++i)
  884. if (x[i] != y[i])
  885. return false;
  886. return true;
  887. }
  888. int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
  889. {
  890. int hash = 0;
  891. for (int i = 0; i < obj.Length; ++i)
  892. hash = (hash << 5) - hash + obj[i].GetHashCode ();
  893. return hash;
  894. }
  895. #endregion
  896. }
  897. //
  898. // When comparing type signature of overrides or overloads
  899. // this version tolerates different MVARs at same position
  900. //
  901. public static class Override
  902. {
  903. public static bool IsEqual (TypeSpec a, TypeSpec b)
  904. {
  905. if (a == b)
  906. return true;
  907. //
  908. // Consider the following example:
  909. //
  910. // public abstract class A
  911. // {
  912. // public abstract T Foo<T>();
  913. // }
  914. //
  915. // public class B : A
  916. // {
  917. // public override U Foo<T>() { return default (U); }
  918. // }
  919. //
  920. // Here, `T' and `U' are method type parameters from different methods
  921. // (A.Foo and B.Foo), so both `==' and Equals() will fail.
  922. //
  923. // However, since we're determining whether B.Foo() overrides A.Foo(),
  924. // we need to do a signature based comparision and consider them equal.
  925. //
  926. var tp_a = a as TypeParameterSpec;
  927. if (tp_a != null) {
  928. var tp_b = b as TypeParameterSpec;
  929. return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
  930. }
  931. var ac_a = a as ArrayContainer;
  932. if (ac_a != null) {
  933. var ac_b = b as ArrayContainer;
  934. return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
  935. }
  936. if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
  937. return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
  938. if (a.MemberDefinition != b.MemberDefinition)
  939. return false;
  940. do {
  941. for (int i = 0; i < a.TypeArguments.Length; ++i) {
  942. if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
  943. return false;
  944. }
  945. a = a.DeclaringType;
  946. b = b.DeclaringType;
  947. } while (a != null);
  948. return true;
  949. }
  950. public static bool IsEqual (TypeSpec[] a, TypeSpec[] b)
  951. {
  952. if (a == b)
  953. return true;
  954. if (a.Length != b.Length)
  955. return false;
  956. for (int i = 0; i < a.Length; ++i) {
  957. if (!IsEqual (a[i], b[i]))
  958. return false;
  959. }
  960. return true;
  961. }
  962. //
  963. // Compares unordered arrays
  964. //
  965. public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
  966. {
  967. if (a == b)
  968. return true;
  969. if (a == null || b == null || a.Length != b.Length)
  970. return false;
  971. for (int ai = 0; ai < a.Length; ++ai) {
  972. bool found = false;
  973. for (int bi = 0; bi < b.Length; ++bi) {
  974. if (IsEqual (a[ai], b[bi])) {
  975. found = true;
  976. break;
  977. }
  978. }
  979. if (!found)
  980. return false;
  981. }
  982. return true;
  983. }
  984. public static bool IsEqual (AParametersCollection a, AParametersCollection b)
  985. {
  986. if (a == b)
  987. return true;
  988. if (a.Count != b.Count)
  989. return false;
  990. for (int i = 0; i < a.Count; ++i) {
  991. if (!IsEqual (a.Types[i], b.Types[i]))
  992. return false;
  993. if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
  994. return false;
  995. }
  996. return true;
  997. }
  998. }
  999. //
  1000. // Type variance equality comparison
  1001. //
  1002. public static class Variant
  1003. {
  1004. public static bool IsEqual (TypeSpec type1, TypeSpec type2)
  1005. {
  1006. if (!type1.IsGeneric || !type2.IsGeneric)
  1007. return false;
  1008. var target_type_def = type2.MemberDefinition;
  1009. if (type1.MemberDefinition != target_type_def)
  1010. return false;
  1011. var t1_targs = type1.TypeArguments;
  1012. var t2_targs = type2.TypeArguments;
  1013. var targs_definition = target_type_def.TypeParameters;
  1014. if (!type1.IsInterface && !type1.IsDelegate) {
  1015. return false;
  1016. }
  1017. for (int i = 0; i < targs_definition.Length; ++i) {
  1018. if (TypeSpecComparer.IsEqual (t1_targs[i], t2_targs[i]))
  1019. continue;
  1020. Variance v = targs_definition[i].Variance;
  1021. if (v == Variance.None) {
  1022. return false;
  1023. }
  1024. if (v == Variance.Covariant) {
  1025. if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i]))
  1026. return false;
  1027. } else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) {
  1028. return false;
  1029. }
  1030. }
  1031. return true;
  1032. }
  1033. }
  1034. //
  1035. // Checks whether two generic instances may become equal for some
  1036. // particular instantiation (26.3.1).
  1037. //
  1038. public static class Unify
  1039. {
  1040. //
  1041. // Either @a or @b must be generic type
  1042. //
  1043. public static bool IsEqual (TypeSpec a, TypeSpec b)
  1044. {
  1045. if (a.MemberDefinition != b.MemberDefinition) {
  1046. var base_ifaces = a.Interfaces;
  1047. if (base_ifaces != null) {
  1048. foreach (var base_iface in base_ifaces) {
  1049. if (base_iface.Arity > 0 && IsEqual (base_iface, b))
  1050. return true;
  1051. }
  1052. }
  1053. return false;
  1054. }
  1055. var ta = a.TypeArguments;
  1056. var tb = b.TypeArguments;
  1057. for (int i = 0; i < ta.Length; i++) {
  1058. if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
  1059. return false;
  1060. }
  1061. if (a.IsNested && b.IsNested)
  1062. return IsEqual (a.DeclaringType, b.DeclaringType);
  1063. return true;
  1064. }
  1065. static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
  1066. {
  1067. TypeSpec[] targs = type.TypeArguments;
  1068. for (int i = 0; i < targs.Length; i++) {
  1069. if (tparam == targs[i])
  1070. return true;
  1071. if (ContainsTypeParameter (tparam, targs[i]))
  1072. return true;
  1073. }
  1074. return false;
  1075. }
  1076. /// <summary>
  1077. /// Check whether `a' and `b' may become equal generic types.
  1078. /// The algorithm to do that is a little bit complicated.
  1079. /// </summary>
  1080. static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
  1081. {
  1082. if (a.IsGenericParameter) {
  1083. //
  1084. // If a is an array of a's type, they may never
  1085. // become equal.
  1086. //
  1087. if (b.IsArray)
  1088. return false;
  1089. //
  1090. // If b is a generic parameter or an actual type,
  1091. // they may become equal:
  1092. //
  1093. // class X<T,U> : I<T>, I<U>
  1094. // class X<T> : I<T>, I<float>
  1095. //
  1096. if (b.IsGenericParameter)
  1097. return a != b && a.DeclaringType == b.DeclaringType;
  1098. //
  1099. // We're now comparing a type parameter with a
  1100. // generic instance. They may become equal unless
  1101. // the type parameter appears anywhere in the
  1102. // generic instance:
  1103. //
  1104. // class X<T,U> : I<T>, I<X<U>>
  1105. // -> error because you could instanciate it as
  1106. // X<X<int>,int>
  1107. //
  1108. // class X<T> : I<T>, I<X<T>> -> ok
  1109. //
  1110. return !ContainsTypeParameter (a, b);
  1111. }
  1112. if (b.IsGenericParameter)
  1113. return MayBecomeEqualGenericTypes (b, a);
  1114. //
  1115. // At this point, neither a nor b are a type parameter.
  1116. //
  1117. // If one of them is a generic instance, compare them (if the
  1118. // other one is not a generic instance, they can never
  1119. // become equal).
  1120. //
  1121. if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
  1122. return IsEqual (a, b);
  1123. //
  1124. // If both of them are arrays.
  1125. //
  1126. var a_ac = a as ArrayContainer;
  1127. if (a_ac != null) {
  1128. var b_ac = b as ArrayContainer;
  1129. if (b_ac == null || a_ac.Rank != b_ac.Rank)
  1130. return false;
  1131. return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
  1132. }
  1133. //
  1134. // Ok, two ordinary types.
  1135. //
  1136. return false;
  1137. }
  1138. }
  1139. public static bool Equals (TypeSpec[] x, TypeSpec[] y)
  1140. {
  1141. if (x == y)
  1142. return true;
  1143. if (x.Length != y.Length)
  1144. return false;
  1145. for (int i = 0; i < x.Length; ++i)
  1146. if (!IsEqual (x[i], y[i]))
  1147. return false;
  1148. return true;
  1149. }
  1150. //
  1151. // Identity type conversion
  1152. //
  1153. // Default reference comparison, it has to be used when comparing
  1154. // two possible dynamic/internal types
  1155. //
  1156. public static bool IsEqual (TypeSpec a, TypeSpec b)
  1157. {
  1158. if (a == b) {
  1159. // This also rejects dynamic == dynamic
  1160. return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
  1161. }
  1162. if (a == null || b == null)
  1163. return false;
  1164. if (a.IsArray) {
  1165. var a_a = (ArrayContainer) a;
  1166. var b_a = b as ArrayContainer;
  1167. if (b_a == null)
  1168. return false;
  1169. return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element);
  1170. }
  1171. if (!a.IsGeneric || !b.IsGeneric) {
  1172. //
  1173. // object and dynamic are considered equivalent there is an identity conversion
  1174. // between object and dynamic, and between constructed types that are the same
  1175. // when replacing all occurences of dynamic with object.
  1176. //
  1177. if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
  1178. return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
  1179. return false;
  1180. }
  1181. if (a.MemberDefinition != b.MemberDefinition)
  1182. return false;
  1183. do {
  1184. if (!Equals (a.TypeArguments, b.TypeArguments))
  1185. return false;
  1186. a = a.DeclaringType;
  1187. b = b.DeclaringType;
  1188. } while (a != null);
  1189. return true;
  1190. }
  1191. }
  1192. public interface ITypeDefinition : IMemberDefinition
  1193. {
  1194. IAssemblyDefinition DeclaringAssembly { get; }
  1195. string Namespace { get; }
  1196. bool IsPartial { get; }
  1197. bool IsComImport { get; }
  1198. bool IsTypeForwarder { get; }
  1199. bool IsCyclicTypeForwarder { get; }
  1200. int TypeParametersCount { get; }
  1201. TypeParameterSpec[] TypeParameters { get; }
  1202. TypeSpec GetAttributeCoClass ();
  1203. string GetAttributeDefaultMember ();
  1204. AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
  1205. bool IsInternalAsPublic (IAssemblyDefinition assembly);
  1206. void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
  1207. }
  1208. class InternalType : TypeSpec, ITypeDefinition
  1209. {
  1210. public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
  1211. public static readonly InternalType Arglist = new InternalType ("__arglist");
  1212. public static readonly InternalType MethodGroup = new InternalType ("method group");
  1213. public static readonly InternalType NullLiteral = new InternalType ("null");
  1214. public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
  1215. public static readonly InternalType Namespace = new InternalType ("<namespace>");
  1216. public static readonly InternalType ErrorType = new InternalType ("<error>");
  1217. readonly string name;
  1218. InternalType (string name)
  1219. : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
  1220. {
  1221. this.name = name;
  1222. this.definition = this;
  1223. cache = MemberCache.Empty;
  1224. // Make all internal types CLS-compliant, non-obsolete
  1225. state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
  1226. }
  1227. #region Properties
  1228. public override int Arity {
  1229. get {
  1230. return 0;
  1231. }
  1232. }
  1233. IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
  1234. get {
  1235. throw new NotImplementedException ();
  1236. }
  1237. }
  1238. bool ITypeDefinition.IsComImport {
  1239. get {
  1240. return false;
  1241. }
  1242. }
  1243. bool IMemberDefinition.IsImported {
  1244. get {
  1245. return false;
  1246. }
  1247. }
  1248. bool ITypeDefinition.IsPartial {
  1249. get {
  1250. return false;
  1251. }
  1252. }
  1253. bool ITypeDefinition.IsTypeForwarder {
  1254. get {
  1255. return false;
  1256. }
  1257. }
  1258. bool ITypeDefinition.IsCyclicTypeForwarder {
  1259. get {
  1260. return false;
  1261. }
  1262. }
  1263. public override string Name {
  1264. get {
  1265. return name;
  1266. }
  1267. }
  1268. string ITypeDefinition.Namespace {
  1269. get {
  1270. return null;
  1271. }
  1272. }
  1273. int ITypeDefinition.TypeParametersCount {
  1274. get {
  1275. return 0;
  1276. }
  1277. }
  1278. TypeParameterSpec[] ITypeDefinition.TypeParameters {
  1279. get {
  1280. return null;
  1281. }
  1282. }
  1283. #endregion
  1284. public override string GetSignatureForError ()
  1285. {
  1286. return name;
  1287. }
  1288. #region ITypeDefinition Members
  1289. TypeSpec ITypeDefinition.GetAttributeCoClass ()
  1290. {
  1291. return null;
  1292. }
  1293. string ITypeDefinition.GetAttributeDefaultMember ()
  1294. {
  1295. return null;
  1296. }
  1297. AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
  1298. {
  1299. return null;
  1300. }
  1301. bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
  1302. {
  1303. throw new NotImplementedException ();
  1304. }
  1305. void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
  1306. {
  1307. throw new NotImplementedException ();
  1308. }
  1309. string[] IMemberDefinition.ConditionalConditions ()
  1310. {
  1311. return null;
  1312. }
  1313. ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
  1314. {
  1315. return null;
  1316. }
  1317. bool? IMemberDefinition.CLSAttributeValue {
  1318. get {
  1319. return null;
  1320. }
  1321. }
  1322. void IMemberDefinition.SetIsAssigned ()
  1323. {
  1324. }
  1325. void IMemberDefinition.SetIsUsed ()
  1326. {
  1327. }
  1328. #endregion
  1329. }
  1330. //
  1331. // Common base class for composite types
  1332. //
  1333. public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
  1334. {
  1335. protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
  1336. : base (kind, element.DeclaringType, null, info, element.Modifiers)
  1337. {
  1338. this.Element = element;
  1339. state &= ~SharedStateFlags;
  1340. state |= (element.state & SharedStateFlags);
  1341. if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
  1342. state |= StateFlags.HasDynamicElement;
  1343. // Has to use its own type definition instead of just element definition to
  1344. // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
  1345. this.definition = this;
  1346. cache = MemberCache.Empty;
  1347. }
  1348. #region Properties
  1349. public TypeSpec Element { get; private set; }
  1350. bool ITypeDefinition.IsComImport {
  1351. get {
  1352. return false;
  1353. }
  1354. }
  1355. bool ITypeDefinition.IsPartial {
  1356. get {
  1357. return false;
  1358. }
  1359. }
  1360. bool ITypeDefinition.IsTypeForwarder {
  1361. get {
  1362. return false;
  1363. }
  1364. }
  1365. bool ITypeDefinition.IsCyclicTypeForwarder {
  1366. get {
  1367. return false;
  1368. }
  1369. }
  1370. public override string Name {
  1371. get {
  1372. throw new NotSupportedException ();
  1373. }
  1374. }
  1375. #endregion
  1376. public override ObsoleteAttribute GetAttributeObsolete ()
  1377. {
  1378. return Element.GetAttributeObsolete ();
  1379. }
  1380. protected virtual string GetPostfixSignature ()
  1381. {
  1382. return null;
  1383. }
  1384. public override string GetSignatureForDocumentation ()
  1385. {
  1386. return Element.GetSignatureForDocumentation () + GetPostfixSignature ();
  1387. }
  1388. public override string GetSignatureForError ()
  1389. {
  1390. return Element.GetSignatureForError () + GetPostfixSignature ();
  1391. }
  1392. public override TypeSpec Mutate (TypeParameterMutator mutator)
  1393. {
  1394. var me = Element.Mutate (mutator);
  1395. if (me == Element)
  1396. return this;
  1397. var mutated = (ElementTypeSpec) MemberwiseClone ();
  1398. mutated.Element = me;
  1399. mutated.info = null;
  1400. return mutated;
  1401. }
  1402. #region ITypeDefinition Members
  1403. IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
  1404. get {
  1405. return Element.MemberDefinition.DeclaringAssembly;
  1406. }
  1407. }
  1408. bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
  1409. {
  1410. return Element.MemberDefinition.IsInternalAsPublic (assembly);
  1411. }
  1412. public string Namespace {
  1413. get { throw new NotImplementedException (); }
  1414. }
  1415. public int TypeParametersCount {
  1416. get {
  1417. return 0;
  1418. }
  1419. }
  1420. public TypeParameterSpec[] TypeParameters {
  1421. get {
  1422. throw new NotSupportedException ();
  1423. }
  1424. }
  1425. public TypeSpec GetAttributeCoClass ()
  1426. {
  1427. return Element.MemberDefinition.GetAttributeCoClass ();
  1428. }
  1429. public string GetAttributeDefaultMember ()
  1430. {
  1431. return Element.MemberDefinition.GetAttributeDefaultMember ();
  1432. }
  1433. public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
  1434. {
  1435. Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
  1436. }
  1437. public bool IsImported {
  1438. get {
  1439. return Element.MemberDefinition.IsImported;
  1440. }
  1441. }
  1442. public string[] ConditionalConditions ()
  1443. {
  1444. return Element.MemberDefinition.ConditionalConditions ();
  1445. }
  1446. bool? IMemberDefinition.CLSAttributeValue {
  1447. get {
  1448. return Element.MemberDefinition.CLSAttributeValue;
  1449. }
  1450. }
  1451. public void SetIsAssigned ()
  1452. {
  1453. Element.MemberDefinition.SetIsAssigned ();
  1454. }
  1455. public void SetIsUsed ()
  1456. {
  1457. Element.MemberDefinition.SetIsUsed ();
  1458. }
  1459. #endregion
  1460. }
  1461. public class ArrayContainer : ElementTypeSpec
  1462. {
  1463. public struct TypeRankPair : IEquatable<TypeRankPair>
  1464. {
  1465. TypeSpec ts;
  1466. int rank;
  1467. public TypeRankPair (TypeSpec ts, int rank)
  1468. {
  1469. this.ts = ts;
  1470. this.rank = rank;
  1471. }
  1472. public override int GetHashCode ()
  1473. {
  1474. return ts.GetHashCode () ^ rank.GetHashCode ();
  1475. }
  1476. #region IEquatable<Tuple<T1,T2>> Members
  1477. public bool Equals (TypeRankPair other)
  1478. {
  1479. return other.ts == ts && other.rank == rank;
  1480. }
  1481. #endregion
  1482. }
  1483. readonly int rank;
  1484. readonly ModuleContainer module;
  1485. private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
  1486. : base (MemberKind.ArrayType, element, null)
  1487. {
  1488. this.module = module;
  1489. this.rank = rank;
  1490. }
  1491. public int Rank {
  1492. get {
  1493. return rank;
  1494. }
  1495. }
  1496. public MethodInfo GetConstructor ()
  1497. {
  1498. var mb = module.Builder;
  1499. var arg_types = new MetaType[rank];
  1500. for (int i = 0; i < rank; i++)
  1501. arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
  1502. var ctor = mb.GetArrayMethod (
  1503. GetMetaInfo (), Constructor.ConstructorName,
  1504. CallingConventions.HasThis,
  1505. null, arg_types);
  1506. return ctor;
  1507. }
  1508. public MethodInfo GetAddressMethod ()
  1509. {
  1510. var mb = module.Builder;
  1511. var arg_types = new MetaType[rank];
  1512. for (int i = 0; i < rank; i++)
  1513. arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
  1514. var address = mb.GetArrayMethod (
  1515. GetMetaInfo (), "Address",
  1516. CallingConventions.HasThis | CallingConventions.Standard,
  1517. ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types);
  1518. return address;
  1519. }
  1520. public MethodInfo GetGetMethod ()
  1521. {
  1522. var mb = module.Builder;
  1523. var arg_types = new MetaType[rank];
  1524. for (int i = 0; i < rank; i++)
  1525. arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
  1526. var get = mb.GetArrayMethod (
  1527. GetMetaInfo (), "Get",
  1528. CallingConventions.HasThis | CallingConventions.Standard,
  1529. Element.GetMetaInfo (), arg_types);
  1530. return get;
  1531. }
  1532. public MethodInfo GetSetMethod ()
  1533. {
  1534. var mb = module.Builder;
  1535. var arg_types = new MetaType[rank + 1];
  1536. for (int i = 0; i < rank; i++)
  1537. arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
  1538. arg_types[rank] = Element.GetMetaInfo ();
  1539. var set = mb.GetArrayMethod (
  1540. GetMetaInfo (), "Set",
  1541. CallingConventions.HasThis | CallingConventions.Standard,
  1542. module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types);
  1543. return set;
  1544. }
  1545. public override MetaType GetMetaInfo ()
  1546. {
  1547. if (info == null) {
  1548. if (rank == 1)
  1549. info = Element.GetMetaInfo ().MakeArrayType ();
  1550. else
  1551. info = Element.GetMetaInfo ().MakeArrayType (rank);
  1552. }
  1553. return info;
  1554. }
  1555. protected override string GetPostfixSignature()
  1556. {
  1557. return GetPostfixSignature (rank);
  1558. }
  1559. public static string GetPostfixSignature (int rank)
  1560. {
  1561. StringBuilder sb = new StringBuilder ();
  1562. sb.Append ("[");
  1563. for (int i = 1; i < rank; i++) {
  1564. sb.Append (",");
  1565. }
  1566. sb.Append ("]");
  1567. return sb.ToString ();
  1568. }
  1569. public override string GetSignatureForDocumentation ()
  1570. {
  1571. StringBuilder sb = new StringBuilder ();
  1572. GetElementSignatureForDocumentation (sb);
  1573. return sb.ToString ();
  1574. }
  1575. void GetElementSignatureForDocumentation (StringBuilder sb)
  1576. {
  1577. var ac = Element as ArrayContainer;
  1578. if (ac == null)
  1579. sb.Append (Element.GetSignatureForDocumentation ());
  1580. else
  1581. ac.GetElementSignatureForDocumentation (sb);
  1582. sb.Append ("[");
  1583. for (int i = 1; i < rank; i++) {
  1584. if (i == 1)
  1585. sb.Append ("0:");
  1586. sb.Append (",0:");
  1587. }
  1588. sb.Append ("]");
  1589. }
  1590. public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
  1591. {
  1592. return MakeType (module, element, 1);
  1593. }
  1594. public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank)
  1595. {
  1596. ArrayContainer ac;
  1597. var key = new TypeRankPair (element, rank);
  1598. if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
  1599. ac = new ArrayContainer (module, element, rank);
  1600. ac.BaseType = module.Compiler.BuiltinTypes.Array;
  1601. ac.Interfaces = ac.BaseType.Interfaces;
  1602. module.ArrayTypesCache.Add (key, ac);
  1603. }
  1604. return ac;
  1605. }
  1606. public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
  1607. {
  1608. return Element.ResolveMissingDependencies (caller);
  1609. }
  1610. }
  1611. class ReferenceContainer : ElementTypeSpec
  1612. {
  1613. private ReferenceContainer (TypeSpec element)
  1614. : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
  1615. {
  1616. }
  1617. public override MetaType GetMetaInfo ()
  1618. {
  1619. if (info == null) {
  1620. info = Element.GetMetaInfo ().MakeByRefType ();
  1621. }
  1622. return info;
  1623. }
  1624. public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element)
  1625. {
  1626. ReferenceContainer pc;
  1627. if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) {
  1628. pc = new ReferenceContainer (element);
  1629. module.ReferenceTypesCache.Add (element, pc);
  1630. }
  1631. return pc;
  1632. }
  1633. }
  1634. class PointerContainer : ElementTypeSpec
  1635. {
  1636. private PointerContainer (TypeSpec element)
  1637. : base (MemberKind.PointerType, element, null)
  1638. {
  1639. // It's never CLS-Compliant
  1640. state &= ~StateFlags.CLSCompliant_Undetected;
  1641. }
  1642. public override MetaType GetMetaInfo ()
  1643. {
  1644. if (info == null) {
  1645. info = Element.GetMetaInfo ().MakePointerType ();
  1646. }
  1647. return info;
  1648. }
  1649. protected override string GetPostfixSignature()
  1650. {
  1651. return "*";
  1652. }
  1653. public static PointerContainer MakeType (ModuleContainer module, TypeSpec element)
  1654. {
  1655. PointerContainer pc;
  1656. if (!module.PointerTypesCache.TryGetValue (element, out pc)) {
  1657. pc = new PointerContainer (element);
  1658. module.PointerTypesCache.Add (element, pc);
  1659. }
  1660. return pc;
  1661. }
  1662. }
  1663. public class MissingTypeSpecReference
  1664. {
  1665. public MissingTypeSpecReference (TypeSpec type, MemberSpec caller)
  1666. {
  1667. Type = type;
  1668. Caller = caller;
  1669. }
  1670. public TypeSpec Type { get; private set; }
  1671. public MemberSpec Caller { get; private set; }
  1672. }
  1673. }