Browse Source

Fix type inference and overload resolution when a class type parameter gets substituted by a method type parameter.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
c9c204439f
  1. 15
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs
  2. 21
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs
  3. 27
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  4. 28
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs
  5. 158
      ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs
  6. 66
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  7. 22
      ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs
  8. 26
      ICSharpCode.NRefactory/CSharp/Resolver/InvocationResolveResult.cs
  9. 2
      ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs
  10. 63
      ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs
  11. 3
      ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs
  12. 2
      ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs
  13. 16
      ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs
  14. 63
      ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs
  15. 2
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  16. 27
      ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs
  17. 4
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  18. 6
      ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs
  19. 39
      ICSharpCode.NRefactory/TypeSystem/IType.cs
  20. 10
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs
  21. 12
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs
  22. 81
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs
  23. 65
      ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs
  24. 57
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs
  25. 53
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs
  26. 282
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs
  27. 103
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs
  28. 66
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs
  29. 101
      ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs
  30. 5
      ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs
  31. 183
      ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs

15
ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

@ -17,7 +17,9 @@ @@ -17,7 +17,9 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -279,5 +281,18 @@ class DerivedClass : MiddleClass { @@ -279,5 +281,18 @@ class DerivedClass : MiddleClass {
InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName);
}
[Test]
public void SubstituteClassAndMethodTypeParametersAtOnce()
{
string program = @"class C<X> { static void M<T>(X a, T b) { $C<T>.M(b, a)$; } }";
var rr = Resolve<InvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
var m = (SpecializedMethod)rr.Member;
Assert.AreEqual("X", m.TypeArguments.Single().Name);
Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name);
Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name);
}
}
}

21
ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -290,6 +291,26 @@ class TestClass { @@ -290,6 +291,26 @@ class TestClass {
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
}
[Test]
public void ConvertAllInGenericMethod()
{
string program = @"using System;
class TestClass {
static void Method<T>(System.Collections.Generic.List<T> list) {
$list.ConvertAll(x => (int)x)$;
}
}";
var rr = Resolve<InvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
SpecializedMethod m = (SpecializedMethod)rr.Member;
Assert.AreEqual("System.Int32", m.TypeArguments[0].ReflectionName);
Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", m.Parameters[0].Type.Resolve(context).ReflectionName);
var crr = (ConversionResolveResult)rr.Arguments[0];
Assert.IsTrue(crr.Conversion.IsAnonymousFunctionConversion);
Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", crr.Type.ReflectionName);
}
/* TODO write test for this
class A
{

27
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -19,8 +19,8 @@ @@ -19,8 +19,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -496,7 +496,7 @@ namespace A.B { @@ -496,7 +496,7 @@ namespace A.B {
[Test]
public void InnerTypeResolve ()
public void InnerTypeResolve1 ()
{
string program = @"public class C<T> { public class Inner { } }
class TestClass {
@ -507,15 +507,19 @@ class TestClass { @@ -507,15 +507,19 @@ class TestClass {
";
TypeResolveResult trr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("C.Inner", trr.Type.FullName);
program = @"public class C<T> { public class D<S,U> { public class Inner { } }}
}
[Test]
public void InnerTypeResolve2 ()
{
string program = @"public class C<T> { public class D<S,U> { public class Inner { } }}
class TestClass {
void Test() {
$C<string>.D<int,TestClass>.Inner$ a;
}
}
";
trr = Resolve<TypeResolveResult>(program);
TypeResolveResult trr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("C.D.Inner", trr.Type.FullName);
}
@ -838,5 +842,18 @@ class B @@ -838,5 +842,18 @@ class B
var mrr = Resolve<MemberResolveResult>(program);
Assert.AreEqual("B.x", mrr.Member.FullName);
}
[Test]
public void SubstituteClassAndMethodTypeParametersAtOnce()
{
string program = @"class C<X> { static void M<T>(X a, T b) { $C<T>.M<X>$(b, a); } }";
var rr = Resolve<MethodGroupResolveResult>(program);
Assert.AreEqual("X", rr.TypeArguments.Single().Name);
var m = (SpecializedMethod)rr.Methods.Single();
Assert.AreSame(rr.TypeArguments.Single(), m.TypeArguments.Single());
Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name);
Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name);
}
}
}

28
ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

@ -175,7 +175,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -175,7 +175,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override IType GetInferredReturnType(IType[] parameterTypes)
{
Assert.AreEqual(expectedParameterTypes, parameterTypes);
Assert.AreEqual(expectedParameterTypes, parameterTypes, "Parameters types passed to " + this);
return inferredReturnType;
}
@ -216,6 +216,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -216,6 +216,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ti.InferTypeArguments(typeParameters, arguments, parameterTypes, out success));
Assert.IsTrue(success);
}
[Test]
public void ConvertAllLambdaInference()
{
ITypeParameter[] classTypeParameters = { new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T") };
ITypeParameter[] methodTypeParameters = { new DefaultTypeParameter(EntityType.Method, 0, "R") };
IType[] parameterTypes = {
new ParameterizedType(ctx.GetTypeDefinition(typeof(Converter<,>)),
new[] { classTypeParameters[0], methodTypeParameters[0] })
};
// Signature: List<T>.ConvertAll<R>(Converter<T, R> converter);
// Invocation: listOfString.ConvertAll(s => default(int));
ResolveResult[] arguments = {
new MockImplicitLambda(new[] { KnownTypeReference.String.Resolve(ctx) }, KnownTypeReference.Int32.Resolve(ctx))
};
IType[] classTypeArguments = {
KnownTypeReference.String.Resolve(ctx)
};
bool success;
Assert.AreEqual(
new [] { KnownTypeReference.Int32.Resolve(ctx) },
ti.InferTypeArguments(methodTypeParameters, arguments, parameterTypes, out success, classTypeArguments));
}
#endregion
#region FindTypeInBounds

158
ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs

@ -1,158 +0,0 @@ @@ -1,158 +0,0 @@
//
// StringBuilderOutputFormatter.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Text;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public class StringBuilderOutputFormatter : IOutputFormatter
{
readonly StringBuilder sb = new StringBuilder ();
int indentation;
bool needsIndent = true;
public int Length {
get {
WriteIndentation ();
return sb.Length;
}
}
public int Indentation {
get {
return this.indentation;
}
set {
indentation = value;
}
}
public string EolMarker {
get;
set;
}
public override string ToString ()
{
return sb.ToString ();
}
public void WriteIdentifier (string ident)
{
WriteIndentation ();
sb.Append (ident);
}
public void WriteKeyword (string keyword)
{
WriteIndentation ();
sb.Append (keyword);
}
public void WriteToken (string token)
{
WriteIndentation ();
sb.Append (token);
}
public void Space ()
{
WriteIndentation ();
sb.Append (' ');
}
public void OpenBrace (BraceStyle style)
{
WriteIndentation ();
sb.Append (' ');
sb.Append ('{');
Indent ();
NewLine ();
}
public void CloseBrace (BraceStyle style)
{
Unindent ();
WriteIndentation ();
sb.Append ('}');
}
void WriteIndentation ()
{
if (needsIndent) {
needsIndent = false;
for (int i = 0; i < indentation; i++) {
sb.Append ('\t');
}
}
}
public void NewLine ()
{
sb.Append (EolMarker);
needsIndent = true;
}
public void Indent ()
{
indentation++;
}
public void Unindent ()
{
indentation--;
}
public void WriteComment (CommentType commentType, string content)
{
WriteIndentation ();
switch (commentType) {
case CommentType.SingleLine:
sb.Append ("//");
sb.AppendLine (content);
break;
case CommentType.MultiLine:
sb.Append ("/*");
sb.Append (content);
sb.Append ("*/");
break;
case CommentType.Documentation:
sb.Append ("///");
sb.AppendLine (content);
break;
}
}
public virtual void StartNode (AstNode node)
{
}
public virtual void EndNode (AstNode node)
{
}
}
}

66
ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs

