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)