|
|
|
|
@ -18,6 +18,7 @@
@@ -18,6 +18,7 @@
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Text; |
|
|
|
|
using System.Threading; |
|
|
|
|
@ -31,58 +32,115 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -31,58 +32,115 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
/// </summary>
|
|
|
|
|
public abstract class SpecializedMember : IMember |
|
|
|
|
{ |
|
|
|
|
readonly IType declaringType; |
|
|
|
|
readonly IMember memberDefinition; |
|
|
|
|
TypeParameterSubstitution substitution; |
|
|
|
|
|
|
|
|
|
IType declaringType; |
|
|
|
|
IType returnType; |
|
|
|
|
|
|
|
|
|
protected SpecializedMember(IType declaringType, IMember memberDefinition) |
|
|
|
|
protected SpecializedMember(IMember memberDefinition) |
|
|
|
|
{ |
|
|
|
|
if (declaringType == null) |
|
|
|
|
throw new ArgumentNullException("declaringType"); |
|
|
|
|
if (memberDefinition == null) |
|
|
|
|
throw new ArgumentNullException("memberDefinition"); |
|
|
|
|
|
|
|
|
|
this.declaringType = declaringType; |
|
|
|
|
this.memberDefinition = memberDefinition; |
|
|
|
|
SpecializedMember sm = memberDefinition as SpecializedMember; |
|
|
|
|
if (sm != null) { |
|
|
|
|
this.memberDefinition = sm.memberDefinition; |
|
|
|
|
this.substitution = sm.substitution; |
|
|
|
|
} else { |
|
|
|
|
this.memberDefinition = memberDefinition; |
|
|
|
|
this.substitution = TypeParameterSubstitution.Identity; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual void Initialize(TypeVisitor substitution) |
|
|
|
|
/// <summary>
|
|
|
|
|
/// Performs a substitution. This method may only be called by constructors in derived classes.
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected void AddSubstitution(TypeParameterSubstitution newSubstitution) |
|
|
|
|
{ |
|
|
|
|
this.returnType = Substitute(memberDefinition.ReturnType, substitution); |
|
|
|
|
Debug.Assert(declaringType == null); |
|
|
|
|
Debug.Assert(returnType == null); |
|
|
|
|
this.substitution = TypeParameterSubstitution.Compose(newSubstitution, this.substitution); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public virtual IMemberReference ToMemberReference() |
|
|
|
|
public static SpecializedMember Create(IMember memberDefinition, TypeParameterSubstitution substitution) |
|
|
|
|
{ |
|
|
|
|
return new SpecializingMemberReference(declaringType.ToTypeReference(), memberDefinition.ToMemberReference()); |
|
|
|
|
if (memberDefinition == null) { |
|
|
|
|
return null; |
|
|
|
|
} else if (memberDefinition is IMethod) { |
|
|
|
|
return new SpecializedMethod((IMethod)memberDefinition, substitution); |
|
|
|
|
} else if (memberDefinition is IProperty) { |
|
|
|
|
return new SpecializedProperty((IProperty)memberDefinition, substitution); |
|
|
|
|
} else if (memberDefinition is IField) { |
|
|
|
|
return new SpecializedField((IField)memberDefinition, substitution); |
|
|
|
|
} else if (memberDefinition is IEvent) { |
|
|
|
|
return new SpecializedEvent((IEvent)memberDefinition, substitution); |
|
|
|
|
} else { |
|
|
|
|
throw new NotSupportedException("Unknown IMember: " + memberDefinition); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal static TypeVisitor GetSubstitution(IType declaringType) |
|
|
|
|
public IMemberReference ToMemberReference() |
|
|
|
|
{ |
|
|
|
|
ParameterizedType pt = declaringType as ParameterizedType; |
|
|
|
|
if (pt != null) |
|
|
|
|
return pt.GetSubstitution(); |
|
|
|
|
else |
|
|
|
|
return null; |
|
|
|
|
return new SpecializingMemberReference( |
|
|
|
|
memberDefinition.ToMemberReference(), |
|
|
|
|
ToTypeReference(substitution.ClassTypeArguments), |
|
|
|
|
ToTypeReference(substitution.MethodTypeArguments)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal static IType Substitute(IType type, TypeVisitor substitution) |
|
|
|
|
static IList<ITypeReference> ToTypeReference(IList<IType> typeArguments) |
|
|
|
|
{ |
|
|
|
|
if (substitution == null) |
|
|
|
|
return type; |
|
|
|
|
if (typeArguments == null) |
|
|
|
|
return null; |
|
|
|
|
else |
|
|
|
|
return type.AcceptVisitor(substitution); |
|
|
|
|
return typeArguments.Select(t => t.ToTypeReference()).ToArray(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal IMethod WrapAccessor(IMethod accessorDefinition) |
|
|
|
|
internal IMethod WrapAccessor(ref IMethod cachingField, IMethod accessorDefinition) |
|
|
|
|
{ |
|
|
|
|
if (accessorDefinition == null) |
|
|
|
|
return null; |
|
|
|
|
var result = LazyInit.VolatileRead(ref cachingField); |
|
|
|
|
if (result != null) |
|
|
|
|
return result; |
|
|
|
|
else |
|
|
|
|
return new SpecializedMethod(declaringType, accessorDefinition); |
|
|
|
|
return LazyInit.GetOrSet(ref cachingField, new SpecializedMethod(accessorDefinition, substitution)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the substitution belonging to this specialized member.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public TypeParameterSubstitution Substitution { |
|
|
|
|
get { return substitution; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IType DeclaringType { |
|
|
|
|
get { return declaringType; } |
|
|
|
|
get { |
|
|
|
|
var result = LazyInit.VolatileRead(ref this.declaringType); |
|
|
|
|
if (result != null) |
|
|
|
|
return result; |
|
|
|
|
IType definitionDeclaringType = memberDefinition.DeclaringType; |
|
|
|
|
ITypeDefinition definitionDeclaringTypeDef = definitionDeclaringType as ITypeDefinition; |
|
|
|
|
if (definitionDeclaringTypeDef != null && definitionDeclaringType.TypeParameterCount > 0) { |
|
|
|
|
if (substitution.ClassTypeArguments != null && substitution.ClassTypeArguments.Count == definitionDeclaringType.TypeParameterCount) { |
|
|
|
|
result = new ParameterizedType(definitionDeclaringTypeDef, substitution.ClassTypeArguments); |
|
|
|
|
} else { |
|
|
|
|
result = new ParameterizedType(definitionDeclaringTypeDef, definitionDeclaringTypeDef.TypeParameters).AcceptVisitor(substitution); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
result = definitionDeclaringType.AcceptVisitor(substitution); |
|
|
|
|
} |
|
|
|
|
return LazyInit.GetOrSet(ref this.declaringType, result); |
|
|
|
|
} |
|
|
|
|
internal set { |
|
|
|
|
// This setter is used as an optimization when the code constructing
|
|
|
|
|
// the SpecializedMember already knows the declaring type.
|
|
|
|
|
Debug.Assert(this.declaringType == null); |
|
|
|
|
Debug.Assert(value != null); |
|
|
|
|
// As this setter is used only during construction before the member is published
|
|
|
|
|
// to other threads, we don't need a volatile write.
|
|
|
|
|
this.declaringType = value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IMember MemberDefinition { |
|
|
|
|
@ -94,8 +152,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -94,8 +152,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IType ReturnType { |
|
|
|
|
get { return returnType; } |
|
|
|
|
protected set { returnType = value; } |
|
|
|
|
get { |
|
|
|
|
var result = LazyInit.VolatileRead(ref this.returnType); |
|
|
|
|
if (result != null) |
|
|
|
|
return result; |
|
|
|
|
else |
|
|
|
|
return LazyInit.GetOrSet(ref this.returnType, memberDefinition.ReturnType.AcceptVisitor(substitution)); |
|
|
|
|
} |
|
|
|
|
protected set { |
|
|
|
|
// This setter is used for LiftedUserDefinedOperator, a special case of specialized member
|
|
|
|
|
// (not a normal type parameter substitution).
|
|
|
|
|
|
|
|
|
|
// As this setter is used only during construction before the member is published
|
|
|
|
|
// to other threads, we don't need a volatile write.
|
|
|
|
|
this.returnType = value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public bool IsVirtual { |
|
|
|
|
@ -143,19 +214,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -143,19 +214,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
var definitionImplementations = memberDefinition.ImplementedInterfaceMembers; |
|
|
|
|
IMember[] result = new IMember[definitionImplementations.Count]; |
|
|
|
|
for (int i = 0; i < result.Length; i++) { |
|
|
|
|
result[i] = Specialize(definitionImplementations[i]); |
|
|
|
|
result[i] = SpecializedMember.Create(definitionImplementations[i], substitution); |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Specialize another member using the same type arguments as this member.
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected virtual IMember Specialize(IMember otherMember) |
|
|
|
|
{ |
|
|
|
|
return SpecializingMemberReference.CreateSpecializedMember(declaringType, memberDefinition, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public bool IsExplicitInterfaceImplementation { |
|
|
|
|
get { return memberDefinition.IsExplicitInterfaceImplementation; } |
|
|
|
|
} |
|
|
|
|
@ -241,13 +304,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -241,13 +304,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
SpecializedMember other = obj as SpecializedMember; |
|
|
|
|
if (other == null) |
|
|
|
|
return false; |
|
|
|
|
return this.declaringType.Equals(other.declaringType) && this.memberDefinition.Equals(other.memberDefinition); |
|
|
|
|
return this.memberDefinition.Equals(other.memberDefinition) && this.substitution.Equals(other.substitution); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override int GetHashCode() |
|
|
|
|
{ |
|
|
|
|
unchecked { |
|
|
|
|
return 1000000007 * declaringType.GetHashCode() + 1000000009 * memberDefinition.GetHashCode(); |
|
|
|
|
return 1000000007 * memberDefinition.GetHashCode() + 1000000009 * substitution.GetHashCode(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -256,11 +319,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -256,11 +319,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
StringBuilder b = new StringBuilder("["); |
|
|
|
|
b.Append(GetType().Name); |
|
|
|
|
b.Append(' '); |
|
|
|
|
b.Append(declaringType.ToString()); |
|
|
|
|
b.Append(this.DeclaringType.ToString()); |
|
|
|
|
b.Append('.'); |
|
|
|
|
b.Append(this.Name); |
|
|
|
|
b.Append(':'); |
|
|
|
|
b.Append(returnType.ToString()); |
|
|
|
|
b.Append(this.ReturnType.ToString()); |
|
|
|
|
b.Append(']'); |
|
|
|
|
return b.ToString(); |
|
|
|
|
} |
|
|
|
|
@ -270,36 +333,48 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -270,36 +333,48 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
{ |
|
|
|
|
IList<IParameter> parameters; |
|
|
|
|
|
|
|
|
|
protected SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition) |
|
|
|
|
: base(declaringType, memberDefinition) |
|
|
|
|
protected SpecializedParameterizedMember(IParameterizedMember memberDefinition) |
|
|
|
|
: base(memberDefinition) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override void Initialize(TypeVisitor substitution) |
|
|
|
|
public IList<IParameter> Parameters { |
|
|
|
|
get { |
|
|
|
|
var result = LazyInit.VolatileRead(ref this.parameters); |
|
|
|
|
if (result != null) |
|
|
|
|
return result; |
|
|
|
|
else |
|
|
|
|
return LazyInit.GetOrSet(ref this.parameters, CreateParameters(this.Substitution)); |
|
|
|
|
} |
|
|
|
|
protected set { |
|
|
|
|
// This setter is used for LiftedUserDefinedOperator, a special case of specialized member
|
|
|
|
|
// (not a normal type parameter substitution).
|
|
|
|
|
|
|
|
|
|
// As this setter is used only during construction before the member is published
|
|
|
|
|
// to other threads, we don't need a volatile write.
|
|
|
|
|
this.parameters = value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected IList<IParameter> CreateParameters(TypeVisitor substitution) |
|
|
|
|
{ |
|
|
|
|
base.Initialize(substitution); |
|
|
|
|
|
|
|
|
|
var paramDefs = ((IParameterizedMember)this.MemberDefinition).Parameters; |
|
|
|
|
if (paramDefs.Count == 0) { |
|
|
|
|
this.parameters = EmptyList<IParameter>.Instance; |
|
|
|
|
return EmptyList<IParameter>.Instance; |
|
|
|
|
} else { |
|
|
|
|
var parameters = new IParameter[paramDefs.Count]; |
|
|
|
|
for (int i = 0; i < parameters.Length; i++) { |
|
|
|
|
IType newType = Substitute(paramDefs[i].Type, substitution); |
|
|
|
|
IType newType = paramDefs[i].Type.AcceptVisitor(substitution); |
|
|
|
|
if (newType != paramDefs[i].Type) { |
|
|
|
|
parameters[i] = new SpecializedParameter(paramDefs[i], newType); |
|
|
|
|
} else { |
|
|
|
|
parameters[i] = paramDefs[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.parameters = Array.AsReadOnly(parameters); |
|
|
|
|
return Array.AsReadOnly(parameters); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IList<IParameter> Parameters { |
|
|
|
|
get { return parameters; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override string ToString() |
|
|
|
|
{ |
|
|
|
|
StringBuilder b = new StringBuilder("["); |
|
|
|
|
@ -309,9 +384,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -309,9 +384,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
b.Append('.'); |
|
|
|
|
b.Append(this.Name); |
|
|
|
|
b.Append('('); |
|
|
|
|
for (int i = 0; i < parameters.Count; i++) { |
|
|
|
|
for (int i = 0; i < this.Parameters.Count; i++) { |
|
|
|
|
if (i > 0) b.Append(", "); |
|
|
|
|
b.Append(parameters[i].ToString()); |
|
|
|
|
b.Append(this.Parameters[i].ToString()); |
|
|
|
|
} |
|
|
|
|
b.Append("):"); |
|
|
|
|
b.Append(this.ReturnType.ToString()); |
|
|
|
|
@ -326,7 +401,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -326,7 +401,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
|
|
|
|
|
public SpecializedParameter(IParameter originalParameter, IType newType) |
|
|
|
|
{ |
|
|
|
|
this.originalParameter = originalParameter; |
|
|
|
|
if (originalParameter is SpecializedParameter) |
|
|
|
|
this.originalParameter = ((SpecializedParameter)originalParameter).originalParameter; |
|
|
|
|
else |
|
|
|
|
this.originalParameter = originalParameter; |
|
|
|
|
this.newType = newType; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|