@ -344,7 +344,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -344,7 +344,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
IMember IMember.MemberDefinition {
get { return null; }
get { return this; }
}
IList<IExplicitInterfaceImplementation> IMember.InterfaceImplementations {
@ -1723,7 +1723,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1723,7 +1723,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new InvocationResolveResult(
null, lifted.nonLiftedOperator, lifted.ReturnType.Resolve(context),
r.GetArgumentsWithConversions(), r.BestCandidateErrors,
typeArguments: r.InferredTypeArguments,
isLiftedOperatorInvocation: true,
argumentToParameterMap: r.GetArgumentToParameterMap()
);
@ -2004,15 +2003,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2004,15 +2003,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
NamespaceResolveResult nrr = target as NamespaceResolveResult;
if (nrr != null) {
if (typeArguments.Count == 0) {
string fullName = NamespaceDeclaration.BuildQualifiedName(nrr.NamespaceName, identifier);
if (context.GetNamespace(fullName, StringComparer.Ordinal) != null)
return new NamespaceResolveResult(fullName);
}
ITypeDefinition def = context.GetTypeDefinition(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal);
if (def != null)
return new TypeResolveResult(def);
return ErrorResult;
return ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments);
}
if (SharedTypes.Dynamic.Equals(target.Type))
@ -2021,7 +2012,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2021,7 +2012,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
MemberLookup lookup = CreateMemberLookup();
ResolveResult result = lookup.Lookup(target, identifier, typeArguments, isInvocationTarget);
if (result is UnknownMemberResolveResult) {
var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments.Count);
var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments);
if (extensionMethods.Count > 0) {
return new MethodGroupResolveResult(target, identifier, EmptyList<IMethod>.Instance, typeArguments) {
extensionMethods = extensionMethods
@ -2039,6 +2030,36 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2039,6 +2030,36 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return result;
}
public ResolveResult ResolveMemberType(ResolveResult target, string identifier, IList<IType> typeArguments)
{
cancellationToken.ThrowIfCancellationRequested();
NamespaceResolveResult nrr = target as NamespaceResolveResult;
if (nrr != null) {
return ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments);
}
MemberLookup lookup = CreateMemberLookup();
return lookup.LookupType(target.Type, identifier, typeArguments);
}
ResolveResult ResolveMemberAccessOnNamespace(NamespaceResolveResult nrr, string identifier, IList<IType> typeArguments)
{
if (typeArguments.Count == 0) {
string fullName = NamespaceDeclaration.BuildQualifiedName(nrr.NamespaceName, identifier);
if (context.GetNamespace(fullName, StringComparer.Ordinal) != null)
return new NamespaceResolveResult(fullName);
}
ITypeDefinition def = context.GetTypeDefinition(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal);
if (def != null) {
if (typeArguments.Count > 0)
return new TypeResolveResult(new ParameterizedType(def, typeArguments));
else
return new TypeResolveResult(def);
}
return ErrorResult;
}
MemberLookup CreateMemberLookup()
{
return new MemberLookup(context, this.CurrentTypeDefinition, this.UsingScope != null ? this.UsingScope.ProjectContent : null);
@ -2047,9 +2068,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2047,9 +2068,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region GetExtensionMethods
/// <summary>
/// Gets the extension methods that are called 'name', and can be called with 'typeArgumentCount' explicit type arguments;
/// Gets the extension methods that are called 'name'
/// and are applicable with a first argument type of 'targetType'.
/// </summary>
/// <param name="targetType">Type of the 'this' argument</param>
/// <param name="name">Name of the extension method</param>
/// <param name="typeArguments">Explicitly provided type arguments.
/// An empty list will return all matching extension method definitions;
/// a non-empty list will return <see cref="SpecializedMethod"/>s for all extension methods
/// with the matching number of type parameters.</param>
/// <remarks>
/// The results are stored in nested lists because they are grouped by using scope.
/// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }",
@ -2059,13 +2086,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2059,13 +2086,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// new List { all extensions from SomeExtensions }
/// }
/// </remarks>
public List<List<IMethod>> GetExtensionMethods(IType targetType, string name, int typeArgumentCount)
public List<List<IMethod>> GetExtensionMethods(IType targetType, string name, IList<IType> typeArguments = null)
{
List<List<IMethod>> extensionMethodGroups = new List<List<IMethod>>();
foreach (var inputGroup in GetAllExtensionMethods()) {
List<IMethod> outputGroup = new List<IMethod>();
foreach (var method in inputGroup) {
if (method.Name == name && (typeArgumentCount == 0 || method.TypeParameters.Count == typeArgumentCount)) {
if (method.Name != name)
continue;
if (typeArguments != null && typeArguments.Count > 0) {
if (method.TypeParameters.Count != typeArguments.Count)
continue;
SpecializedMethod sm = new SpecializedMethod(method.DeclaringType, method, typeArguments);
// TODO: verify targetType
outputGroup.Add(sm);
} else {
// TODO: verify targetType
outputGroup.Add(method);
}

22
ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs

@ -310,6 +310,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -310,6 +310,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return Conversion.ImplicitPointerConversion;
return Conversion.None;
}
/// <summary>
/// Gets whether the type 'fromType' is convertible to 'toType'
/// using one of the conversions allowed when satisying constraints (§4.4.4)
/// </summary>
public bool IsConstraintConvertible(IType fromType, IType toType)
{
if (fromType == null)
throw new ArgumentNullException("fromType");
if (toType == null)
throw new ArgumentNullException("toType");
if (IdentityConversion(fromType, toType))
return true;
if (ImplicitReferenceConversion(fromType, toType))
return true;
if (BoxingConversion(fromType, toType) && !NullableType.IsNullable(fromType))
return true;
if (ImplicitTypeParameterConversion(fromType, toType))
return true;
return false;
}
#endregion
#region ExplicitConversion

26
ICSharpCode.NRefactory/CSharp/Resolver/InvocationResolveResult.cs

@ -31,7 +31,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -31,7 +31,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public class InvocationResolveResult : MemberResolveResult
{
public readonly OverloadResolutionErrors OverloadResolutionErrors;
public readonly IList<IType> TypeArguments;
public readonly IList<ResolveResult> Arguments;
@ -55,11 +54,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -55,11 +54,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public InvocationResolveResult(ResolveResult targetResult, OverloadResolution or, ITypeResolveContext context)
: base(
or.IsExtensionMethodInvocation ? null : targetResult,
or.BestCandidate,
GetReturnType(or, context))
or.GetBestCandidateWithSubstitutedTypeArguments(),
context)
{
this.OverloadResolutionErrors = or.BestCandidateErrors;
this.TypeArguments = or.InferredTypeArguments;
this.argumentToParameterMap = or.GetArgumentToParameterMap();
this.Arguments = or.GetArgumentsWithConversions();
@ -72,14 +70,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -72,14 +70,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult targetResult, IParameterizedMember member, IType returnType,
IList<ResolveResult> arguments,
OverloadResolutionErrors overloadResolutionErrors = OverloadResolutionErrors.None,
IList<IType> typeArguments = null,
bool isExtensionMethodInvocation = false, bool isExpandedForm = false,
bool isLiftedOperatorInvocation = false,
IList<int> argumentToParameterMap = null)
: base(targetResult, member, returnType)
{
this.OverloadResolutionErrors = overloadResolutionErrors;
this.TypeArguments = typeArguments ?? EmptyList<IType>.Instance;
this.Arguments = arguments ?? EmptyList<ResolveResult>.Instance;
this.IsExtensionMethodInvocation = isExtensionMethodInvocation;
this.IsExpandedForm = isExpandedForm;
@ -87,24 +83,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -87,24 +83,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.argumentToParameterMap = argumentToParameterMap;
}
static IType GetReturnType(OverloadResolution or, ITypeResolveContext context)
{
if (context == null)
throw new ArgumentNullException("context");
IType returnType;
if (or.BestCandidate.EntityType == EntityType.Constructor)
returnType = or.BestCandidate.DeclaringType;
else
returnType = or.BestCandidate.ReturnType.Resolve(context);
var typeArguments = or.InferredTypeArguments;
if (typeArguments.Count > 0)
return returnType.AcceptVisitor(new MethodTypeParameterSubstitution(typeArguments));
else
return returnType;
}
public override bool IsError {
get { return this.OverloadResolutionErrors != OverloadResolutionErrors.None; }
}

2
ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override string ToString()
{
return string.Format("[VariableResolveResult {0}]", variable);
return string.Format("[LocalResolveResult {0}]", variable);
}
}
}

63
ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs

@ -126,12 +126,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -126,12 +126,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
int typeArgumentCount = typeArguments.Count;
Predicate<ITypeDefinition> typeFilter = delegate (ITypeDefinition d) {
return d.TypeParameterCount == typeArgumentCount && d.Name == name && IsAccessible(d, true);
// inner types contain the type parameters of outer types. therefore this count has to been adjusted.
int correctedCount = d.TypeParameterCount - (d.DeclaringType != null ? d.DeclaringType.TypeParameterCount : 0);
return correctedCount == typeArgumentCount && d.Name == name && IsAccessible(d, true);
};
List<IType> types = declaringType.GetNestedTypes(context, typeFilter).ToList();
List<IType> types;
if (parameterizeResultType)
types = declaringType.GetNestedTypes(typeArguments, context, typeFilter).ToList();
else
types = declaringType.GetNestedTypes(context, typeFilter).ToList();
RemoveTypesHiddenByOtherTypes(types);
if (types.Count > 0)
return CreateTypeResolveResult(types[0], types.Count > 1, typeArguments, parameterizeResultType);
if (types.Count == 1)
return new TypeResolveResult(types[0]);
else if (types.Count > 1)
return new AmbiguousTypeResolveResult(types[0]);
else
return new UnknownMemberResolveResult(declaringType, name, typeArguments);
}
@ -156,24 +165,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -156,24 +165,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
ResolveResult CreateTypeResolveResult(IType returnedType, bool isAmbiguous, IList<IType> typeArguments, bool parameterizeResultType)
{
if (parameterizeResultType && typeArguments.Count > 0) {
// Complete the partial parameterization
ParameterizedType pt = returnedType as ParameterizedType;
if (pt != null) {
IType[] newTypeArguments = new IType[pt.TypeParameterCount];
pt.TypeArguments.CopyTo(newTypeArguments, 0);
typeArguments.CopyTo(newTypeArguments, newTypeArguments.Length - typeArguments.Count);
returnedType = new ParameterizedType(pt.GetDefinition(), newTypeArguments);
}
}
if (isAmbiguous)
return new AmbiguousTypeResolveResult(returnedType);
else
return new TypeResolveResult(returnedType);
}
/// <summary>
/// Performs a member lookup.
/// </summary>
@ -185,32 +176,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -185,32 +176,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
List<IType> types = new List<IType>();
List<IMember> members = new List<IMember>();
if (!isInvocation) {
// Consider nested types only if it's not an invocation. The type parameter count must match in this case.
// Consider nested types only if it's not an invocation.
// type.GetNestedTypes() is checking the type parameter count for an exact match.
Predicate<ITypeDefinition> typeFilter = delegate (ITypeDefinition d) {
// inner types contain the type parameters of outer types. therefore this count has to been adjusted.
int correctedCount = d.TypeParameterCount - (d.DeclaringType != null ? d.DeclaringType.TypeParameterCount : 0);
return correctedCount == typeArgumentCount && d.Name == name && IsAccessible(d, true);
return d.Name == name && IsAccessible(d, true);
};
types.AddRange(type.GetNestedTypes(context, typeFilter));
types.AddRange(type.GetNestedTypes(typeArguments, context, typeFilter));
}
bool allowProtectedAccess = IsProtectedAccessAllowed(type);
Predicate<IMember> memberFilter = delegate(IMember member) {
return !member.IsOverride && member.Name == name && IsAccessible(member, allowProtectedAccess);
};
if (typeArgumentCount == 0) {
Predicate<IMember> memberFilter = delegate(IMember member) {
return !member.IsOverride && member.Name == name && IsAccessible(member, allowProtectedAccess);
};
members.AddRange(type.GetMembers(context, memberFilter));
// Note: IsInvocable-checking cannot be done as part of the memberFilter;
// because it must be done after type substitution.
if (isInvocation)
members.RemoveAll(m => !IsInvocable(m, context));
} else {
// No need to check for isInvocation/isInvocable here:
// we filter out all non-methods
Predicate<IMethod> memberFilter = delegate(IMethod method) {
return method.TypeParameters.Count == typeArgumentCount
&& !method.IsOverride && method.Name == name && IsAccessible(method, allowProtectedAccess);
};
members.AddRange(type.GetMethods(context, memberFilter).SafeCast<IMethod, IMember>());
members.AddRange(type.GetMethods(typeArguments, context, memberFilter));
}
// TODO: can't members also hide types?
@ -269,7 +257,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -269,7 +257,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (types.Count > 0) {
bool isAmbiguous = !(types.Count == 1 && members.Count == 0);
return CreateTypeResolveResult(types[0], isAmbiguous, typeArguments, true);
if (isAmbiguous)
return new AmbiguousTypeResolveResult(types[0]);
else
return new TypeResolveResult(types[0]);
}
if (members.Count == 0)
return new UnknownMemberResolveResult(type, name, typeArguments);

3
ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs

@ -51,7 +51,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -51,7 +51,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.constantValue = constantValue;
}
public MemberResolveResult(ResolveResult targetResult, IMember member, ITypeResolveContext context) : base(member.ReturnType.Resolve(context))
public MemberResolveResult(ResolveResult targetResult, IMember member, ITypeResolveContext context)
: base(member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType.Resolve(context))
{
this.targetResult = targetResult;
this.member = member;

2
ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs

@ -67,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -67,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
for (int i = 0; i < typeArgs.Length; i++) {
typeArgs[i] = typeArguments[i].Resolve(context);
}
return r.ResolveMemberAccess(targetRR, identifier, typeArgs, false);
return r.ResolveMemberType(targetRR, identifier, typeArgs);
}
public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context)

