diff --git a/src/Main/Base/Project/Src/Services/AmbienceService/NetAmbience.cs b/src/Main/Base/Project/Src/Services/AmbienceService/NetAmbience.cs index 94107d5910..8a7689dadd 100644 --- a/src/Main/Base/Project/Src/Services/AmbienceService/NetAmbience.cs +++ b/src/Main/Base/Project/Src/Services/AmbienceService/NetAmbience.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.SharpDevelop builder.Append('<'); for (int i = 0; i < c.TypeParameters.Count; ++i) { if (i > 0) builder.Append(", "); - builder.Append(c.TypeParameters[i].Name); + builder.Append(ConvertTypeParameter(c.TypeParameters[i])); } builder.Append('>'); } @@ -176,6 +176,14 @@ namespace ICSharpCode.SharpDevelop return builder.ToString(); } + string ConvertTypeParameter(ITypeParameter tp) + { + if (tp.BoundTo != null) + return Convert(tp.BoundTo); + else + return tp.Name; + } + public override string Convert(IMethod m) { StringBuilder builder = new StringBuilder(); @@ -195,7 +203,7 @@ namespace ICSharpCode.SharpDevelop builder.Append('<'); for (int i = 0; i < m.TypeParameters.Count; ++i) { if (i > 0) builder.Append(", "); - builder.Append(m.TypeParameters[i].Name); + builder.Append(ConvertTypeParameter(m.TypeParameters[i])); } builder.Append('>'); } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj index ce66364903..f4deb115bc 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj @@ -72,6 +72,7 @@ + diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs index 8600134989..a75d7ef70a 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs @@ -160,7 +160,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp builder.Append('<'); for (int i = 0; i < c.TypeParameters.Count; ++i) { if (i > 0) builder.Append(", "); - builder.Append(c.TypeParameters[i].Name); + builder.Append(ConvertTypeParameter(c.TypeParameters[i])); } builder.Append('>'); } @@ -416,7 +416,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp builder.Append('<'); for (int i = 0; i < m.TypeParameters.Count; ++i) { if (i > 0) builder.Append(", "); - builder.Append(m.TypeParameters[i].Name); + builder.Append(ConvertTypeParameter(m.TypeParameters[i])); } builder.Append('>'); } @@ -453,6 +453,14 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp return builder.ToString(); } + string ConvertTypeParameter(ITypeParameter tp) + { + if (tp.BoundTo != null) + return Convert(tp.BoundTo); + else + return tp.Name; + } + public override string ConvertEnd(IMethod m) { return "}"; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/OverloadResolution.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/OverloadResolution.cs index b3775d62c6..0ba140cbc3 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/OverloadResolution.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/OverloadResolution.cs @@ -151,16 +151,28 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp if (!success) { candidate.Status = CandidateStatus.TypeInferenceFailed; } - if (typeArguments != null) { - // apply inferred type arguments - method = (IMethod)method.CreateSpecializedMember(); - method.ReturnType = ConstructedReturnType.TranslateType(method.ReturnType, typeArguments, true); - for (int i = 0; i < method.Parameters.Count; ++i) { - method.Parameters[i].ReturnType = ConstructedReturnType.TranslateType(method.Parameters[i].ReturnType, typeArguments, true); - } - candidate.Method = method; - } + candidate.Method = ApplyTypeArgumentsToMethod(method, typeArguments); + } + } + } + + static IMethod ApplyTypeArgumentsToMethod(IMethod genericMethod, IList typeArguments) + { + if (typeArguments != null && typeArguments.Count > 0) { + // apply inferred type arguments + IMethod method = (IMethod)genericMethod.CreateSpecializedMember(); + method.ReturnType = ConstructedReturnType.TranslateType(method.ReturnType, typeArguments, true); + for (int i = 0; i < method.Parameters.Count; ++i) { + method.Parameters[i].ReturnType = ConstructedReturnType.TranslateType(method.Parameters[i].ReturnType, typeArguments, true); + } + for (int i = 0; i < Math.Min(typeArguments.Count, method.TypeParameters.Count); i++) { + var tp = new BoundTypeParameter(method.TypeParameters[i], method.DeclaringType, method); + tp.BoundTo = typeArguments[i]; + method.TypeParameters[i] = tp; } + return method; + } else { + return genericMethod; } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/BoundTypeParameter.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/BoundTypeParameter.cs new file mode 100644 index 0000000000..8bbeda8915 --- /dev/null +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/BoundTypeParameter.cs @@ -0,0 +1,95 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.SharpDevelop.Dom +{ + /// + /// A type parameter that was bound to a concrete type. + /// + public sealed class BoundTypeParameter : AbstractFreezable, ITypeParameter + { + readonly ITypeParameter baseTypeParameter; + readonly IMethod owningMethod; + readonly IClass owningClass; + IReturnType boundTo; + + public BoundTypeParameter(ITypeParameter baseTypeParameter, IClass owningClass) + : this(baseTypeParameter, owningClass, null) + { + } + + public BoundTypeParameter(ITypeParameter baseTypeParameter, IClass owningClass, IMethod owningMethod) + { + if (owningClass == null) + throw new ArgumentNullException("owningClass"); + if (baseTypeParameter == null) + throw new ArgumentNullException("baseTypeParameter"); + this.baseTypeParameter = baseTypeParameter; + this.owningMethod = owningMethod; + this.owningClass = owningClass; + } + + protected override void FreezeInternal() + { + base.FreezeInternal(); + baseTypeParameter.Freeze(); + owningMethod.Freeze(); + owningClass.Freeze(); + } + + public string Name { + get { return baseTypeParameter.Name; } + } + + public int Index { + get { return baseTypeParameter.Index; } + } + + public IList Attributes { + get { return baseTypeParameter.Attributes; } + } + + public IMethod Method { + get { return owningMethod; } + } + + public IClass Class { + get { return owningClass; } + } + + public IList Constraints { + get { return baseTypeParameter.Constraints; } + } + + public bool HasConstructableConstraint { + get { return baseTypeParameter.HasConstructableConstraint; } + } + + public bool HasReferenceTypeConstraint { + get { return baseTypeParameter.HasReferenceTypeConstraint; } + } + + public bool HasValueTypeConstraint { + get { return baseTypeParameter.HasValueTypeConstraint; } + } + + public IReturnType BoundTo { + get { return boundTo; } + set { + CheckBeforeMutation(); + boundTo = value; + } + } + + public ITypeParameter UnboundTypeParameter { + get { return baseTypeParameter.UnboundTypeParameter; } + } + } +} diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs index 0597c51a0e..bab90c8a7e 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs @@ -82,7 +82,7 @@ namespace ICSharpCode.SharpDevelop.Dom { DefaultMethod p = new DefaultMethod(Name, ReturnType, Modifiers, Region, BodyRegion, DeclaringType); p.parameters = DefaultParameter.Clone(this.Parameters); - p.typeParameters = this.typeParameters; + p.typeParameters = new List(this.typeParameters); p.CopyDocumentationFrom(this); p.documentationTag = DocumentationTag; p.isExtensionMethod = this.isExtensionMethod; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultTypeParameter.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultTypeParameter.cs index 37d0095e42..8fe4a5f7f0 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultTypeParameter.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultTypeParameter.cs @@ -17,10 +17,10 @@ namespace ICSharpCode.SharpDevelop.Dom { public static readonly IList EmptyTypeParameterList = EmptyList.Instance; - string name; - IMethod method; - IClass targetClass; - int index; + readonly string name; + readonly IMethod method; + readonly IClass targetClass; + readonly int index; IList constraints = new List(); protected override void FreezeInternal() @@ -178,5 +178,21 @@ namespace ICSharpCode.SharpDevelop.Dom } return c; } + + /// + /// Gets the type that was used to bind this type parameter. + /// This property returns null for generic methods/classes, it + /// is non-null only for constructed versions of generic methods. + /// + public virtual IReturnType BoundTo { + get { return null; } + } + + /// + /// If this type parameter was bound, returns the unbound version of it. + /// + public virtual ITypeParameter UnboundTypeParameter { + get { return this; } + } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ITypeParameter.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ITypeParameter.cs index 3eb06ca517..7e3df55fca 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ITypeParameter.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ITypeParameter.cs @@ -20,6 +20,9 @@ namespace ICSharpCode.SharpDevelop.Dom /// string Name { get; } + /// + /// Gets the index of the type parameter in the type parameter list of the owning method/class. + /// int Index { get; } IList Attributes { get; } @@ -35,7 +38,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// When the type parameter is defined for a method, this is the class containing /// that method. /// - IClass Class { get; } + IClass Class { get; } /// /// Gets the contraints of this type parameter. @@ -56,5 +59,17 @@ namespace ICSharpCode.SharpDevelop.Dom /// Gets if the type parameter has the 'struct' constraint. /// bool HasValueTypeConstraint { get; } + + /// + /// Gets the type that was used to bind this type parameter. + /// This property returns null for generic methods/classes, it + /// is non-null only for constructed versions of generic methods. + /// + IReturnType BoundTo { get; } + + /// + /// If this type parameter was bound, returns the unbound version of it. + /// + ITypeParameter UnboundTypeParameter { get; } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetAmbience.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetAmbience.cs index 8c429203af..ffa6375df2 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetAmbience.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetAmbience.cs @@ -151,7 +151,7 @@ namespace ICSharpCode.SharpDevelop.Dom.VBNet builder.Append("(Of "); for (int i = 0; i < c.TypeParameters.Count; ++i) { if (i > 0) builder.Append(", "); - builder.Append(c.TypeParameters[i].Name); + builder.Append(ConvertTypeParameter(c.TypeParameters[i])); } builder.Append(')'); } @@ -428,7 +428,7 @@ namespace ICSharpCode.SharpDevelop.Dom.VBNet builder.Append("(Of "); for (int i = 0; i < m.TypeParameters.Count; ++i) { if (i > 0) builder.Append(", "); - builder.Append(m.TypeParameters[i].Name); + builder.Append(ConvertTypeParameter(m.TypeParameters[i])); } builder.Append(')'); } @@ -457,6 +457,14 @@ namespace ICSharpCode.SharpDevelop.Dom.VBNet return builder.ToString(); } + string ConvertTypeParameter(ITypeParameter tp) + { + if (tp.BoundTo != null) + return Convert(tp.BoundTo); + else + return tp.Name; + } + public override string ConvertEnd(IMethod m) { if (m == null)