PageRenderTime 4849ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs

http://github.com/icsharpcode/SharpDevelop
C# | 350 lines | 277 code | 50 blank | 23 comment | 60 complexity | 1b3a874dc1d8d9d48a996c2a98e63e6a MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CPL-1.0, LGPL-2.1
  1. // Copyright (c) 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. using System;
  19. using System.Collections.Generic;
  20. using System.Globalization;
  21. using ICSharpCode.NRefactory.Utils;
  22. namespace ICSharpCode.NRefactory.TypeSystem.Implementation
  23. {
  24. public abstract class AbstractTypeParameter : ITypeParameter
  25. {
  26. readonly ICompilation compilation;
  27. readonly EntityType ownerType;
  28. readonly IEntity owner;
  29. readonly int index;
  30. readonly string name;
  31. readonly IList<IAttribute> attributes;
  32. readonly DomRegion region;
  33. readonly VarianceModifier variance;
  34. protected AbstractTypeParameter(IEntity owner, int index, string name, VarianceModifier variance, IList<IAttribute> attributes, DomRegion region)
  35. {
  36. if (owner == null)
  37. throw new ArgumentNullException("owner");
  38. this.owner = owner;
  39. this.compilation = owner.Compilation;
  40. this.ownerType = owner.EntityType;
  41. this.index = index;
  42. this.name = name ?? ((this.OwnerType == EntityType.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture));
  43. this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
  44. this.region = region;
  45. this.variance = variance;
  46. }
  47. protected AbstractTypeParameter(ICompilation compilation, EntityType ownerType, int index, string name, VarianceModifier variance, IList<IAttribute> attributes, DomRegion region)
  48. {
  49. if (compilation == null)
  50. throw new ArgumentNullException("compilation");
  51. this.compilation = compilation;
  52. this.ownerType = ownerType;
  53. this.index = index;
  54. this.name = name ?? ((this.OwnerType == EntityType.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture));
  55. this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
  56. this.region = region;
  57. this.variance = variance;
  58. }
  59. public EntityType OwnerType {
  60. get { return ownerType; }
  61. }
  62. public IEntity Owner {
  63. get { return owner; }
  64. }
  65. public int Index {
  66. get { return index; }
  67. }
  68. public IList<IAttribute> Attributes {
  69. get { return attributes; }
  70. }
  71. public VarianceModifier Variance {
  72. get { return variance; }
  73. }
  74. public DomRegion Region {
  75. get { return region; }
  76. }
  77. public ICompilation Compilation {
  78. get { return compilation; }
  79. }
  80. volatile IType effectiveBaseClass;
  81. public IType EffectiveBaseClass {
  82. get {
  83. if (effectiveBaseClass == null)
  84. effectiveBaseClass = CalculateEffectiveBaseClass();
  85. return effectiveBaseClass;
  86. }
  87. }
  88. IType CalculateEffectiveBaseClass()
  89. {
  90. // protect against cyclic type parameters
  91. using (var busyLock = BusyManager.Enter(this)) {
  92. if (!busyLock.Success)
  93. return SpecialType.UnknownType;
  94. if (HasValueTypeConstraint)
  95. return this.Compilation.FindType(KnownTypeCode.ValueType);
  96. List<IType> classTypeConstraints = new List<IType>();
  97. foreach (IType constraint in this.DirectBaseTypes) {
  98. if (constraint.Kind == TypeKind.Class) {
  99. classTypeConstraints.Add(constraint);
  100. } else if (constraint.Kind == TypeKind.TypeParameter) {
  101. IType baseClass = ((ITypeParameter)constraint).EffectiveBaseClass;
  102. if (baseClass.Kind == TypeKind.Class)
  103. classTypeConstraints.Add(baseClass);
  104. }
  105. }
  106. if (classTypeConstraints.Count == 0)
  107. return this.Compilation.FindType(KnownTypeCode.Object);
  108. // Find the derived-most type in the resulting set:
  109. IType result = classTypeConstraints[0];
  110. for (int i = 1; i < classTypeConstraints.Count; i++) {
  111. if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition()))
  112. result = classTypeConstraints[i];
  113. }
  114. return result;
  115. }
  116. }
  117. public IList<IType> EffectiveInterfaceSet {
  118. get {
  119. throw new NotImplementedException();
  120. }
  121. }
  122. public abstract bool HasDefaultConstructorConstraint { get; }
  123. public abstract bool HasReferenceTypeConstraint { get; }
  124. public abstract bool HasValueTypeConstraint { get; }
  125. public TypeKind Kind {
  126. get { return TypeKind.TypeParameter; }
  127. }
  128. public bool? IsReferenceType {
  129. get {
  130. if (this.HasValueTypeConstraint)
  131. return false;
  132. if (this.HasReferenceTypeConstraint)
  133. return true;
  134. // A type parameter is known to be a reference type if it has the reference type constraint
  135. // or its effective base class is not object or System.ValueType.
  136. IType effectiveBaseClass = this.EffectiveBaseClass;
  137. if (effectiveBaseClass.Kind == TypeKind.Class || effectiveBaseClass.Kind == TypeKind.Delegate) {
  138. ITypeDefinition effectiveBaseClassDef = effectiveBaseClass.GetDefinition();
  139. if (effectiveBaseClassDef != null) {
  140. switch (effectiveBaseClassDef.KnownTypeCode) {
  141. case KnownTypeCode.Object:
  142. case KnownTypeCode.ValueType:
  143. case KnownTypeCode.Enum:
  144. return null;
  145. }
  146. }
  147. return true;
  148. } else if (effectiveBaseClass.Kind == TypeKind.Struct || effectiveBaseClass.Kind == TypeKind.Enum) {
  149. return false;
  150. }
  151. return null;
  152. }
  153. }
  154. IType IType.DeclaringType {
  155. get { return null; }
  156. }
  157. int IType.TypeParameterCount {
  158. get { return 0; }
  159. }
  160. public abstract IEnumerable<IType> DirectBaseTypes { get; }
  161. public string Name {
  162. get { return name; }
  163. }
  164. string INamedElement.Namespace {
  165. get { return string.Empty; }
  166. }
  167. string INamedElement.FullName {
  168. get { return name; }
  169. }
  170. public string ReflectionName {
  171. get {
  172. return (this.OwnerType == EntityType.Method ? "``" : "`") + index.ToString(CultureInfo.InvariantCulture);
  173. }
  174. }
  175. ITypeDefinition IType.GetDefinition()
  176. {
  177. return null;
  178. }
  179. public IType AcceptVisitor(TypeVisitor visitor)
  180. {
  181. return visitor.VisitTypeParameter(this);
  182. }
  183. public IType VisitChildren(TypeVisitor visitor)
  184. {
  185. return this;
  186. }
  187. public ITypeReference ToTypeReference()
  188. {
  189. return new TypeParameterReference(this.OwnerType, this.Index);
  190. }
  191. IEnumerable<IType> IType.GetNestedTypes(Predicate<ITypeDefinition> filter, GetMemberOptions options)
  192. {
  193. return EmptyList<IType>.Instance;
  194. }
  195. IEnumerable<IType> IType.GetNestedTypes(IList<IType> typeArguments, Predicate<ITypeDefinition> filter, GetMemberOptions options)
  196. {
  197. return EmptyList<IType>.Instance;
  198. }
  199. static readonly IUnresolvedMethod dummyConstructor = CreateDummyConstructor();
  200. static IUnresolvedMethod CreateDummyConstructor()
  201. {
  202. var m = new DefaultUnresolvedMethod {
  203. EntityType = EntityType.Constructor,
  204. Name = ".ctor",
  205. Accessibility = Accessibility.Public,
  206. IsSynthetic = true,
  207. ReturnType = KnownTypeReference.Void
  208. };
  209. m.Freeze();
  210. return m;
  211. }
  212. static IMethod GetDummyConstructor(ICompilation compilation)
  213. {
  214. // Reuse the same IMethod instance for all dummy constructors
  215. // so that two occurrences of 'new T()' refer to the same constructor.
  216. return (IMethod)compilation.CacheManager.GetOrAddShared(
  217. dummyConstructor, _ => dummyConstructor.CreateResolved(compilation.TypeResolveContext));
  218. }
  219. public IEnumerable<IMethod> GetConstructors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
  220. {
  221. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
  222. if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint) {
  223. if (filter == null || filter(dummyConstructor)) {
  224. var resolvedCtor = GetDummyConstructor(compilation);
  225. IMethod m = new SpecializedMethod(resolvedCtor, TypeParameterSubstitution.Identity) { DeclaringType = this };
  226. return new [] { m };
  227. }
  228. }
  229. return EmptyList<IMethod>.Instance;
  230. } else {
  231. return GetMembersHelper.GetConstructors(this, filter, options);
  232. }
  233. }
  234. public IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
  235. {
  236. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  237. return EmptyList<IMethod>.Instance;
  238. else
  239. return GetMembersHelper.GetMethods(this, FilterNonStatic(filter), options);
  240. }
  241. public IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
  242. {
  243. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  244. return EmptyList<IMethod>.Instance;
  245. else
  246. return GetMembersHelper.GetMethods(this, typeArguments, FilterNonStatic(filter), options);
  247. }
  248. public IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
  249. {
  250. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  251. return EmptyList<IProperty>.Instance;
  252. else
  253. return GetMembersHelper.GetProperties(this, FilterNonStatic(filter), options);
  254. }
  255. public IEnumerable<IField> GetFields(Predicate<IUnresolvedField> filter = null, GetMemberOptions options = GetMemberOptions.None)
  256. {
  257. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  258. return EmptyList<IField>.Instance;
  259. else
  260. return GetMembersHelper.GetFields(this, FilterNonStatic(filter), options);
  261. }
  262. public IEnumerable<IEvent> GetEvents(Predicate<IUnresolvedEvent> filter = null, GetMemberOptions options = GetMemberOptions.None)
  263. {
  264. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  265. return EmptyList<IEvent>.Instance;
  266. else
  267. return GetMembersHelper.GetEvents(this, FilterNonStatic(filter), options);
  268. }
  269. public IEnumerable<IMember> GetMembers(Predicate<IUnresolvedMember> filter = null, GetMemberOptions options = GetMemberOptions.None)
  270. {
  271. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  272. return EmptyList<IMember>.Instance;
  273. else
  274. return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options);
  275. }
  276. static Predicate<T> FilterNonStatic<T>(Predicate<T> filter) where T : class, IUnresolvedMember
  277. {
  278. if (filter == null)
  279. return member => !member.IsStatic;
  280. else
  281. return member => !member.IsStatic && filter(member);
  282. }
  283. public sealed override bool Equals(object obj)
  284. {
  285. return Equals(obj as IType);
  286. }
  287. public override int GetHashCode()
  288. {
  289. return base.GetHashCode();
  290. }
  291. public virtual bool Equals(IType other)
  292. {
  293. return this == other; // use reference equality for type parameters
  294. }
  295. public override string ToString()
  296. {
  297. return this.ReflectionName;
  298. }
  299. }
  300. }