16
ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs

@ -31,8 +31,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -31,8 +31,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public class MethodGroupResolveResult : ResolveResult
{
readonly ReadOnlyCollection<IMethod> methods;
readonly ReadOnlyCollection<IType> typeArguments;
readonly IList<IMethod> methods;
readonly IList<IType> typeArguments;
readonly ResolveResult targetResult;
readonly string methodName;
@ -44,8 +44,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -44,8 +44,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new ArgumentNullException("methods");
this.targetResult = targetResult;
this.methodName = methodName;
this.methods = new ReadOnlyCollection<IMethod>(methods);
this.typeArguments = typeArguments != null ? new ReadOnlyCollection<IType>(typeArguments) : EmptyList<IType>.Instance;
this.methods = methods;
this.typeArguments = typeArguments ?? EmptyList<IType>.Instance;
}
/// <summary>
@ -73,14 +73,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -73,14 +73,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets the methods that were found.
/// This list does not include extension methods.
/// </summary>
public ReadOnlyCollection<IMethod> Methods {
public IList<IMethod> Methods {
get { return methods; }
}
/// <summary>
/// Gets the type arguments that were explicitly provided.
/// </summary>
public ReadOnlyCollection<IType> TypeArguments {
public IList<IType> TypeArguments {
get { return typeArguments; }
}
@ -104,7 +104,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -104,7 +104,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
UsingScope oldUsingScope = resolver.UsingScope;
try {
resolver.UsingScope = usingScope;
extensionMethods = resolver.GetExtensionMethods(this.TargetType, methodName, typeArguments.Count);
extensionMethods = resolver.GetExtensionMethods(this.TargetType, methodName, typeArguments);
} finally {
resolver.UsingScope = oldUsingScope;
resolver = null;
@ -173,7 +173,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -173,7 +173,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
}
Log.WriteLine("Overload resolution finished, best candidate is {0}.", or.BestCandidate);
Log.WriteLine("Overload resolution finished, best candidate is {0}.", or.GetBestCandidateWithSubstitutedTypeArguments());
return or;
}

63
ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs

@ -53,7 +53,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -53,7 +53,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public IType[] InferredTypes;
public IList<IParameter> Parameters { get { return Member.Parameters; } }
/// <summary>
/// Gets the original member parameters (before any substitution!)
/// </summary>
public readonly IList<IParameter> Parameters;
/// <summary>
/// Conversions applied to the arguments.
@ -86,7 +89,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -86,7 +89,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
this.Member = member;
this.IsExpandedForm = isExpanded;
this.ParameterTypes = new IType[member.Parameters.Count];
this.Parameters = ((IParameterizedMember)member.MemberDefinition).Parameters;
this.ParameterTypes = new IType[this.Parameters.Count];
}
public void AddError(OverloadResolutionErrors newError)
@ -227,8 +231,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -227,8 +231,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
} else {
// named argument
for (int j = 0; j < candidate.Member.Parameters.Count; j++) {
if (argumentNames[i] == candidate.Member.Parameters[j].Name) {
for (int j = 0; j < candidate.Parameters.Count; j++) {
if (argumentNames[i] == candidate.Parameters[j].Name) {
candidate.ArgumentToParameterMap[i] = j;
}
}
@ -250,6 +254,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -250,6 +254,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
return;
}
ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType;
IList<IType> classTypeArguments;
if (parameterizedDeclaringType != null) {
classTypeArguments = parameterizedDeclaringType.TypeArguments;
} else {
classTypeArguments = null;
}
// The method is generic:
if (explicitlyGivenTypeArguments != null) {
if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count) {
@ -268,12 +279,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -268,12 +279,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} else {
TypeInference ti = new TypeInference(context, conversions);
bool success;
candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success);
candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments);
if (!success)
candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed);
}
// Now substitute in the formal parameters:
var substitution = new ConstraintValidatingSubstitution(candidate.InferredTypes, this);
var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this);
for (int i = 0; i < candidate.ParameterTypes.Length; i++) {
candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution);
}
@ -281,15 +292,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -281,15 +292,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint);
}
sealed class ConstraintValidatingSubstitution : MethodTypeParameterSubstitution
sealed class ConstraintValidatingSubstitution : TypeParameterSubstitution
{
readonly OverloadResolution overloadResolution;
readonly Conversions conversions;
readonly ITypeResolveContext context;
public bool ConstraintsValid = true;
public ConstraintValidatingSubstitution(IType[] typeArguments, OverloadResolution overloadResolution)
: base(typeArguments)
public ConstraintValidatingSubstitution(IList<IType> classTypeArguments, IList<IType> methodTypeArguments, OverloadResolution overloadResolution)
: base(classTypeArguments, methodTypeArguments)
{
this.overloadResolution = overloadResolution;
this.context = overloadResolution.context;
this.conversions = overloadResolution.conversions;
}
public override IType VisitParameterizedType(ParameterizedType type)
@ -312,11 +325,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -312,11 +325,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
break;
}
if (tp.HasReferenceTypeConstraint) {
if (typeArg.IsReferenceType(overloadResolution.context) != true)
if (typeArg.IsReferenceType(context) != true)
ConstraintsValid = false;
}
if (tp.HasValueTypeConstraint) {
if (!NullableType.IsNonNullableValueType(typeArg, overloadResolution.context))
if (!NullableType.IsNonNullableValueType(typeArg, context))
ConstraintsValid = false;
}
if (tp.HasDefaultConstructorConstraint) {
@ -324,13 +337,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -324,13 +337,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (def != null && def.IsAbstract)
ConstraintsValid = false;
ConstraintsValid &= typeArg.GetConstructors(
overloadResolution.context,
context,
m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public
).Any();
}
foreach (IType constraintType in tp.Constraints) {
IType c = newParameterizedType.SubstituteInType(constraintType);
ConstraintsValid &= overloadResolution.IsConstraintConvertible(typeArg, c);
ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c);
}
}
}
@ -338,12 +351,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -338,12 +351,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return newType;
}
}
bool IsConstraintConvertible(IType typeArg, IType constraintType)
{
// TODO: this isn't exactly correct; not all kinds of implicit conversions are allowed here
return conversions.ImplicitConversion(typeArg, constraintType);
}
#endregion
#region CheckApplicability
@ -604,7 +611,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -604,7 +611,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public IList<IType> InferredTypeArguments {
get {
if (bestCandidate != null && bestCandidate.InferredTypes != null)
return Array.AsReadOnly(bestCandidate.InferredTypes);
return bestCandidate.InferredTypes;
else
return EmptyList<IType>.Instance;
}
@ -657,5 +664,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -657,5 +664,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
return args;
}
public IParameterizedMember GetBestCandidateWithSubstitutedTypeArguments()
{
if (bestCandidate == null)
return null;
IMethod method = bestCandidate.Member as IMethod;
if (method != null && method.TypeParameters.Count > 0) {
return new SpecializedMethod(method.DeclaringType, (IMethod)method.MemberDefinition, bestCandidate.InferredTypes);
} else {
return bestCandidate.Member;
}
}
}
}

