Browse Source

SpecializedMethod: Perform type substitution in the type parameter constraints.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
18e088e688
  1. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractTypeParameter.cs
  2. 8
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs
  3. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs
  4. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs
  5. 22
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs
  6. 98
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs
  7. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs
  8. 1
      ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterWithInheritedConstraints.cs

2
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractTypeParameter.cs

@ -326,7 +326,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -326,7 +326,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override string ToString()
{
return this.ReflectionName;
return this.name;
}
}
}

8
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -28,7 +28,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// Default implementation of <see cref="ITypeParameter"/>.
/// </summary>
[Serializable]
public sealed class DefaultTypeParameter : AbstractTypeParameter, ISupportsInterning
public sealed class DefaultTypeParameter : AbstractTypeParameter
{
IList<ITypeReference> constraints;
@ -152,6 +152,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -152,6 +152,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.HasDefaultConstructorConstraint, this.HasReferenceTypeConstraint, this.HasValueTypeConstraint);
}
/*
* Interning for type parameters is disabled; we can't intern cyclic structures as might
* occur in the constraints, and incomplete interning is dangerous for type parameters
* as we use reference equality.
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
// protect against cyclic constraints
@ -180,6 +184,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -180,6 +184,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return base.EqualsForInterning(o)
&& this.constraints == o.constraints
&& this.flags == o.flags;
}
}*/
}
}

4
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs

@ -31,12 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,12 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
: base(declaringType, eventDefinition)
{
this.eventDefinition = eventDefinition;
Initialize(GetSubstitution(declaringType), null);
}
internal SpecializedEvent(IType declaringType, IEvent eventDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, eventDefinition, substitution, context)
: base(declaringType, eventDefinition)
{
this.eventDefinition = eventDefinition;
Initialize(substitution, context);
}
public bool CanAdd {

4
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs

@ -31,12 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,12 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
: base(declaringType, fieldDefinition)
{
this.fieldDefinition = fieldDefinition;
Initialize(GetSubstitution(declaringType), null);
}
internal SpecializedField(IType declaringType, IField fieldDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, fieldDefinition, substitution, context)
: base(declaringType, fieldDefinition)
{
this.fieldDefinition = fieldDefinition;
Initialize(substitution, context);
}
public bool IsReadOnly {

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

@ -29,14 +29,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -29,14 +29,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
readonly IType declaringType;
readonly IMember memberDefinition;
readonly ITypeReference returnType;
ITypeReference returnType;
protected SpecializedMember(IType declaringType, IMember memberDefinition)
: this(declaringType, memberDefinition, GetSubstitution(declaringType), null)
{
}
internal SpecializedMember(IType declaringType, IMember memberDefinition, TypeVisitor substitution, ITypeResolveContext context)
{
if (declaringType == null)
throw new ArgumentNullException("declaringType");
@ -45,6 +40,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -45,6 +40,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.declaringType = declaringType;
this.memberDefinition = memberDefinition;
}
protected virtual void Initialize(TypeVisitor substitution, ITypeResolveContext context)
{
this.returnType = Substitute(memberDefinition.ReturnType, substitution, context);
}
@ -233,17 +232,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -233,17 +232,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public abstract class SpecializedParameterizedMember : SpecializedMember, IParameterizedMember
{
readonly IList<IParameter> parameters;
IList<IParameter> parameters;
protected SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition)
: this(declaringType, memberDefinition, GetSubstitution(declaringType), null)
: base(declaringType, memberDefinition)
{
}
internal SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, memberDefinition, substitution, context)
protected override void Initialize(TypeVisitor substitution, ITypeResolveContext context)
{
var paramDefs = memberDefinition.Parameters;
base.Initialize(substitution, context);
var paramDefs = ((IParameterizedMember)this.MemberDefinition).Parameters;
if (paramDefs.Count == 0) {
this.parameters = EmptyList<IParameter>.Instance;
} else {

98
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs

@ -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);
}
}
}
}

4
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs

@ -31,12 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,12 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
: base(declaringType, propertyDefinition)
{
this.propertyDefinition = propertyDefinition;
Initialize(GetSubstitution(declaringType), null);
}
internal SpecializedProperty(IType declaringType, IProperty propertyDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, propertyDefinition, substitution, context)
: base(declaringType, propertyDefinition)
{
this.propertyDefinition = propertyDefinition;
Initialize(substitution, context);
}
public bool CanGet {

1
ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterWithInheritedConstraints.cs

@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// <summary>
/// Represents a type parameter that inherits its constraints from the overridden method in the base class.
/// </summary>
[Serializable]
public sealed class TypeParameterWithInheritedConstraints : AbstractTypeParameter
{
readonly IMethod parentMethod;

Loading…
Cancel
Save