|
|
|
|
@ -18,8 +18,12 @@
@@ -18,8 +18,12 @@
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Text; |
|
|
|
|
|
|
|
|
|
using ICSharpCode.NRefactory.Utils; |
|
|
|
|
|
|
|
|
|
namespace ICSharpCode.NRefactory.TypeSystem.Implementation |
|
|
|
|
{ |
|
|
|
|
/// <summary>
|
|
|
|
|
@ -29,23 +33,58 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -29,23 +33,58 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
{ |
|
|
|
|
readonly IMethod methodDefinition; |
|
|
|
|
readonly IList<IType> typeArguments; |
|
|
|
|
readonly IList<ITypeParameter> specializedTypeParameters; |
|
|
|
|
|
|
|
|
|
public SpecializedMethod(IType declaringType, IMethod methodDefinition, IList<IType> typeArguments = null) |
|
|
|
|
: this(declaringType, methodDefinition, typeArguments, GetSubstitution(declaringType, typeArguments), null) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal SpecializedMethod(IType declaringType, IMethod methodDefinition, IList<IType> typeArguments, TypeVisitor substitution, ITypeResolveContext context) : base(declaringType, methodDefinition, substitution, context) |
|
|
|
|
internal SpecializedMethod(IType declaringType, IMethod methodDefinition, IList<IType> typeArguments, TypeVisitor substitution, ITypeResolveContext context) |
|
|
|
|
: base(declaringType, methodDefinition) |
|
|
|
|
{ |
|
|
|
|
if (declaringType == null) |
|
|
|
|
throw new ArgumentNullException("declaringType"); |
|
|
|
|
if (methodDefinition == null) |
|
|
|
|
throw new ArgumentNullException("methodDefinition"); |
|
|
|
|
|
|
|
|
|
this.methodDefinition = methodDefinition; |
|
|
|
|
this.typeArguments = typeArguments; |
|
|
|
|
|
|
|
|
|
if (typeArguments != null) { |
|
|
|
|
if (methodDefinition.TypeParameters.Any(ConstraintNeedsSpecialization)) { |
|
|
|
|
// The method is generic, and we need to specialize the type parameters
|
|
|
|
|
specializedTypeParameters = new ITypeParameter[methodDefinition.TypeParameters.Count]; |
|
|
|
|
for (int i = 0; i < specializedTypeParameters.Count; i++) { |
|
|
|
|
ITypeParameter tp = methodDefinition.TypeParameters[i]; |
|
|
|
|
if (ConstraintNeedsSpecialization(tp)) |
|
|
|
|
tp = new SpecializedTypeParameter(tp, substitution); |
|
|
|
|
specializedTypeParameters[i] = tp; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (typeArguments != null && typeArguments.Count > 0) { |
|
|
|
|
if (typeArguments.Count != methodDefinition.TypeParameters.Count) |
|
|
|
|
throw new ArgumentException("Number of type arguments does not match number of type parameters"); |
|
|
|
|
this.typeArguments = typeArguments; |
|
|
|
|
} else { |
|
|
|
|
this.typeArguments = EmptyList<IType>.Instance; |
|
|
|
|
throw new ArgumentException("Incorrect number of type arguments"); |
|
|
|
|
} else if (specializedTypeParameters != null) { |
|
|
|
|
// No type arguments were specified, but the method is generic.
|
|
|
|
|
// -> substitute original type parameters with the specialized ones
|
|
|
|
|
substitution = GetSubstitution(declaringType, specializedTypeParameters.ToArray<IType>()); |
|
|
|
|
for (int i = 0; i < specializedTypeParameters.Count; i++) { |
|
|
|
|
if (ConstraintNeedsSpecialization(methodDefinition.TypeParameters[i])) { |
|
|
|
|
((SpecializedTypeParameter)specializedTypeParameters[i]).substitution = substitution; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Initialize(substitution, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool ConstraintNeedsSpecialization(ITypeParameter tp) |
|
|
|
|
{ |
|
|
|
|
DefaultTypeParameter dtp = tp as DefaultTypeParameter; |
|
|
|
|
if (dtp != null) |
|
|
|
|
return dtp.Constraints.Count != 0; |
|
|
|
|
else |
|
|
|
|
return true; // we can't know if specialization will be required
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal static TypeVisitor GetSubstitution(IType declaringType, IList<IType> typeArguments) |
|
|
|
|
@ -97,7 +136,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -97,7 +136,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IList<ITypeParameter> TypeParameters { |
|
|
|
|
get { return methodDefinition.TypeParameters; } |
|
|
|
|
get { |
|
|
|
|
return specializedTypeParameters ?? methodDefinition.TypeParameters; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public bool IsExtensionMethod { |
|
|
|
|
@ -142,5 +183,48 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@@ -142,5 +183,48 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
|
|
|
|
|
b.Append(']'); |
|
|
|
|
return b.ToString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sealed class SpecializedTypeParameter : AbstractTypeParameter |
|
|
|
|
{ |
|
|
|
|
readonly ITypeParameter baseTp; |
|
|
|
|
// The substition may be replaced at the end of SpecializedMethod constructor
|
|
|
|
|
internal TypeVisitor substitution; |
|
|
|
|
|
|
|
|
|
public SpecializedTypeParameter(ITypeParameter baseTP, TypeVisitor substitution) |
|
|
|
|
: base(baseTP.OwnerType, baseTP.Index, baseTP.Name) |
|
|
|
|
{ |
|
|
|
|
this.baseTp = baseTP; |
|
|
|
|
this.substitution = substitution; |
|
|
|
|
|
|
|
|
|
this.Variance = baseTP.Variance; |
|
|
|
|
this.Region = baseTP.Region; |
|
|
|
|
this.Attributes.AddRange(baseTP.Attributes); |
|
|
|
|
Freeze(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override bool? IsReferenceType(ITypeResolveContext context) |
|
|
|
|
{ |
|
|
|
|
bool? result = baseTp.IsReferenceType(context); |
|
|
|
|
if (result != null) |
|
|
|
|
return result; |
|
|
|
|
IType effectiveBaseClass = baseTp.GetEffectiveBaseClass(context); |
|
|
|
|
return IsReferenceTypeHelper(effectiveBaseClass); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override IEnumerable<IType> GetEffectiveInterfaceSet(ITypeResolveContext context) |
|
|
|
|
{ |
|
|
|
|
return baseTp.GetEffectiveInterfaceSet(context).Select(i => i.AcceptVisitor(substitution)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override IType GetEffectiveBaseClass(ITypeResolveContext context) |
|
|
|
|
{ |
|
|
|
|
return baseTp.GetEffectiveBaseClass(context).AcceptVisitor(substitution); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override ITypeParameterConstraints GetConstraints(ITypeResolveContext context) |
|
|
|
|
{ |
|
|
|
|
return baseTp.GetConstraints(context).ApplySubstitution(substitution); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|