2
ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs

@ -2231,7 +2231,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2231,7 +2231,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
var typeArguments = GetTypeArguments(memberType.TypeArguments);
return resolver.ResolveMemberAccess(target, memberType.MemberName, typeArguments);
return resolver.ResolveMemberType(target, memberType.MemberName, typeArguments);
}
public override ResolveResult VisitComposedType(ComposedType composedType, object data)

27
ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs

@ -87,9 +87,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -87,9 +87,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IType[] parameterTypes;
ResolveResult[] arguments;
bool[,] dependencyMatrix;
IList<IType> classTypeArguments;
#region InferTypeArguments (main function)
public IType[] InferTypeArguments(IList<ITypeParameter> typeParameters, IList<ResolveResult> arguments, IList<IType> parameterTypes, out bool success)
/// <summary>
/// Performs type inference.
/// </summary>
/// <param name="typeParameters">The method type parameters that should be inferred.</param>
/// <param name="arguments">The arguments passed to the method.</param>
/// <param name="parameterTypes">The parameter types of the method.</param>
/// <param name="success">Out: whether type inference was successful</param>
/// <param name="classTypeArguments">
/// Class type arguments. These are substituted for class type parameters in the formal parameter types
/// when inferring a method group or lambda.
/// </param>
/// <returns>The inferred type arguments.</returns>
public IType[] InferTypeArguments(IList<ITypeParameter> typeParameters, IList<ResolveResult> arguments, IList<IType> parameterTypes, out bool success, IList<IType> classTypeArguments = null)
{
if (typeParameters == null)
throw new ArgumentNullException("typeParameters");
@ -102,6 +115,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -102,6 +115,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
for (int i = 0; i < this.typeParameters.Length; i++) {
if (i != typeParameters[i].Index)
throw new ArgumentException("Type parameter has wrong index");
if (typeParameters[i].OwnerType != EntityType.Method)
throw new ArgumentException("Type parameter must be owned by a method");
this.typeParameters[i] = new TP(typeParameters[i]);
}
this.parameterTypes = new IType[Math.Min(arguments.Count, parameterTypes.Count)];
@ -112,6 +127,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -112,6 +127,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.arguments[i] = arguments[i];
this.parameterTypes[i] = parameterTypes[i];
}
this.classTypeArguments = classTypeArguments;
Log.WriteLine("Type Inference");
Log.WriteLine(" Signature: M<" + string.Join<TP>(", ", this.typeParameters) + ">"
+ "(" + string.Join<IType>(", ", this.parameterTypes) + ")");
@ -137,6 +153,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -137,6 +153,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.parameterTypes = null;
this.arguments = null;
this.dependencyMatrix = null;
this.classTypeArguments = null;
}
/// <summary>
@ -443,7 +460,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -443,7 +460,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (lrr.IsImplicitlyTyped) {
if (m.Parameters.Count != lrr.Parameters.Count)
return; // cannot infer due to mismatched parameter lists
MethodTypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
IType[] inferredParameterTypes = new IType[m.Parameters.Count];
for (int i = 0; i < inferredParameterTypes.Length; i++) {
IType parameterType = m.Parameters[i].Type.Resolve(context);
@ -466,7 +483,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -466,7 +483,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IMethod m = GetDelegateOrExpressionTreeSignature(t);
if (m != null) {
ResolveResult[] args = new ResolveResult[m.Parameters.Count];
MethodTypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
for (int i = 0; i < args.Length; i++) {
IParameter param = m.Parameters[i];
IType parameterType = param.Type.Resolve(context);
@ -494,13 +511,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -494,13 +511,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
MethodTypeParameterSubstitution GetSubstitutionForFixedTPs()
TypeParameterSubstitution GetSubstitutionForFixedTPs()
{
IType[] fixedTypes = new IType[typeParameters.Length];
for (int i = 0; i < fixedTypes.Length; i++) {
fixedTypes[i] = typeParameters[i].FixedTo ?? SharedTypes.UnknownType;
}
return new MethodTypeParameterSubstitution(fixedTypes);
return new TypeParameterSubstitution(classTypeArguments, fixedTypes);
}
#endregion

4
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -246,7 +246,7 @@ @@ -246,7 +246,7 @@
<Compile Include="TypeSystem\Implementation\DefaultTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\GetClassTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\CompositeTypeResolveContext.cs" />
<Compile Include="TypeSystem\Implementation\MethodTypeParameterSubstitution.cs" />
<Compile Include="TypeSystem\Implementation\TypeParameterSubstitution.cs" />
<Compile Include="TypeSystem\Implementation\NestedTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\ProxyTypeResolveContext.cs" />
<Compile Include="TypeSystem\Implementation\DefaultTypeDefinition.cs" />
@ -255,6 +255,7 @@ @@ -255,6 +255,7 @@
<Compile Include="TypeSystem\Implementation\SimpleProjectContent.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedEvent.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedField.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedMember.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedMethod.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedProperty.cs" />
<Compile Include="TypeSystem\Implementation\SubstitutionTypeReference.cs" />
@ -380,7 +381,6 @@ @@ -380,7 +381,6 @@
<Compile Include="CSharp\Refactoring\NodeSelectionAction.cs" />
<Compile Include="CSharp\Refactoring\RefactoringContext.cs" />
<Compile Include="CSharp\Refactoring\Script.cs" />
<Compile Include="CSharp\Refactoring\StringBuilderOutputFormatter.cs" />
<Compile Include="CSharp\Refactoring\TextReplaceAction.cs" />
<Compile Include="CSharp\Refactoring\ContextAction\AddAnotherAccessor.cs" />
<Compile Include="CSharp\Refactoring\ContextAction\CheckIfParameterIsNull.cs" />

6
ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs

@ -209,11 +209,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -209,11 +209,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (method.Name == "Invoke") {
ParameterizedType pt = type as ParameterizedType;
if (pt != null) {
SpecializedMethod m = new SpecializedMethod(method);
m.SetDeclaringType(pt);
var substitution = pt.GetSubstitution();
m.SubstituteTypes(t => SubstitutionTypeReference.Create(t, substitution));
return m;
return new SpecializedMethod(pt, method);
}
return method;
}

39
ICSharpCode.NRefactory/TypeSystem/IType.cs

@ -125,6 +125,22 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -125,6 +125,22 @@ namespace ICSharpCode.NRefactory.TypeSystem
// Derived.GetNestedTypes() = Base+Nested<`1, >
// Here `1 refers to B, and there's no way to return X as it would collide with B.
/// <summary>
/// Gets inner classes (including inherited inner classes)
/// that have <c>typeArguments.Count</c> additional type parameters.
/// </summary>
/// <param name="typeArguments">The type arguments passed to the inner class</param>
/// <param name="context">The context used for resolving type references</param>
/// <param name="filter">The filter used to select which types to return.
/// The filter is tested on the original type definitions (before parameterization).</param>
/// <remarks>
/// Type parameters belonging to the outer class will have the value copied from the outer type
/// if it is a parameterized type. Otherwise, those existing type parameters will be self-parameterized,
/// and thus 'leaked' to the caller in the same way the GetMembers() method does not specialize members
/// from an <see cref="ITypeDefinition"/> and 'leaks' type parameters in member signatures.
/// </remarks>
IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter = null);
/// <summary>
/// Gets all instance constructors for this type.
/// </summary>
@ -134,7 +150,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -134,7 +150,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <remarks>
/// This list does not include constructors in base classes or static constructors.
/// For methods on parameterized types, type substitution will be performed on the method signature,
/// and the appriopriate <see cref="SpecializedMethod"/> will be returned.
/// and the appropriate <see cref="SpecializedMethod"/> will be returned.
/// </remarks>
IEnumerable<IMethod> GetConstructors(ITypeResolveContext context, Predicate<IMethod> filter = null);
@ -147,10 +163,23 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -147,10 +163,23 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <remarks>
/// The list does not include constructors.
/// For methods on parameterized types, type substitution will be performed on the method signature,
/// and the appriopriate <see cref="SpecializedMethod"/> will be returned.
/// and the appropriate <see cref="SpecializedMethod"/> will be returned.
/// </remarks>
IEnumerable<IMethod> GetMethods(ITypeResolveContext context, Predicate<IMethod> filter = null);
/// <summary>
/// Gets all generic methods that can be called on this type with the specified type arguments.
/// </summary>
/// <param name="typeArguments">The type arguments used for the call.</param>
/// <param name="context">The context used for resolving type references</param>
/// <param name="filter">The filter used to select which methods to return.
/// The filter is tested on the original method definitions (before specialization).</param>
/// <remarks>
/// Type substitution will be performed on the method signature, creating a <see cref="SpecializedMethod"/>
/// with the specified type arguments.
/// </remarks>
IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter = null);
/// <summary>
/// Gets all properties that can be called on this type.
/// </summary>
@ -159,7 +188,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -159,7 +188,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// The filter is tested on the original property definitions (before specialization).</param>
/// <remarks>
/// For properties on parameterized types, type substitution will be performed on the property signature,
/// and the appriopriate <see cref="SpecializedProperty"/> will be returned.
/// and the appropriate <see cref="SpecializedProperty"/> will be returned.
/// </remarks>
IEnumerable<IProperty> GetProperties(ITypeResolveContext context, Predicate<IProperty> filter = null);
@ -171,7 +200,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -171,7 +200,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// The filter is tested on the original field definitions (before specialization).</param>
/// <remarks>
/// For fields on parameterized types, type substitution will be performed on the field's return type,
/// and the appriopriate <see cref="SpecializedField"/> will be returned.
/// and the appropriate <see cref="SpecializedField"/> will be returned.
/// </remarks>
IEnumerable<IField> GetFields(ITypeResolveContext context, Predicate<IField> filter = null);
@ -183,7 +212,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -183,7 +212,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// The filter is tested on the original event definitions (before specialization).</param>
/// <remarks>
/// For fields on parameterized types, type substitution will be performed on the event's return type,
/// and the appriopriate <see cref="SpecializedEvent"/> will be returned.
/// and the appropriate <see cref="SpecializedEvent"/> will be returned.
/// </remarks>
IEnumerable<IEvent> GetEvents(ITypeResolveContext context, Predicate<IEvent> filter = null);

10
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs

@ -82,11 +82,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -82,11 +82,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return EmptyList<IType>.Instance;
}
public virtual IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter = null)
{
return EmptyList<IType>.Instance;
}
public virtual IEnumerable<IMethod> GetMethods(ITypeResolveContext context, Predicate<IMethod> filter = null)
{
return EmptyList<IMethod>.Instance;
}
public virtual IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter)
{
return EmptyList<IMethod>.Instance;
}
public virtual IEnumerable<IMethod> GetConstructors(ITypeResolveContext context, Predicate<IMethod> filter = null)
{
return EmptyList<IMethod>.Instance;

12
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

@ -426,16 +426,26 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -426,16 +426,26 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return this;
}
public virtual IEnumerable<IType> GetNestedTypes(ITypeResolveContext context, Predicate<ITypeDefinition> filter = null)
public IEnumerable<IType> GetNestedTypes(ITypeResolveContext context, Predicate<ITypeDefinition> filter = null)
{
return ParameterizedType.GetNestedTypes(this, context, filter);
}
public IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter = null)
{
return ParameterizedType.GetNestedTypes(this, typeArguments, context, filter);
}
public virtual IEnumerable<IMethod> GetMethods(ITypeResolveContext context, Predicate<IMethod> filter = null)
{
return ParameterizedType.GetMethods(this, context, filter);
}
public virtual IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter = null)
{
return ParameterizedType.GetMethods(this, typeArguments, context, filter);
}
public virtual IEnumerable<IMethod> GetConstructors(ITypeResolveContext context, Predicate<IMethod> filter = null)
{
ITypeDefinition compound = GetCompoundClass();

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

@ -261,86 +261,40 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -261,86 +261,40 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IEnumerable<IMethod> GetMethods(ITypeResolveContext context, Predicate<IMethod> filter = null)
{
foreach (var baseType in GetNonCircularBaseTypes(context)) {
foreach (var m in baseType.GetMethods(context, filter)) {
if (!m.IsStatic)
yield return m;
}
}
return ParameterizedType.GetMethods(this, context, FilterNonStatic(filter));
}
public IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter = null)
{
return ParameterizedType.GetMethods(this, typeArguments, context, FilterNonStatic(filter));
}
public IEnumerable<IProperty> GetProperties(ITypeResolveContext context, Predicate<IProperty> filter = null)
{
foreach (var baseType in GetNonCircularBaseTypes(context)) {
foreach (var m in baseType.GetProperties(context, filter)) {
if (!m.IsStatic)
yield return m;
}
}
return ParameterizedType.GetProperties(this, context, FilterNonStatic(filter));
}
public IEnumerable<IField> GetFields(ITypeResolveContext context, Predicate<IField> filter = null)
{
foreach (var baseType in GetNonCircularBaseTypes(context)) {
foreach (var m in baseType.GetFields(context, filter)) {
if (!m.IsStatic)
yield return m;
}
}
return ParameterizedType.GetFields(this, context, FilterNonStatic(filter));
}
public IEnumerable<IEvent> GetEvents(ITypeResolveContext context, Predicate<IEvent> filter = null)
{
foreach (var baseType in GetNonCircularBaseTypes(context)) {
foreach (var m in baseType.GetEvents(context, filter)) {
if (!m.IsStatic)
yield return m;
}
}
return ParameterizedType.GetEvents(this, context, FilterNonStatic(filter));
}
public IEnumerable<IMember> GetMembers(ITypeResolveContext context, Predicate<IMember> filter = null)
{
foreach (var baseType in GetNonCircularBaseTypes(context)) {
foreach (var m in baseType.GetMembers(context, filter)) {
if (!m.IsStatic)
yield return m;
}
}
return ParameterizedType.GetMembers(this, context, FilterNonStatic(filter));
}
// Problem with type parameter resolving - circular declarations
// void Example<S, T> (S s, T t) where S : T where T : S
IEnumerable<IType> GetNonCircularBaseTypes(ITypeResolveContext context)
{
var result = this.GetBaseTypes(context).Where(bt => !IsCircular (context, bt));
if (result.Any ())
return result;
// result may be empty, GetBaseTypes doesn't return object/struct when there are only constraints (even circular) as base types are available,
// but even when there are only circular references the default base type should be included.
IType defaultBaseType = context.GetTypeDefinition("System", HasValueTypeConstraint ? "ValueType" : "Object", 0, StringComparer.Ordinal);
if (defaultBaseType != null)
return new [] { defaultBaseType };
return Enumerable.Empty<IType> ();
}
bool IsCircular(ITypeResolveContext context, IType baseType)
static Predicate<T> FilterNonStatic<T>(Predicate<T> filter) where T : class, IMember
{
var parameter = baseType as DefaultTypeParameter;
if (parameter == null)
return false;
var stack = new Stack<DefaultTypeParameter>();
while (true) {
if (parameter == this)
return true;
foreach (DefaultTypeParameter parameterBaseType in parameter.GetNonCircularBaseTypes(context).Where(t => t is DefaultTypeParameter)) {
stack.Push(parameterBaseType);
}
if (stack.Count == 0)
return false;
parameter = stack.Pop();
}
if (filter == null)
return member => !member.IsStatic;
else
return member => !member.IsStatic && filter(member);
}
IEnumerable<IType> IType.GetNestedTypes(ITypeResolveContext context, Predicate<ITypeDefinition> filter)
@ -348,6 +302,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -348,6 +302,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return EmptyList<IType>.Instance;
}
IEnumerable<IType> IType.GetNestedTypes(IList<IType> typeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter)
{
return EmptyList<IType>.Instance;
}
public IEnumerable<IType> GetBaseTypes(ITypeResolveContext context)
{
bool hasNonInterfaceConstraint = false;

65
ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs

@ -1,65 +0,0 @@ @@ -1,65 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Substitutes method type parameters with type arguments. Does not modify class type parameters.
/// </summary>
public class MethodTypeParameterSubstitution : TypeVisitor
{
readonly IList<IType> typeArguments;
public MethodTypeParameterSubstitution(IList<IType> typeArguments)
{
this.typeArguments = typeArguments;
}
public override IType VisitTypeParameter(ITypeParameter type)
{
int index = type.Index;
if (type.OwnerType == EntityType.Method) {
if (index >= 0 && index < typeArguments.Count)
return typeArguments[index];
else
return SharedTypes.UnknownType;
} else {
return base.VisitTypeParameter(type);
}
}
public override string ToString()
{
StringBuilder b = new StringBuilder();
b.Append('[');
for (int i = 0; i < typeArguments.Count; i++) {
if (i > 0) b.Append(", ");
b.Append("``");
b.Append(i);
b.Append(" -> ");
b.Append(typeArguments[i]);
}
b.Append(']');
return b.ToString();
}
}
}

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

