/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs

http://github.com/icsharpcode/ILSpy · C# · 410 lines · 311 code · 60 blank · 39 comment · 42 complexity · 57df86948b88cd82d6895078f3bd23db MD5 · raw file

  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. using System;
  19. using System.Collections.Generic;
  20. using System.Diagnostics;
  21. using System.Linq;
  22. using System.Text;
  23. using System.Threading;
  24. using ICSharpCode.NRefactory.Documentation;
  25. using ICSharpCode.NRefactory.Utils;
  26. namespace ICSharpCode.NRefactory.TypeSystem.Implementation
  27. {
  28. /// <summary>
  29. /// Represents a SpecializedMember (a member on which type substitution has been performed).
  30. /// </summary>
  31. public abstract class SpecializedMember : IMember
  32. {
  33. protected readonly IMember baseMember;
  34. TypeParameterSubstitution substitution;
  35. IType declaringType;
  36. IType returnType;
  37. protected SpecializedMember(IMember memberDefinition)
  38. {
  39. if (memberDefinition == null)
  40. throw new ArgumentNullException("memberDefinition");
  41. if (memberDefinition is SpecializedMember)
  42. throw new ArgumentException("Member definition cannot be specialized. Please use IMember.Specialize() instead of directly constructing SpecializedMember instances.");
  43. this.baseMember = memberDefinition;
  44. this.substitution = TypeParameterSubstitution.Identity;
  45. }
  46. /// <summary>
  47. /// Performs a substitution. This method may only be called by constructors in derived classes.
  48. /// </summary>
  49. protected void AddSubstitution(TypeParameterSubstitution newSubstitution)
  50. {
  51. Debug.Assert(declaringType == null);
  52. Debug.Assert(returnType == null);
  53. this.substitution = TypeParameterSubstitution.Compose(newSubstitution, this.substitution);
  54. }
  55. [Obsolete("Use IMember.Specialize() instead")]
  56. public static IMember Create(IMember memberDefinition, TypeParameterSubstitution substitution)
  57. {
  58. if (memberDefinition == null) {
  59. return null;
  60. } else {
  61. return memberDefinition.Specialize(substitution);
  62. }
  63. }
  64. public virtual IMemberReference ToMemberReference()
  65. {
  66. return ToReference();
  67. }
  68. public virtual IMemberReference ToReference()
  69. {
  70. return new SpecializingMemberReference(
  71. baseMember.ToReference(),
  72. ToTypeReference(substitution.ClassTypeArguments),
  73. null);
  74. }
  75. ISymbolReference ISymbol.ToReference()
  76. {
  77. return ToReference();
  78. }
  79. internal static IList<ITypeReference> ToTypeReference(IList<IType> typeArguments)
  80. {
  81. if (typeArguments == null)
  82. return null;
  83. else
  84. return typeArguments.Select(t => t.ToTypeReference()).ToArray();
  85. }
  86. internal IMethod WrapAccessor(ref IMethod cachingField, IMethod accessorDefinition)
  87. {
  88. if (accessorDefinition == null)
  89. return null;
  90. var result = LazyInit.VolatileRead(ref cachingField);
  91. if (result != null) {
  92. return result;
  93. } else {
  94. var sm = accessorDefinition.Specialize(substitution);
  95. //sm.AccessorOwner = this;
  96. return LazyInit.GetOrSet(ref cachingField, sm);
  97. }
  98. }
  99. /// <summary>
  100. /// Gets the substitution belonging to this specialized member.
  101. /// </summary>
  102. public TypeParameterSubstitution Substitution {
  103. get { return substitution; }
  104. }
  105. public IType DeclaringType {
  106. get {
  107. var result = LazyInit.VolatileRead(ref this.declaringType);
  108. if (result != null)
  109. return result;
  110. IType definitionDeclaringType = baseMember.DeclaringType;
  111. ITypeDefinition definitionDeclaringTypeDef = definitionDeclaringType as ITypeDefinition;
  112. if (definitionDeclaringTypeDef != null && definitionDeclaringType.TypeParameterCount > 0) {
  113. if (substitution.ClassTypeArguments != null && substitution.ClassTypeArguments.Count == definitionDeclaringType.TypeParameterCount) {
  114. result = new ParameterizedType(definitionDeclaringTypeDef, substitution.ClassTypeArguments);
  115. } else {
  116. result = new ParameterizedType(definitionDeclaringTypeDef, definitionDeclaringTypeDef.TypeParameters).AcceptVisitor(substitution);
  117. }
  118. } else {
  119. result = definitionDeclaringType.AcceptVisitor(substitution);
  120. }
  121. return LazyInit.GetOrSet(ref this.declaringType, result);
  122. }
  123. internal set {
  124. // This setter is used as an optimization when the code constructing
  125. // the SpecializedMember already knows the declaring type.
  126. Debug.Assert(this.declaringType == null);
  127. Debug.Assert(value != null);
  128. // As this setter is used only during construction before the member is published
  129. // to other threads, we don't need a volatile write.
  130. this.declaringType = value;
  131. }
  132. }
  133. public IMember MemberDefinition {
  134. get { return baseMember.MemberDefinition; }
  135. }
  136. public IUnresolvedMember UnresolvedMember {
  137. get { return baseMember.UnresolvedMember; }
  138. }
  139. public IType ReturnType {
  140. get {
  141. var result = LazyInit.VolatileRead(ref this.returnType);
  142. if (result != null)
  143. return result;
  144. else
  145. return LazyInit.GetOrSet(ref this.returnType, baseMember.ReturnType.AcceptVisitor(substitution));
  146. }
  147. protected set {
  148. // This setter is used for LiftedUserDefinedOperator, a special case of specialized member
  149. // (not a normal type parameter substitution).
  150. // As this setter is used only during construction before the member is published
  151. // to other threads, we don't need a volatile write.
  152. this.returnType = value;
  153. }
  154. }
  155. public bool IsVirtual {
  156. get { return baseMember.IsVirtual; }
  157. }
  158. public bool IsOverride {
  159. get { return baseMember.IsOverride; }
  160. }
  161. public bool IsOverridable {
  162. get { return baseMember.IsOverridable; }
  163. }
  164. public SymbolKind SymbolKind {
  165. get { return baseMember.SymbolKind; }
  166. }
  167. [Obsolete("Use the SymbolKind property instead.")]
  168. public EntityType EntityType {
  169. get { return baseMember.EntityType; }
  170. }
  171. public DomRegion Region {
  172. get { return baseMember.Region; }
  173. }
  174. public DomRegion BodyRegion {
  175. get { return baseMember.BodyRegion; }
  176. }
  177. public ITypeDefinition DeclaringTypeDefinition {
  178. get { return baseMember.DeclaringTypeDefinition; }
  179. }
  180. public IList<IAttribute> Attributes {
  181. get { return baseMember.Attributes; }
  182. }
  183. IList<IMember> implementedInterfaceMembers;
  184. public IList<IMember> ImplementedInterfaceMembers {
  185. get {
  186. return LazyInitializer.EnsureInitialized(ref implementedInterfaceMembers, FindImplementedInterfaceMembers);
  187. }
  188. }
  189. IList<IMember> FindImplementedInterfaceMembers()
  190. {
  191. var definitionImplementations = baseMember.ImplementedInterfaceMembers;
  192. IMember[] result = new IMember[definitionImplementations.Count];
  193. for (int i = 0; i < result.Length; i++) {
  194. result[i] = definitionImplementations[i].Specialize(substitution);
  195. }
  196. return result;
  197. }
  198. public bool IsExplicitInterfaceImplementation {
  199. get { return baseMember.IsExplicitInterfaceImplementation; }
  200. }
  201. public DocumentationComment Documentation {
  202. get { return baseMember.Documentation; }
  203. }
  204. public Accessibility Accessibility {
  205. get { return baseMember.Accessibility; }
  206. }
  207. public bool IsStatic {
  208. get { return baseMember.IsStatic; }
  209. }
  210. public bool IsAbstract {
  211. get { return baseMember.IsAbstract; }
  212. }
  213. public bool IsSealed {
  214. get { return baseMember.IsSealed; }
  215. }
  216. public bool IsShadowing {
  217. get { return baseMember.IsShadowing; }
  218. }
  219. public bool IsSynthetic {
  220. get { return baseMember.IsSynthetic; }
  221. }
  222. public bool IsPrivate {
  223. get { return baseMember.IsPrivate; }
  224. }
  225. public bool IsPublic {
  226. get { return baseMember.IsPublic; }
  227. }
  228. public bool IsProtected {
  229. get { return baseMember.IsProtected; }
  230. }
  231. public bool IsInternal {
  232. get { return baseMember.IsInternal; }
  233. }
  234. public bool IsProtectedOrInternal {
  235. get { return baseMember.IsProtectedOrInternal; }
  236. }
  237. public bool IsProtectedAndInternal {
  238. get { return baseMember.IsProtectedAndInternal; }
  239. }
  240. public string FullName {
  241. get { return baseMember.FullName; }
  242. }
  243. public string Name {
  244. get { return baseMember.Name; }
  245. }
  246. public string Namespace {
  247. get { return baseMember.Namespace; }
  248. }
  249. public string ReflectionName {
  250. get { return baseMember.ReflectionName; }
  251. }
  252. public ICompilation Compilation {
  253. get { return baseMember.Compilation; }
  254. }
  255. public IAssembly ParentAssembly {
  256. get { return baseMember.ParentAssembly; }
  257. }
  258. public virtual IMember Specialize(TypeParameterSubstitution newSubstitution)
  259. {
  260. return baseMember.Specialize(TypeParameterSubstitution.Compose(newSubstitution, this.substitution));
  261. }
  262. public override bool Equals(object obj)
  263. {
  264. SpecializedMember other = obj as SpecializedMember;
  265. if (other == null)
  266. return false;
  267. return this.baseMember.Equals(other.baseMember) && this.substitution.Equals(other.substitution);
  268. }
  269. public override int GetHashCode()
  270. {
  271. unchecked {
  272. return 1000000007 * baseMember.GetHashCode() + 1000000009 * substitution.GetHashCode();
  273. }
  274. }
  275. public override string ToString()
  276. {
  277. StringBuilder b = new StringBuilder("[");
  278. b.Append(GetType().Name);
  279. b.Append(' ');
  280. b.Append(this.DeclaringType.ToString());
  281. b.Append('.');
  282. b.Append(this.Name);
  283. b.Append(':');
  284. b.Append(this.ReturnType.ToString());
  285. b.Append(']');
  286. return b.ToString();
  287. }
  288. }
  289. public abstract class SpecializedParameterizedMember : SpecializedMember, IParameterizedMember
  290. {
  291. IList<IParameter> parameters;
  292. protected SpecializedParameterizedMember(IParameterizedMember memberDefinition)
  293. : base(memberDefinition)
  294. {
  295. }
  296. public IList<IParameter> Parameters {
  297. get {
  298. var result = LazyInit.VolatileRead(ref this.parameters);
  299. if (result != null)
  300. return result;
  301. else
  302. return LazyInit.GetOrSet(ref this.parameters, CreateParameters(this.Substitution));
  303. }
  304. protected set {
  305. // This setter is used for LiftedUserDefinedOperator, a special case of specialized member
  306. // (not a normal type parameter substitution).
  307. // As this setter is used only during construction before the member is published
  308. // to other threads, we don't need a volatile write.
  309. this.parameters = value;
  310. }
  311. }
  312. protected IList<IParameter> CreateParameters(TypeVisitor substitution)
  313. {
  314. var paramDefs = ((IParameterizedMember)this.baseMember).Parameters;
  315. if (paramDefs.Count == 0) {
  316. return EmptyList<IParameter>.Instance;
  317. } else {
  318. var parameters = new IParameter[paramDefs.Count];
  319. for (int i = 0; i < parameters.Length; i++) {
  320. var p = paramDefs[i];
  321. IType newType = p.Type.AcceptVisitor(substitution);
  322. parameters[i] = new DefaultParameter(
  323. newType, p.Name, this,
  324. p.Region, p.Attributes, p.IsRef, p.IsOut,
  325. p.IsParams, p.IsOptional, p.ConstantValue
  326. );
  327. }
  328. return Array.AsReadOnly(parameters);
  329. }
  330. }
  331. public override string ToString()
  332. {
  333. StringBuilder b = new StringBuilder("[");
  334. b.Append(GetType().Name);
  335. b.Append(' ');
  336. b.Append(this.DeclaringType.ReflectionName);
  337. b.Append('.');
  338. b.Append(this.Name);
  339. b.Append('(');
  340. for (int i = 0; i < this.Parameters.Count; i++) {
  341. if (i > 0) b.Append(", ");
  342. b.Append(this.Parameters[i].ToString());
  343. }
  344. b.Append("):");
  345. b.Append(this.ReturnType.ReflectionName);
  346. b.Append(']');
  347. return b.ToString();
  348. }
  349. }
  350. }