PageRenderTime 29ms CodeModel.GetById 5ms app.highlight 18ms RepoModel.GetById 2ms app.codeStats 0ms

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