@ -21,55 +21,46 @@ using System; @@ -21,55 +21,46 @@ using System;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Represents a specialized IEvent (e.g. after type substitution).
/// Represents a specialized IEvent (event after type substitution).
/// </summary>
public class SpecializedEvent : DefaultEvent
public class SpecializedEvent : SpecializedMember, IEvent
{
readonly IMember memberDefinition;
IType declaringType;
readonly IEvent eventDefinition;
public SpecializedEvent(IEvent e) : base(e)
public SpecializedEvent(IType declaringType, IEvent eventDefinition)
: base(declaringType, eventDefinition)
{
this.memberDefinition = e.MemberDefinition;
this.declaringType = e.DeclaringType;
this.eventDefinition = eventDefinition;
}
public override IType DeclaringType {
get { return declaringType; }
internal SpecializedEvent(IType declaringType, IEvent eventDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, eventDefinition, substitution, context)
{
this.eventDefinition = eventDefinition;
}
public void SetDeclaringType(IType declaringType)
{
CheckBeforeMutation();
this.declaringType = declaringType;
public bool CanAdd {
get { return eventDefinition.CanAdd; }
}
public override IMember MemberDefinition {
get { return memberDefinition; }
public bool CanRemove {
get { return eventDefinition.CanRemove; }
}
public override string Documentation {
get { return memberDefinition.Documentation; }
public bool CanInvoke {
get { return eventDefinition.CanInvoke; }
}
public override int GetHashCode()
{
int hashCode = 0;
unchecked {
if (memberDefinition != null)
hashCode += 1000000007 * memberDefinition.GetHashCode();
if (declaringType != null)
hashCode += 1000000009 * declaringType.GetHashCode();
}
return hashCode;
public IAccessor AddAccessor {
get { return eventDefinition.AddAccessor; }
}
public override bool Equals(object obj)
{
SpecializedEvent other = obj as SpecializedEvent;
if (other == null)
return false;
return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType);
public IAccessor RemoveAccessor {
get { return eventDefinition.RemoveAccessor; }
}
public IAccessor InvokeAccessor {
get { return eventDefinition.InvokeAccessor; }
}
}
}

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

@ -21,55 +21,42 @@ using System; @@ -21,55 +21,42 @@ using System;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Represents a specialized IField (e.g. after type substitution).
/// Represents a specialized IField (field after type substitution).
/// </summary>
public class SpecializedField : DefaultField
public class SpecializedField : SpecializedMember, IField
{
readonly IMember memberDefinition;
IType declaringType;
readonly IField fieldDefinition;
public SpecializedField(IField f) : base(f)
public SpecializedField(IType declaringType, IField fieldDefinition)
: base(declaringType, fieldDefinition)
{
this.memberDefinition = f.MemberDefinition;
this.declaringType = f.DeclaringType;
this.fieldDefinition = fieldDefinition;
}
public override IType DeclaringType {
get { return declaringType; }
internal SpecializedField(IType declaringType, IField fieldDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, fieldDefinition, substitution, context)
{
this.fieldDefinition = fieldDefinition;
}
public void SetDeclaringType(IType declaringType)
{
CheckBeforeMutation();
this.declaringType = declaringType;
public bool IsReadOnly {
get { return fieldDefinition.IsReadOnly; }
}
public override IMember MemberDefinition {
get { return memberDefinition; }
public bool IsVolatile {
get { return fieldDefinition.IsVolatile; }
}
public override string Documentation {
get { return memberDefinition.Documentation; }
ITypeReference IVariable.Type {
get { return this.ReturnType; }
}
public override int GetHashCode()
{
int hashCode = 0;
unchecked {
if (memberDefinition != null)
hashCode += 1000000007 * memberDefinition.GetHashCode();
if (declaringType != null)
hashCode += 1000000009 * declaringType.GetHashCode();
}
return hashCode;
public bool IsConst {
get { return fieldDefinition.IsConst; }
}
public override bool Equals(object obj)
{
SpecializedField other = obj as SpecializedField;
if (other == null)
return false;
return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType);
public IConstantValue ConstantValue {
get { return fieldDefinition.ConstantValue; }
}
}
}

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

@ -0,0 +1,282 @@ @@ -0,0 +1,282 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Represents a SpecializedMember (a member on which type substitution has been performed).
/// </summary>
public abstract class SpecializedMember : IMember
{
readonly IType declaringType;
readonly IMember memberDefinition;
readonly 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");
if (memberDefinition == null)
throw new ArgumentNullException("memberDefinition");
this.declaringType = declaringType;
this.memberDefinition = memberDefinition;
this.returnType = Substitute(memberDefinition.ReturnType, substitution, context);
}
internal static TypeVisitor GetSubstitution(IType declaringType)
{
ParameterizedType pt = declaringType as ParameterizedType;
if (pt != null)
return pt.GetSubstitution();
else
return null;
}
internal static ITypeReference Substitute(ITypeReference type, TypeVisitor substitution, ITypeResolveContext context)
{
if (substitution == null)
return type;
if (context != null)
return type.Resolve(context).AcceptVisitor(substitution);
else
return SubstitutionTypeReference.Create(type, substitution);
}
public IType DeclaringType {
get { return declaringType; }
}
public IMember MemberDefinition {
get { return memberDefinition; }
}
public ITypeReference ReturnType {
get { return returnType; }
}
public IList<IExplicitInterfaceImplementation> InterfaceImplementations {
get { return memberDefinition.InterfaceImplementations; }
}
public bool IsVirtual {
get { return memberDefinition.IsVirtual; }
}
public bool IsOverride {
get { return memberDefinition.IsOverride; }
}
public bool IsOverridable {
get { return memberDefinition.IsOverridable; }
}
public EntityType EntityType {
get { return memberDefinition.EntityType; }
}
public DomRegion Region {
get { return memberDefinition.Region; }
}
public DomRegion BodyRegion {
get { return memberDefinition.BodyRegion; }
}
public ITypeDefinition DeclaringTypeDefinition {
get { return memberDefinition.DeclaringTypeDefinition; }
}
public IList<IAttribute> Attributes {
get { return memberDefinition.Attributes; }
}
public string Documentation {
get { return memberDefinition.Documentation; }
}
public Accessibility Accessibility {
get { return memberDefinition.Accessibility; }
}
public bool IsStatic {
get { return memberDefinition.IsStatic; }
}
public bool IsAbstract {
get { return memberDefinition.IsAbstract; }
}
public bool IsSealed {
get { return memberDefinition.IsSealed; }
}
public bool IsShadowing {
get { return memberDefinition.IsShadowing; }
}
public bool IsSynthetic {
get { return memberDefinition.IsSynthetic; }
}
public bool IsPrivate {
get { return memberDefinition.IsPrivate; }
}
public bool IsPublic {
get { return memberDefinition.IsPublic; }
}
public bool IsProtected {
get { return memberDefinition.IsProtected; }
}
public bool IsInternal {
get { return memberDefinition.IsInternal; }
}
public bool IsProtectedOrInternal {
get { return memberDefinition.IsProtectedOrInternal; }
}
public bool IsProtectedAndInternal {
get { return memberDefinition.IsProtectedAndInternal; }
}
public IProjectContent ProjectContent {
get { return memberDefinition.ProjectContent; }
}
public string FullName {
get { return memberDefinition.FullName; }
}
public string Name {
get { return memberDefinition.Name; }
}
public string Namespace {
get { return memberDefinition.Namespace; }
}
public string ReflectionName {
get { return memberDefinition.ReflectionName; }
}
public bool IsFrozen {
get { return memberDefinition.IsFrozen; }
}
void IFreezable.Freeze()
{
if (!memberDefinition.IsFrozen)
throw new NotSupportedException();
}
public override bool Equals(object obj)
{
SpecializedMember other = obj as SpecializedMember;
if (other == null)
return false;
return this.declaringType.Equals(other.declaringType) && this.memberDefinition.Equals(other.memberDefinition);
}
public override int GetHashCode()
{
unchecked {
return 1000000007 * declaringType.GetHashCode() + 1000000009 * memberDefinition.GetHashCode();
}
}
public override string ToString()
{
StringBuilder b = new StringBuilder("[");
b.Append(GetType().Name);
b.Append(' ');
b.Append(declaringType.ToString());
b.Append('.');
b.Append(this.Name);
b.Append(':');
b.Append(returnType.ToString());
b.Append(']');
return b.ToString();
}
}
public abstract class SpecializedParameterizedMember : SpecializedMember, IParameterizedMember
{
readonly IList<IParameter> parameters;
protected SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition)
: this(declaringType, memberDefinition, GetSubstitution(declaringType), null)
{
}
internal SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, memberDefinition, substitution, context)
{
var paramDefs = memberDefinition.Parameters;
if (paramDefs.Count == 0) {
this.parameters = EmptyList<IParameter>.Instance;
} else {
var parameters = new IParameter[paramDefs.Count];
for (int i = 0; i < parameters.Length; i++) {
ITypeReference newType = Substitute(paramDefs[i].Type, substitution, context);
if (newType != paramDefs[i].Type) {
parameters[i] = new DefaultParameter(paramDefs[i]) { Type = newType };
} else {
parameters[i] = paramDefs[i];
}
}
this.parameters = Array.AsReadOnly(parameters);
}
}
public IList<IParameter> Parameters {
get { return parameters; }
}
public override string ToString()
{
StringBuilder b = new StringBuilder("[");
b.Append(GetType().Name);
b.Append(' ');
b.Append(this.DeclaringType.ToString());
b.Append('.');
b.Append(this.Name);
b.Append('(');
for (int i = 0; i < parameters.Count; i++) {
if (i > 0) b.Append(", ");
b.Append(parameters[i].ToString());
}
b.Append("):");
b.Append(this.ReturnType.ToString());
b.Append(']');
return b.ToString();
}
}
}

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

@ -17,49 +17,62 @@ @@ -17,49 +17,62 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Represents a specialized IMethod (e.g. after type substitution).
/// </summary>
public class SpecializedMethod : DefaultMethod
public class SpecializedMethod : SpecializedParameterizedMember, IMethod
{
readonly IMember memberDefinition;
IType declaringType;
readonly IMethod methodDefinition;
readonly IList<IType> typeArguments;
public SpecializedMethod(IMethod m) : base(m)
public SpecializedMethod(IType declaringType, IMethod methodDefinition, IList<IType> typeArguments = null)
: this(declaringType, methodDefinition, typeArguments, GetSubstitution(declaringType, typeArguments), null)
{
this.memberDefinition = m.MemberDefinition;
this.declaringType = m.DeclaringType;
}
public override IType DeclaringType {
get { return declaringType; }
}
public void SetDeclaringType(IType declaringType)
internal SpecializedMethod(IType declaringType, IMethod methodDefinition, IList<IType> typeArguments, TypeVisitor substitution, ITypeResolveContext context) : base(declaringType, methodDefinition, substitution, context)
{
CheckBeforeMutation();
this.declaringType = declaringType;
this.methodDefinition = methodDefinition;
if (typeArguments != null) {
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;
}
}
public override IMember MemberDefinition {
get { return memberDefinition; }
internal static TypeVisitor GetSubstitution(IType declaringType, IList<IType> typeArguments)
{
ParameterizedType pt = declaringType as ParameterizedType;
if (pt != null)
return pt.GetSubstitution(typeArguments);
else if (typeArguments != null)
return new TypeParameterSubstitution(null, typeArguments);
else
return null;
}
public override string Documentation {
get { return memberDefinition.Documentation; }
/// <summary>
/// Gets the type arguments passed to this method.
/// </summary>
public IList<IType> TypeArguments {
get { return typeArguments; }
}
public override int GetHashCode()
{
int hashCode = 0;
int hashCode = base.GetHashCode();
unchecked {
if (memberDefinition != null)
hashCode += 1000000007 * memberDefinition.GetHashCode();
if (declaringType != null)
hashCode += 1000000009 * declaringType.GetHashCode();
for (int i = 0; i < typeArguments.Count; i++) {
hashCode *= 362631391;
hashCode += typeArguments[i].GetHashCode();
}
}
return hashCode;
}
@ -67,25 +80,39 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -67,25 +80,39 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override bool Equals(object obj)
{
SpecializedMethod other = obj as SpecializedMethod;
if (other == null)
if (!base.Equals(other))
return false;
if (typeArguments.Count != other.typeArguments.Count)
return false;
return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType);
for (int i = 0; i < typeArguments.Count; i++) {
if (!typeArguments[i].Equals(other.typeArguments[i]))
return false;
}
return true;
}
/// <summary>
/// Performs type substitution in parameter types and in the return type.
/// </summary>
public void SubstituteTypes(Func<ITypeReference, ITypeReference> substitution)
{
this.ReturnType = substitution(this.ReturnType);
var p = this.Parameters;
for (int i = 0; i < p.Count; i++) {
ITypeReference newType = substitution(p[i].Type);
if (newType != p[i].Type) {
p[i] = new DefaultParameter(p[i]) { Type = newType };
}
}
// TODO: we might also have to perform substitution within the method's constraints
public IList<IAttribute> ReturnTypeAttributes {
get { return methodDefinition.ReturnTypeAttributes; }
}
public IList<ITypeParameter> TypeParameters {
get { return methodDefinition.TypeParameters; }
}
public bool IsExtensionMethod {
get { return methodDefinition.IsExtensionMethod; }
}
public bool IsConstructor {
get { return methodDefinition.IsConstructor; }
}
public bool IsDestructor {
get { return methodDefinition.IsDestructor; }
}
public bool IsOperator {
get { return methodDefinition.IsOperator; }
}
}
}

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

@ -21,70 +21,42 @@ using System; @@ -21,70 +21,42 @@ using System;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Represents a specialized IProperty (e.g. after type substitution).
/// Represents a specialized IProperty (property after type substitution).
/// </summary>
public class SpecializedProperty : DefaultProperty
public class SpecializedProperty : SpecializedParameterizedMember, IProperty
{
readonly IMember memberDefinition;
IType declaringType;
readonly IProperty propertyDefinition;
public SpecializedProperty(IProperty p) : base(p)
public SpecializedProperty(IType declaringType, IProperty propertyDefinition)
: base(declaringType, propertyDefinition)
{
this.memberDefinition = p.MemberDefinition;
this.declaringType = p.DeclaringType;
this.propertyDefinition = propertyDefinition;
}
public override IType DeclaringType {
get { return declaringType; }
}
public void SetDeclaringType(IType declaringType)
internal SpecializedProperty(IType declaringType, IProperty propertyDefinition, TypeVisitor substitution, ITypeResolveContext context)
: base(declaringType, propertyDefinition, substitution, context)
{
CheckBeforeMutation();
this.declaringType = declaringType;
this.propertyDefinition = propertyDefinition;
}
public override IMember MemberDefinition {
get { return memberDefinition; }
public bool CanGet {
get { return propertyDefinition.CanGet; }
}
public override string Documentation {
get { return memberDefinition.Documentation; }
public bool CanSet {
get { return propertyDefinition.CanSet; }
}
public override int GetHashCode()
{
int hashCode = 0;
unchecked {
if (memberDefinition != null)
hashCode += 1000000007 * memberDefinition.GetHashCode();
if (declaringType != null)
hashCode += 1000000009 * declaringType.GetHashCode();
}
return hashCode;
public IAccessor Getter {
get { return propertyDefinition.Getter; }
}
public override bool Equals(object obj)
{
SpecializedProperty other = obj as SpecializedProperty;
if (other == null)
return false;
return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType);
public IAccessor Setter {
get { return propertyDefinition.Setter; }
}
/// <summary>
/// Performs type substitution in parameter types and in the return type.
/// </summary>
public void SubstituteTypes(Func<ITypeReference, ITypeReference> substitution)
{
this.ReturnType = substitution(this.ReturnType);
var p = this.Parameters;
for (int i = 0; i < p.Count; i++) {
ITypeReference newType = substitution(p[i].Type);
if (newType != p[i].Type) {
p[i] = new DefaultParameter(p[i]) { Type = newType };
}
}
public bool IsIndexer {
get { return propertyDefinition.IsIndexer; }
}
}
}

101
ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Substitues class and method type parameters.
/// </summary>
public class TypeParameterSubstitution : TypeVisitor
{
readonly IList<IType> classTypeArguments;
readonly IList<IType> methodTypeArguments;
/// <summary>
/// Creates a new type parameter substitution.
/// </summary>
/// <param name="classTypeArguments">
/// The type arguments to substitute for class type parameters.
/// Pass <c>null</c> to keep class type parameters unmodified.
/// </param>
/// <param name="methodTypeArguments">
/// The type arguments to substitute for method type parameters.
/// Pass <c>null</c> to keep method type parameters unmodified.
/// </param>
public TypeParameterSubstitution(IList<IType> classTypeArguments, IList<IType> methodTypeArguments)
{
this.classTypeArguments = classTypeArguments;
this.methodTypeArguments = methodTypeArguments;
}
public override IType VisitTypeParameter(ITypeParameter type)
{
int index = type.Index;
if (classTypeArguments != null && type.OwnerType == EntityType.TypeDefinition) {
if (index >= 0 && index < classTypeArguments.Count)
return classTypeArguments[index];
else
return SharedTypes.UnknownType;
} else if (methodTypeArguments != null && type.OwnerType == EntityType.Method) {
if (index >= 0 && index < methodTypeArguments.Count)
return methodTypeArguments[index];
else
return SharedTypes.UnknownType;
} else {
return base.VisitTypeParameter(type);
}
}
public override string ToString()
{
StringBuilder b = new StringBuilder();
b.Append('[');
bool first = true;
if (classTypeArguments != null) {
for (int i = 0; i < classTypeArguments.Count; i++) {
if (first) {
first = false;
b.Append(", ");
}
b.Append('`');
b.Append(i);
b.Append(" -> ");
b.Append(classTypeArguments[i]);
}
}
if (methodTypeArguments != null) {
for (int i = 0; i < methodTypeArguments.Count; i++) {
if (first) {
first = false;
b.Append(", ");
}
b.Append("``");
b.Append(i);
b.Append(" -> ");
b.Append(methodTypeArguments[i]);
}
}
b.Append(']');
return b.ToString();
}
}
}

5
ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs

@ -54,6 +54,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -54,6 +54,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return EmptyList<IMethod>.Instance;
}
public override IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter)
{
return EmptyList<IMethod>.Instance;
}
public override IEnumerable<IProperty> GetProperties(ITypeResolveContext context, Predicate<IProperty> filter)
{
return EmptyList<IProperty>.Instance;

183
ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs

@ -38,44 +38,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -38,44 +38,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </remarks>
public sealed class ParameterizedType : Immutable, IType
{
sealed class Substitution : TypeVisitor
{
readonly IType[] typeArguments;
public Substitution(IType[] typeArguments)
{
this.typeArguments = typeArguments;
}
public override IType VisitTypeParameter(ITypeParameter type)
{
int index = type.Index;
if (type.OwnerType == EntityType.TypeDefinition) {
if (index >= 0 && index < typeArguments.Length)
return typeArguments[index];
else
return SharedTypes.UnknownType;
} else {
return base.VisitTypeParameter(type);
}
}
public override string ToString()
{
StringBuilder b = new StringBuilder();
b.Append('[');
for (int i = 0; i < typeArguments.Length; i++) {
if (i > 0) b.Append(", ");
b.Append('`');
b.Append(i);
b.Append(" -> ");
b.Append(typeArguments[i]);
}
b.Append(']');
return b.ToString();
}
}
readonly ITypeDefinition genericType;
readonly IType[] typeArguments;
@ -190,21 +152,31 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -190,21 +152,31 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
public IType SubstituteInType(IType type)
{
return type.AcceptVisitor(new Substitution(typeArguments));
return type.AcceptVisitor(new TypeParameterSubstitution(typeArguments, null));
}
/// <summary>
/// Gets a type visitor that performs the substitution of class type parameters with the type arguments
/// of this parameterized type.
/// </summary>
public TypeVisitor GetSubstitution()
public TypeParameterSubstitution GetSubstitution()
{
return new TypeParameterSubstitution(typeArguments, null);
}
/// <summary>
/// Gets a type visitor that performs the substitution of class type parameters with the type arguments
/// of this parameterized type,
/// and also substitutes method type parameters with the specified method type arguments.
/// </summary>
public TypeVisitor GetSubstitution(IList<IType> methodTypeArguments)
{
return new Substitution(typeArguments);
return new TypeParameterSubstitution(typeArguments, methodTypeArguments);
}
public IEnumerable<IType> GetBaseTypes(ITypeResolveContext context)
{
Substitution substitution = new Substitution(typeArguments);
var substitution = GetSubstitution();
return genericType.GetBaseTypes(context).Select(t => t.AcceptVisitor(substitution));
}
@ -213,12 +185,22 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -213,12 +185,22 @@ namespace ICSharpCode.NRefactory.TypeSystem
return GetNestedTypes(this, context, filter);
}
public IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter = null)
{
return GetNestedTypes(this, typeArguments, context, filter);
}
internal static IEnumerable<IType> GetNestedTypes(IType type, ITypeResolveContext context, Predicate<ITypeDefinition> filter)
{
return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetNestedTypesInternal(t, context, filter));
return GetNestedTypes(type, null, context, filter);
}
internal static IEnumerable<IType> GetNestedTypes(IType type, IList<IType> nestedTypeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter)
{
return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetNestedTypesInternal(t, nestedTypeArguments, context, filter));
}
static IEnumerable<IType> GetNestedTypesInternal(IType baseType, ITypeResolveContext context, Predicate<ITypeDefinition> filter)
static IEnumerable<IType> GetNestedTypesInternal(IType baseType, IList<IType> nestedTypeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter)
{
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef == null)
@ -227,22 +209,30 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -227,22 +209,30 @@ namespace ICSharpCode.NRefactory.TypeSystem
int outerTypeParameterCount = baseTypeDef.TypeParameterCount;
ParameterizedType pt = baseType as ParameterizedType;
foreach (ITypeDefinition nestedType in baseTypeDef.NestedTypes) {
int totalTypeParameterCount = nestedType.TypeParameterCount;
if (nestedTypeArguments != null) {
if (totalTypeParameterCount - outerTypeParameterCount != nestedTypeArguments.Count)
continue;
}
if (!(filter == null || filter(nestedType)))
continue;
int innerTypeParameterCount = nestedType.TypeParameterCount;
if (innerTypeParameterCount == 0 || (pt == null && innerTypeParameterCount == outerTypeParameterCount)) {
if (totalTypeParameterCount == 0 || (pt == null && totalTypeParameterCount == outerTypeParameterCount)) {
// The nested type has no new type parameters, and there are no type arguments
// to copy from the outer type
// -> we can directly return the nested type definition
yield return nestedType;
} else {
// We need to parameterize the nested type
IType[] newTypeArguments = new IType[innerTypeParameterCount];
IType[] newTypeArguments = new IType[totalTypeParameterCount];
for (int i = 0; i < outerTypeParameterCount; i++) {
newTypeArguments[i] = pt != null ? pt.typeArguments[i] : baseTypeDef.TypeParameters[i];
}
for (int i = outerTypeParameterCount; i < innerTypeParameterCount; i++) {
newTypeArguments[i] = SharedTypes.UnboundTypeArgument;
for (int i = outerTypeParameterCount; i < totalTypeParameterCount; i++) {
if (nestedTypeArguments != null)
newTypeArguments[i] = nestedTypeArguments[i - outerTypeParameterCount];
else
newTypeArguments[i] = SharedTypes.UnboundTypeArgument;
}
yield return new ParameterizedType(nestedType, newTypeArguments);
}
@ -251,14 +241,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -251,14 +241,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
public IEnumerable<IMethod> GetConstructors(ITypeResolveContext context, Predicate<IMethod> filter = null)
{
Substitution substitution = new Substitution(typeArguments);
Func<ITypeReference, ITypeReference> substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution);
var substitution = GetSubstitution();
List<IMethod> methods = genericType.GetConstructors(context, filter).ToList();
for (int i = 0; i < methods.Count; i++) {
SpecializedMethod m = new SpecializedMethod(methods[i]);
m.SetDeclaringType(this);
m.SubstituteTypes(substitutionFunc);
methods[i] = m;
methods[i] = new SpecializedMethod(this, methods[i], null, substitution, context);
}
return methods;
}
@ -268,37 +254,48 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -268,37 +254,48 @@ namespace ICSharpCode.NRefactory.TypeSystem
return GetMethods(this, context, filter);
}
public IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter = null)
{
return GetMethods(this, typeArguments, context, filter);
}
internal static IEnumerable<IMethod> GetMethods(IType type, ITypeResolveContext context, Predicate<IMethod> filter)
{
return GetMethods(type, null, context, filter);
}
internal static IEnumerable<IMethod> GetMethods(IType type, IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter)
{
Predicate<IMethod> newFilter;
if (filter == null)
newFilter = m => !m.IsConstructor;
else
newFilter = m => !m.IsConstructor && filter(m);
return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMethodsInternal(t, context, newFilter));
return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMethodsInternal(t, typeArguments, context, newFilter));
}
static IEnumerable<IMethod> GetMethodsInternal(IType baseType, ITypeResolveContext context, Predicate<IMethod> filter)
static IEnumerable<IMethod> GetMethodsInternal(IType baseType, IList<IType> methodTypeArguments, ITypeResolveContext context, Predicate<IMethod> filter)
{
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef == null)
yield break;
baseTypeDef = baseTypeDef.GetCompoundClass();
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
Substitution substitution = null;
Func<ITypeReference, ITypeReference> substitutionFunc = null;
if (pt != null || (methodTypeArguments != null && methodTypeArguments.Count > 0)) {
TypeVisitor substitution = null;
foreach (IMethod m in baseTypeDef.Methods) {
if (methodTypeArguments != null && methodTypeArguments.Count > 0) {
if (m.TypeParameters.Count != methodTypeArguments.Count)
continue;
}
if (!(filter == null || filter(m)))
continue;
if (substitution == null) {
substitution = new Substitution(pt.typeArguments);
substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution);
substitution = new TypeParameterSubstitution(pt != null ? pt.typeArguments : null, methodTypeArguments);
}
SpecializedMethod sm = new SpecializedMethod(m);
sm.SetDeclaringType(pt);
sm.SubstituteTypes(substitutionFunc);
yield return sm;
yield return new SpecializedMethod(baseType, m, methodTypeArguments, substitution, context);
}
} else {
foreach (IMethod m in baseTypeDef.Methods) {
@ -326,19 +323,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -326,19 +323,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
baseTypeDef = baseTypeDef.GetCompoundClass();
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
Substitution substitution = null;
Func<ITypeReference, ITypeReference> substitutionFunc = null;
TypeParameterSubstitution substitution = null;
foreach (IProperty p in baseTypeDef.Properties) {
if (!(filter == null || filter(p)))
continue;
if (substitution == null) {
substitution = new Substitution(pt.typeArguments);
substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution);
substitution = pt.GetSubstitution();
}
SpecializedProperty sp = new SpecializedProperty(p);
sp.SetDeclaringType(pt);
sp.SubstituteTypes(substitutionFunc);
yield return sp;
yield return new SpecializedProperty(pt, p, substitution, context);
}
} else {
foreach (IProperty p in baseTypeDef.Properties) {
@ -366,19 +358,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -366,19 +358,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
baseTypeDef = baseTypeDef.GetCompoundClass();
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
Substitution substitution = null;
Func<ITypeReference, ITypeReference> substitutionFunc = null;
TypeParameterSubstitution substitution = null;
foreach (IField f in baseTypeDef.Fields) {
if (!(filter == null || filter(f)))
continue;
if (substitution == null) {
substitution = new Substitution(pt.typeArguments);
substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution);
substitution = pt.GetSubstitution();
}
SpecializedField sf = new SpecializedField(f);
sf.SetDeclaringType(pt);
sf.ReturnType = f.ReturnType.Resolve(context).AcceptVisitor(substitution);
yield return sf;
yield return new SpecializedField(pt, f, substitution, context);
}
} else {
foreach (IField f in baseTypeDef.Fields) {
@ -406,19 +393,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -406,19 +393,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
baseTypeDef = baseTypeDef.GetCompoundClass();
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
Substitution substitution = null;
Func<ITypeReference, ITypeReference> substitutionFunc = null;
TypeParameterSubstitution substitution = null;
foreach (IEvent e in baseTypeDef.Events) {
if (!(filter == null || filter(e)))
continue;
if (substitution == null) {
substitution = new Substitution(pt.typeArguments);
substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution);
substitution = pt.GetSubstitution();
}
SpecializedEvent se = new SpecializedEvent(e);
se.SetDeclaringType(pt);
se.ReturnType = e.ReturnType.Resolve(context).AcceptVisitor(substitution);
yield return se;
yield return new SpecializedEvent(pt, e, substitution, context);
}
} else {
foreach (IEvent e in baseTypeDef.Events) {
@ -440,14 +422,19 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -440,14 +422,19 @@ namespace ICSharpCode.NRefactory.TypeSystem
methodFilter = m => !m.IsConstructor;
else
methodFilter = m => !m.IsConstructor && filter(m);
return type.GetNonInterfaceBaseTypes(context).SelectMany(
delegate (IType t) {
IEnumerable<IMember> members = GetMethodsInternal(t, context, methodFilter);
members = members.Concat(GetPropertiesInternal(t, context, filter));
members = members.Concat(GetFieldsInternal(t, context, filter));
members = members.Concat(GetEventsInternal(t, context, filter));
return members;
});
return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMembersInternal(t, context, filter));
}
static IEnumerable<IMember> GetMembersInternal(IType baseType, ITypeResolveContext context, Predicate<IMember> filter)
{
foreach (var m in GetMethodsInternal(baseType, null, context, filter))
yield return m;
foreach (var m in GetPropertiesInternal(baseType, context, filter))
yield return m;
foreach (var m in GetFieldsInternal(baseType, context, filter))
yield return m;
foreach (var m in GetEventsInternal(baseType, context, filter))
yield return m;
}
public override bool Equals(object obj)

Loading…
Cancel
Save