Browse Source

Implemented IUnresolvedMember.Resolve().

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
180ed85c85
  1. 12
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs
  2. 114
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  3. 3
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs
  4. 16
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpTypeResolveContext.cs
  5. 2
      ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj
  6. 3
      ICSharpCode.NRefactory.ConsistencyCheck/Program.cs
  7. 29
      ICSharpCode.NRefactory.ConsistencyCheck/TypeSystemTests.cs
  8. 36
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  9. 4
      ICSharpCode.NRefactory/Documentation/IdStringMemberReference.cs
  10. 5
      ICSharpCode.NRefactory/Documentation/IdStringProvider.cs
  11. 12
      ICSharpCode.NRefactory/TypeSystem/IEvent.cs
  12. 12
      ICSharpCode.NRefactory/TypeSystem/IField.cs
  13. 39
      ICSharpCode.NRefactory/TypeSystem/IMember.cs
  14. 12
      ICSharpCode.NRefactory/TypeSystem/IMethod.cs
  15. 12
      ICSharpCode.NRefactory/TypeSystem/IProperty.cs
  16. 4
      ICSharpCode.NRefactory/TypeSystem/IType.cs
  17. 24
      ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs
  18. 8
      ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs
  19. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
  20. 128
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs
  21. 16
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs
  22. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs
  23. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  24. 5
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs
  25. 5
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs
  26. 17
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs
  27. 16
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs
  28. 61
      ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs
  29. 9
      ICSharpCode.NRefactory/TypeSystem/Implementation/ExplicitInterfaceImplementationMemberReference.cs
  30. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs
  31. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs
  32. 90
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs
  33. 100
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs
  34. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs
  35. 9
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializingMemberReference.cs
  36. 10
      ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs
  37. 30
      ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs

12
ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs

@ -33,9 +33,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -33,9 +33,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public static ResolveResult Resolve (ICompilation compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location,
CancellationToken cancellationToken = default(CancellationToken))
{
return Resolve (() => compilation, parsedFile, cu, location, cancellationToken);
return Resolve (new Lazy<ICompilation>(() => compilation), parsedFile, cu, location, cancellationToken);
}
public static ResolveResult Resolve(Func<ICompilation> compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location,
public static ResolveResult Resolve(Lazy<ICompilation> compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location,
CancellationToken cancellationToken = default(CancellationToken))
{
AstNode node;
@ -45,9 +45,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -45,9 +45,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public static ResolveResult Resolve (ICompilation compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node,
CancellationToken cancellationToken = default(CancellationToken))
{
return Resolve (() => compilation, parsedFile, cu, location, out node, cancellationToken);
return Resolve (new Lazy<ICompilation>(() => compilation), parsedFile, cu, location, out node, cancellationToken);
}
public static ResolveResult Resolve(Func<ICompilation> compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node,
public static ResolveResult Resolve(Lazy<ICompilation> compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node,
CancellationToken cancellationToken = default(CancellationToken))
{
node = cu.GetNodeAt(location);
@ -94,8 +94,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -94,8 +94,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
parentInvocation = node.Parent as InvocationExpression;
}
CSharpAstResolver resolver = new CSharpAstResolver(compilation(), cu, parsedFile);
resolver.ApplyNavigator(new NodeListResolveVisitorNavigator(node), cancellationToken);
// TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused
CSharpAstResolver resolver = new CSharpAstResolver(compilation.Value, cu, parsedFile);
ResolveResult rr = resolver.Resolve(node, cancellationToken);
if (rr is MethodGroupResolveResult && parentInvocation != null)
return resolver.Resolve(parentInvocation);

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

@ -653,16 +653,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -653,16 +653,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpResolver oldResolver = resolver;
for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) {
if (node.Role == Roles.Variable) {
IMember member = null;
IMember member;
if (parsedFile != null) {
member = GetMemberFromLocation(node.StartLocation);
} else if (resolver.CurrentTypeDefinition != null) {
} else {
string name = ((VariableInitializer)node).Name;
if (entityType == EntityType.Event) {
member = resolver.CurrentTypeDefinition.GetEvents(e => e.Name == name && !e.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
} else {
member = resolver.CurrentTypeDefinition.GetFields(e => e.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
}
member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, entityType, name);
}
resolver = resolver.WithCurrentMember(member);
@ -775,46 +771,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -775,46 +771,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
CSharpResolver oldResolver = resolver;
try {
IMember member = null;
IMember member;
if (parsedFile != null) {
member = GetMemberFromLocation(memberDeclaration.StartLocation);
} else if (resolver.CurrentTypeDefinition != null) {
} else {
// Re-discover the method:
EntityType entityType = memberDeclaration.EntityType;
var typeParameters = memberDeclaration.GetChildrenByRole(Roles.TypeParameter).ToArray();
var parameterTypes = TypeSystemConvertVisitor.GetParameterTypes(memberDeclaration.GetChildrenByRole(Roles.Parameter));
if (entityType == EntityType.Constructor) {
bool isStatic = memberDeclaration.HasModifier(Modifiers.Static);
member = resolver.CurrentTypeDefinition.Methods.FirstOrDefault(
m => m.EntityType == entityType && m.IsStatic == isStatic
&& m.Parameters.Count == parameterTypes.Count
&& IsMatchingMethod(m, typeParameters, parameterTypes));
string name = memberDeclaration.HasModifier(Modifiers.Static) ? ".cctor" : ".ctor";
member = AbstractUnresolvedMember.Resolve(
resolver.CurrentTypeResolveContext, entityType, name,
parameterTypeReferences: parameterTypes);
} else if (entityType == EntityType.Destructor) {
member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, entityType, "Finalize");
} else {
string name = (entityType == EntityType.Destructor ? "Finalize" : memberDeclaration.Name);
string[] typeParameterNames = memberDeclaration.GetChildrenByRole(Roles.TypeParameter).Select(tp => tp.Name).ToArray();
AstType explicitInterfaceAstType = memberDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
bool isExplicitInterfaceImplementation = false;
IType explicitInterfaceType = null;
ITypeReference explicitInterfaceType = null;
if (!explicitInterfaceAstType.IsNull) {
isExplicitInterfaceImplementation = true;
explicitInterfaceType = explicitInterfaceAstType.ToTypeReference().Resolve(resolver.CurrentTypeResolveContext);
}
foreach (var method in resolver.CurrentTypeDefinition.GetMethods(
m => m.EntityType == entityType && m.Name == name
&& m.TypeParameters.Count == typeParameters.Length && m.Parameters.Count == parameterTypes.Count
&& m.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation,
GetMemberOptions.IgnoreInheritedMembers
)) {
if (isExplicitInterfaceImplementation) {
if (method.ImplementedInterfaceMembers.Count != 1)
continue;
if (!explicitInterfaceType.Equals(method.ImplementedInterfaceMembers[0].DeclaringType))
continue;
}
if (IsMatchingMethod(method, typeParameters, parameterTypes)) {
member = method;
break;
}
explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
}
member = AbstractUnresolvedMember.Resolve(
resolver.CurrentTypeResolveContext, entityType, memberDeclaration.Name,
explicitInterfaceType, typeParameterNames, parameterTypes);
}
}
resolver = resolver.WithCurrentMember(member);
@ -829,20 +809,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -829,20 +809,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
bool IsMatchingMethod(IMethod method, TypeParameterDeclaration[] typeParameters, IList<ITypeReference> parameterTypes)
{
for (int i = 0; i < typeParameters.Length; i++) {
if (method.TypeParameters[i].Name != typeParameters[i].Name)
return false;
}
var resolvedParameterTypes = parameterTypes.Resolve(resolver.CurrentTypeResolveContext.WithCurrentMember(method));
for (int i = 0; i < parameterTypes.Count; i++) {
if (!method.Parameters[i].Type.Equals(resolvedParameterTypes[i]))
return false;
}
return true;
}
ResolveResult IAstVisitor<ResolveResult>.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
return VisitMethodMember(methodDeclaration);
@ -868,36 +834,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -868,36 +834,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
CSharpResolver oldResolver = resolver;
try {
IMember member = null;
IMember member;
if (parsedFile != null) {
member = GetMemberFromLocation(propertyOrIndexerDeclaration.StartLocation);
} else if (resolver.CurrentTypeDefinition != null) {
} else {
// Re-discover the property:
string name = propertyOrIndexerDeclaration.Name;
var parameterTypeReferences = TypeSystemConvertVisitor.GetParameterTypes(propertyOrIndexerDeclaration.GetChildrenByRole(Roles.Parameter));
var parameterTypes = parameterTypeReferences.Resolve(resolver.CurrentTypeResolveContext);
AstType explicitInterfaceAstType = propertyOrIndexerDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
bool isExplicitInterfaceImplementation = false;
IType explicitInterfaceType = null;
ITypeReference explicitInterfaceType = null;
if (!explicitInterfaceAstType.IsNull) {
isExplicitInterfaceImplementation = true;
explicitInterfaceType = explicitInterfaceAstType.ToTypeReference().Resolve(resolver.CurrentTypeResolveContext);
}
foreach (IProperty property in resolver.CurrentTypeDefinition.GetProperties(
p => p.Name == name && p.Parameters.Count == parameterTypes.Count && p.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation,
GetMemberOptions.IgnoreInheritedMembers
)) {
if (isExplicitInterfaceImplementation) {
if (property.ImplementedInterfaceMembers.Count != 1)
continue;
if (!explicitInterfaceType.Equals(property.ImplementedInterfaceMembers[0].DeclaringType))
continue;
}
if (Enumerable.SequenceEqual(parameterTypes, property.Parameters.Select(p => p.Type))) {
member = property;
break;
}
explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
}
member = AbstractUnresolvedMember.Resolve(
resolver.CurrentTypeResolveContext, propertyOrIndexerDeclaration.EntityType, name,
explicitInterfaceType, parameterTypeReferences: parameterTypeReferences);
}
resolver = resolver.WithCurrentMember(member);
@ -934,24 +885,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -934,24 +885,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
CSharpResolver oldResolver = resolver;
try {
IMember member = null;
IMember member;
if (parsedFile != null) {
member = GetMemberFromLocation(eventDeclaration.StartLocation);
} else if (resolver.CurrentTypeDefinition != null) {
} else {
string name = eventDeclaration.Name;
AstType explicitInterfaceAstType = eventDeclaration.PrivateImplementationType;
if (explicitInterfaceAstType.IsNull) {
member = resolver.CurrentTypeDefinition.GetEvents(
e => e.Name == name && !e.IsExplicitInterfaceImplementation,
GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, EntityType.Event, name);
} else {
IType explicitInterfaceType = explicitInterfaceAstType.ToTypeReference().Resolve(resolver.CurrentTypeResolveContext);
member = resolver.CurrentTypeDefinition.GetEvents(
e => e.Name == name && e.IsExplicitInterfaceImplementation,
GetMemberOptions.IgnoreInheritedMembers
).FirstOrDefault(
e => e.ImplementedInterfaceMembers.Count == 1 && explicitInterfaceType.Equals(e.ImplementedInterfaceMembers[0].DeclaringType)
);
member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, EntityType.Event, name,
explicitInterfaceAstType.ToTypeReference());
}
}
resolver = resolver.WithCurrentMember(member);

3
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs

@ -213,6 +213,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -213,6 +213,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
var unresolvedTypeDef = entity as IUnresolvedTypeDefinition ?? entity.DeclaringTypeDefinition;
var resolvedTypeDef = resolvedEntity as ITypeDefinition ?? resolvedEntity.DeclaringTypeDefinition;
if (unresolvedTypeDef != null && resolvedTypeDef != null) {
// Strictly speaking, we would have to pass the parent context into CreateResolveContext,
// then transform the result using WithTypeDefinition().
// However, we can simplify this here because we know this is a C# type definition.
var context = unresolvedTypeDef.CreateResolveContext(new SimpleTypeResolveContext(resolvedTypeDef));
if (resolvedEntity is IMember)
context = context.WithCurrentMember((IMember)resolvedEntity);

16
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpTypeResolveContext.cs

@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
readonly ResolvedUsingScope currentUsingScope;
readonly ITypeDefinition currentTypeDefinition;
readonly IMember currentMember;
readonly string[] methodTypeParameterNames;
public CSharpTypeResolveContext(IAssembly assembly, ResolvedUsingScope usingScope = null, ITypeDefinition typeDefinition = null, IMember member = null)
{
@ -38,6 +39,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -38,6 +39,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
this.currentMember = member;
}
private CSharpTypeResolveContext(IAssembly assembly, ResolvedUsingScope usingScope, ITypeDefinition typeDefinition, IMember member, string[] methodTypeParameterNames)
{
this.assembly = assembly;
this.currentUsingScope = usingScope;
this.currentTypeDefinition = typeDefinition;
this.currentMember = member;
this.methodTypeParameterNames = methodTypeParameterNames;
}
public ResolvedUsingScope CurrentUsingScope {
get { return currentUsingScope; }
}
@ -60,7 +70,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -60,7 +70,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public CSharpTypeResolveContext WithCurrentTypeDefinition(ITypeDefinition typeDefinition)
{
return new CSharpTypeResolveContext(assembly, currentUsingScope, typeDefinition, currentMember);
return new CSharpTypeResolveContext(assembly, currentUsingScope, typeDefinition, currentMember, methodTypeParameterNames);
}
ITypeResolveContext ITypeResolveContext.WithCurrentTypeDefinition(ITypeDefinition typeDefinition)
@ -70,7 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -70,7 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public CSharpTypeResolveContext WithCurrentMember(IMember member)
{
return new CSharpTypeResolveContext(assembly, currentUsingScope, currentTypeDefinition, member);
return new CSharpTypeResolveContext(assembly, currentUsingScope, currentTypeDefinition, member, methodTypeParameterNames);
}
ITypeResolveContext ITypeResolveContext.WithCurrentMember(IMember member)
@ -80,7 +90,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -80,7 +90,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public CSharpTypeResolveContext WithUsingScope(ResolvedUsingScope usingScope)
{
return new CSharpTypeResolveContext(assembly, usingScope, currentTypeDefinition, currentMember);
return new CSharpTypeResolveContext(assembly, usingScope, currentTypeDefinition, currentMember, methodTypeParameterNames);
}
}
}

2
ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj

@ -59,7 +59,7 @@ @@ -59,7 +59,7 @@
</Compile>
<Compile Include="CSharpProject.cs" />
<Compile Include="FindReferencesConsistencyCheck.cs" />
<Compile Include="IDStringConsistencyCheck.cs" />
<Compile Include="TypeSystemTests.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RandomizedOrderResolverTest.cs" />

3
ICSharpCode.NRefactory.ConsistencyCheck/Program.cs

@ -57,7 +57,8 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck @@ -57,7 +57,8 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
solution.AllFiles.Count(),
solution.Projects.Count);
//using (new Timer("ID String test... ")) IDStringConsistencyCheck.Run(solution);
//using (new Timer("ID String test... ")) TypeSystemTests.IDStringConsistencyCheck(solution);
using (new Timer("Resolve unresolved members... ")) TypeSystemTests.ResolvedUnresolvedMembers(solution);
//RunTestOnAllFiles("Roundtripping test", RoundtripTest.RunTest);
RunTestOnAllFiles("Resolver test", ResolverTest.RunTest);
RunTestOnAllFiles("Resolver test (no parsed file)", ResolverTest.RunTestWithoutParsedFile);

29
ICSharpCode.NRefactory.ConsistencyCheck/IDStringConsistencyCheck.cs → ICSharpCode.NRefactory.ConsistencyCheck/TypeSystemTests.cs

@ -25,9 +25,9 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -25,9 +25,9 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.ConsistencyCheck
{
public class IDStringConsistencyCheck
public class TypeSystemTests
{
public static void Run(Solution solution)
public static void IDStringConsistencyCheck(Solution solution)
{
foreach (var project in solution.Projects) {
var compilation = project.Compilation;
@ -51,5 +51,30 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck @@ -51,5 +51,30 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
if (resolvedEntity != entity)
throw new InvalidOperationException(id);
}
public static void ResolvedUnresolvedMembers(Solution solution)
{
foreach (var project in solution.Projects) {
var compilation = project.Compilation;
var context = new SimpleTypeResolveContext(compilation.MainAssembly);
foreach (var typeDef in compilation.MainAssembly.GetAllTypeDefinitions()) {
foreach (var part in typeDef.Parts) {
if (!typeDef.Equals(part.Resolve(context)))
throw new InvalidOperationException();
}
foreach (var member in typeDef.Members) {
var resolvedMember = member.UnresolvedMember.Resolve(context);
if (!member.Equals(resolvedMember))
throw new InvalidOperationException();
}
// Include (potentially specialized) inherited members when testing ToMemberReference()
foreach (var member in typeDef.GetMembers()) {
var resolvedMember = member.ToMemberReference().Resolve(context);
if (!member.Equals(resolvedMember))
throw new InvalidOperationException();
}
}
}
}
}
}

36
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -189,6 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -189,6 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(1, constraint.TypeParameterCount);
Assert.AreEqual(1, constraint.TypeArguments.Count);
Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]);
Assert.AreSame(m.TypeParameters[0], m.Parameters[0].Type);
}
[Test]
@ -210,6 +211,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -210,6 +211,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(1, constraint.TypeParameterCount);
Assert.AreEqual(1, constraint.TypeArguments.Count);
Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]);
Assert.AreSame(m.TypeParameters[0], m.Parameters[0].Type);
}
[Test]
@ -238,6 +240,38 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -238,6 +240,38 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(m12, m2);
}
[Test]
public void Specialized_GetIndex_ToTypeReference()
{
var method = compilation.FindType(typeof(GenericClass<string, object>)).GetMethods(m => m.Name == "GetIndex").Single();
Assert.AreSame(method.TypeParameters[0], method.Parameters[0].Type);
Assert.AreSame(method, method.TypeParameters[0].Owner);
Assert.IsInstanceOf<SpecializedMethod>(method);
Assert.AreEqual(0, ((SpecializedMethod)method).TypeArguments.Count); // the method itself is not specialized
var methodReference = method.ToMemberReference();
var resolvedMethod = methodReference.Resolve(compilation.TypeResolveContext);
Assert.AreEqual(method, resolvedMethod);
}
[Test]
public void Specialized_GetIndex_SpecializeWithIdentityHasNoEffect()
{
var genericClass = compilation.FindType(typeof(GenericClass<string, object>));
IType[] methodTypeArguments = { DummyTypeParameter.GetMethodTypeParameter(0) };
var method = (SpecializedMethod)genericClass.GetMethods(methodTypeArguments, m => m.Name == "GetIndex").Single();
// GenericClass<string,object>.GetIndex<!!0>()
Assert.AreSame(method, method.TypeParameters[0].Owner);
Assert.AreNotEqual(method.TypeParameters[0], method.TypeArguments[0]);
Assert.IsNull(((ITypeParameter)method.TypeArguments[0]).Owner);
// Now apply identity substitution:
var method2 = new SpecializedMethod(method, TypeParameterSubstitution.Identity);
Assert.AreSame(method2, method2.TypeParameters[0].Owner);
Assert.AreNotEqual(method2.TypeParameters[0], method2.TypeArguments[0]);
Assert.IsNull(((ITypeParameter)method2.TypeArguments[0]).Owner);
Assert.AreEqual(method, method2);
}
[Test]
public void GenericEnum()
{
@ -726,7 +760,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -726,7 +760,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(1.0, arg.ConstantValue);
}
[Test, Ignore("Getting implicit interface implementations is not yet implemented.")]
[Test]
public void ImplicitImplementationOfUnifiedMethods()
{
ITypeDefinition type = GetTypeDefinition(typeof(ImplementationOfUnifiedMethods));

4
ICSharpCode.NRefactory/Documentation/IdStringMemberReference.cs

@ -55,6 +55,10 @@ namespace ICSharpCode.NRefactory.Documentation @@ -55,6 +55,10 @@ namespace ICSharpCode.NRefactory.Documentation
}
}
public ITypeReference DeclaringTypeReference {
get { return declaringTypeReference; }
}
public IMember Resolve(ITypeResolveContext context)
{
IType declaringType = declaringTypeReference.Resolve(context);

5
ICSharpCode.NRefactory/Documentation/IdStringProvider.cs

@ -184,6 +184,11 @@ namespace ICSharpCode.NRefactory.Documentation @@ -184,6 +184,11 @@ namespace ICSharpCode.NRefactory.Documentation
/// <param name="memberIdString">The ID string representing the member (with "M:", "F:", "P:" or "E:" prefix).</param>
/// <returns>A member reference that represents the ID string.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
/// <remarks>
/// The member reference will look in <see cref="ITypeResolveContext.CurrentAssembly"/> first,
/// and if the member is not found there,
/// it will look in all other assemblies of the compilation.
/// </remarks>
public static IMemberReference ParseMemberIdString(string memberIdString)
{
if (memberIdString == null)

12
ICSharpCode.NRefactory/TypeSystem/IEvent.cs

@ -31,6 +31,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -31,6 +31,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
IUnresolvedMethod AddAccessor { get; }
IUnresolvedMethod RemoveAccessor { get; }
IUnresolvedMethod InvokeAccessor { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="Implementation.SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IEvent Resolve(ITypeResolveContext context);
}
public interface IEvent : IMember

12
ICSharpCode.NRefactory/TypeSystem/IField.cs

@ -42,6 +42,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -42,6 +42,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool IsConst { get; }
IConstantValue ConstantValue { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="Implementation.SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IField Resolve(ITypeResolveContext context);
}
/// <summary>

39
ICSharpCode.NRefactory/TypeSystem/IMember.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -27,7 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Method/field/property/event.
/// </summary>
public interface IUnresolvedMember : IUnresolvedEntity
public interface IUnresolvedMember : IUnresolvedEntity, IMemberReference
{
/// <summary>
/// Gets the return type of this member.
@ -62,14 +62,47 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -62,14 +62,47 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
bool IsOverridable { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="Implementation.SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IMember Resolve(ITypeResolveContext context);
/// <summary>
/// Creates the resolved member.
/// </summary>
/// <param name="context">
/// The language-specific context that includes the parent type definition.
/// <see cref="IUnresolvedTypeDefinition.CreateResolveContext"/>
/// </param>
IMember CreateResolved(ITypeResolveContext context);
}
public interface IMemberReference
{
/// <summary>
/// Gets the declaring type reference for the member.
/// </summary>
ITypeReference DeclaringTypeReference { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context to use for resolving this member reference.
/// Which kind of context is required depends on the which kind of member reference this is;
/// please consult the documentation of the method that was used to create this member reference,
/// or that of the class implementing this method.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
IMember Resolve(ITypeResolveContext context);
}
@ -132,6 +165,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -132,6 +165,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Creates a member reference that can be used to rediscover this member in another compilation.
/// </summary>
/// <remarks>
/// If this member is specialized using open generic types, the resulting member reference will need to be looked up in an appropriate generic context.
/// Otherwise, the main resolve context of a compilation is sufficient.
/// </remarks>
IMemberReference ToMemberReference();
}
}

12
ICSharpCode.NRefactory/TypeSystem/IMethod.cs

@ -38,6 +38,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -38,6 +38,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool IsPartialMethodDeclaration { get; }
bool IsPartialMethodImplementation { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="Implementation.SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IMethod Resolve(ITypeResolveContext context);
}
/// <summary>

12
ICSharpCode.NRefactory/TypeSystem/IProperty.cs

@ -32,6 +32,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -32,6 +32,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
IUnresolvedMethod Setter { get; }
bool IsIndexer { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="Implementation.SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IProperty Resolve(ITypeResolveContext context);
}
/// <summary>

4
ICSharpCode.NRefactory/TypeSystem/IType.cs

@ -107,8 +107,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -107,8 +107,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Creates a type reference that can be used to look up a type equivalent to this type in another compilation.
/// </summary>
/// <remarks>
/// If this type is open, the resulting type reference will need to be looked up in an appropriate generic context.
/// If this type is closed, the resulting type reference can be looked up in the main resolve context of another compilation.
/// If this type contains open generics, the resulting type reference will need to be looked up in an appropriate generic context.
/// Otherwise, the main resolve context of a compilation is sufficient.
/// </remarks>
ITypeReference ToTypeReference();

24
ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs

@ -49,12 +49,34 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -49,12 +49,34 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool? HasExtensionMethods { get; }
/// <summary>
/// Creates a type resolve context for this part of the type definition.
/// Looks up the resolved type definition from the <paramref name="context"/> corresponding to this unresolved
/// type definition.
/// </summary>
/// <param name="context">
/// Context for looking up the type. The context must specify the current assembly.
/// A <see cref="Implementation.SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved type definition.
/// In case of an error, returns an <see cref="Implementation.UnknownType"/> instance.
/// Never returns null.
/// </returns>
new IType Resolve(ITypeResolveContext context);
/// <summary>
/// This method is used to add language-specific elements like the C# UsingScope
/// to the type resolve context.
/// </summary>
/// <param name="parentContext">The parent context (e.g. the parent assembly),
/// including the parent type definition for inner classes.</param>
/// <returns>
/// The parent context, modified to include language-specific elements (e.g. using scope)
/// associated with this type definition.
/// </returns>
/// <remarks>
/// Use <c>unresolvedTypeDef.CreateResolveContext(parentContext).WithTypeDefinition(typeDef)</c> to
/// create the context for use within the type definition.
/// </remarks>
ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext);
}

8
ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs

@ -34,12 +34,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -34,12 +34,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
// Keep this interface simple: I decided against having GetMethods/GetEvents etc. here,
// so that the Resolve step is never hidden from the consumer.
// I decided against implementing IFreezable here: ITypeDefinition can be used as ITypeReference,
// I decided against implementing IFreezable here: IUnresolvedTypeDefinition can be used as ITypeReference,
// but when freezing the reference, one wouldn't expect the definition to freeze.
/// <summary>
/// Resolves this type reference.
/// </summary>
/// <param name="context">
/// Context to use for resolving this type reference.
/// Which kind of context is required depends on the which kind of type reference this is;
/// please consult the documentation of the method that was used to create this type reference,
/// or that of the class implementing this method.
/// </param>
/// <returns>
/// Returns the resolved type.
/// In case of an error, returns <see cref="SpecialType.UnknownType"/>.

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

@ -319,7 +319,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -319,7 +319,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override string ToString()
{
return this.ReflectionName;
return this.ReflectionName + " (owner=" + owner + ")";
}
}
}

128
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@ -83,7 +84,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -83,7 +84,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
/*
public IList<IMemberReference> InterfaceImplementations {
public IList<IMemberReference> ExplicitInterfaceImplementations {
get {
RareFields rareFields = (RareFields)this.rareFields;
if (rareFields == null || rareFields.interfaceImplementations == null) {
@ -125,6 +126,131 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -125,6 +126,131 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
}
ITypeReference IMemberReference.DeclaringTypeReference {
get { return this.DeclaringTypeDefinition; }
}
#region Resolve
public abstract IMember CreateResolved(ITypeResolveContext context);
public virtual IMember Resolve(ITypeResolveContext context)
{
ITypeReference interfaceTypeReference = null;
if (this.IsExplicitInterfaceImplementation && this.ExplicitInterfaceImplementations.Count == 1)
interfaceTypeReference = this.ExplicitInterfaceImplementations[0].DeclaringTypeReference;
return Resolve(ExtendContextForType(context, this.DeclaringTypeDefinition), this.EntityType, this.Name, interfaceTypeReference);
}
protected static ITypeResolveContext ExtendContextForType(ITypeResolveContext assemblyContext, IUnresolvedTypeDefinition typeDef)
{
if (typeDef == null)
return assemblyContext;
ITypeResolveContext parentContext;
if (typeDef.DeclaringTypeDefinition != null)
parentContext = ExtendContextForType(assemblyContext, typeDef.DeclaringTypeDefinition);
else
parentContext = assemblyContext;
ITypeDefinition resolvedTypeDef = typeDef.Resolve(assemblyContext).GetDefinition();
return typeDef.CreateResolveContext(parentContext).WithCurrentTypeDefinition(resolvedTypeDef);
}
public static IMember Resolve(ITypeResolveContext context,
EntityType entityType,
string name,
ITypeReference explicitInterfaceTypeReference = null,
IList<string> typeParameterNames = null,
IList<ITypeReference> parameterTypeReferences = null)
{
if (context.CurrentTypeDefinition == null)
return null;
if (parameterTypeReferences == null)
parameterTypeReferences = EmptyList<ITypeReference>.Instance;
if (typeParameterNames == null || typeParameterNames.Count == 0) {
// non-generic member
// In this case, we can simply resolve the parameter types in the given context
var parameterTypes = parameterTypeReferences.Resolve(context);
if (explicitInterfaceTypeReference == null) {
foreach (IMember member in context.CurrentTypeDefinition.Members) {
if (member.IsExplicitInterfaceImplementation)
continue;
if (IsNonGenericMatch(member, entityType, name, parameterTypes))
return member;
}
} else {
IType explicitInterfaceType = explicitInterfaceTypeReference.Resolve(context);
foreach (IMember member in context.CurrentTypeDefinition.Members) {
if (!member.IsExplicitInterfaceImplementation)
continue;
if (member.ImplementedInterfaceMembers.Count != 1)
continue;
if (IsNonGenericMatch(member, entityType, name, parameterTypes)) {
if (explicitInterfaceType.Equals(member.ImplementedInterfaceMembers[0].DeclaringType))
return member;
}
}
}
} else {
// generic member
// In this case, we must specify the correct context for resolving the parameter types
foreach (IMethod method in context.CurrentTypeDefinition.Methods) {
if (method.EntityType != entityType)
continue;
if (method.Name != name)
continue;
if (method.Parameters.Count != parameterTypeReferences.Count)
continue;
// Compare type parameter count and names:
if (!typeParameterNames.SequenceEqual(method.TypeParameters.Select(tp => tp.Name)))
continue;
// Once we know the type parameter names are fitting, we can resolve the
// type references in the context of the method:
var contextForMethod = context.WithCurrentMember(method);
var parameterTypes = parameterTypeReferences.Resolve(contextForMethod);
if (!IsParameterTypeMatch(method, parameterTypes))
continue;
if (explicitInterfaceTypeReference == null) {
if (!method.IsExplicitInterfaceImplementation)
return method;
} else if (method.IsExplicitInterfaceImplementation && method.ImplementedInterfaceMembers.Count == 1) {
IType explicitInterfaceType = explicitInterfaceTypeReference.Resolve(contextForMethod);
if (explicitInterfaceTypeReference.Equals(method.ImplementedInterfaceMembers[0].DeclaringType))
return method;
}
}
}
return null;
}
static bool IsNonGenericMatch(IMember member, EntityType entityType, string name, IList<IType> parameterTypes)
{
if (member.EntityType != entityType)
return false;
if (member.Name != name)
return false;
IMethod method = member as IMethod;
if (method != null && method.TypeParameters.Count > 0)
return false;
return IsParameterTypeMatch(member, parameterTypes);
}
static bool IsParameterTypeMatch(IMember member, IList<IType> parameterTypes)
{
IParameterizedMember parameterizedMember = member as IParameterizedMember;
if (parameterizedMember == null) {
return parameterTypes.Count == 0;
} else if (parameterTypes.Count == parameterizedMember.Parameters.Count) {
for (int i = 0; i < parameterTypes.Count; i++) {
IType type1 = parameterTypes[i];
IType type2 = parameterizedMember.Parameters[i].Type;
if (!type1.Equals(type2)) {
return false;
}
}
return true;
} else {
return false;
}
}
#endregion
}
}

16
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs

@ -26,6 +26,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -26,6 +26,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// References an entity by its type and name.
/// This class can be used to refer to fields, events, and parameterless properties.
/// </summary>
/// <remarks>
/// Resolving a DefaultMemberReference requires a context that provides enough information for resolving the declaring type reference
/// and the parameter types references.
/// </remarks>
[Serializable]
public sealed class DefaultMemberReference : IMemberReference, ISupportsInterning
{
@ -50,6 +54,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -50,6 +54,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.parameterTypes = parameterTypes ?? EmptyList<ITypeReference>.Instance;
}
public ITypeReference DeclaringTypeReference {
get { return typeReference; }
}
public IMember Resolve(ITypeResolveContext context)
{
IType type = typeReference.Resolve(context);
@ -66,14 +74,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -66,14 +74,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
var resolvedParameterTypes = parameterTypes.Resolve(context);
foreach (IMember member in members) {
IParameterizedMember parameterizedMember = member as IParameterizedMember;
if (parameterTypes.Count == 0) {
if (parameterizedMember == null || parameterizedMember.Parameters.Count == 0)
if (parameterizedMember == null) {
if (parameterTypes.Count == 0)
return member;
} else if (parameterTypes.Count == parameterizedMember.Parameters.Count) {
bool signatureMatches = true;
for (int i = 0; i < parameterTypes.Count; i++) {
IType type1 = ParameterListComparer.Instance.NormalizeMethodTypeParameters(resolvedParameterTypes[i]);
IType type2 = ParameterListComparer.Instance.NormalizeMethodTypeParameters(parameterizedMember.Parameters[i].Type);
IType type1 = DummyTypeParameter.NormalizeAllTypeParameters(resolvedParameterTypes[i]);
IType type2 = DummyTypeParameter.NormalizeAllTypeParameters(parameterizedMember.Parameters[i].Type);
if (!type1.Equals(type2)) {
signatureMatches = false;
break;

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

@ -118,7 +118,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -118,7 +118,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append("params ");
b.Append(parameter.Name);
b.Append(':');
b.Append(parameter.Type.ToString());
b.Append(parameter.Type.ReflectionName);
if (parameter.IsOptional) {
b.Append(" = ");
if (parameter.ConstantValue != null)

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

@ -260,8 +260,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -260,8 +260,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.unresolvedTypeDict = unresolved.GetTypeDictionary(compilation.NameComparer);
this.rootNamespace = new NS(this, unresolved.GetUnresolvedRootNamespace(compilation.NameComparer), null);
this.context = new SimpleTypeResolveContext(this);
this.AssemblyAttributes = unresolved.AssemblyAttributes.ToList().CreateResolvedAttributes(context);
this.ModuleAttributes = unresolved.ModuleAttributes.ToList().CreateResolvedAttributes(context);
this.AssemblyAttributes = unresolved.AssemblyAttributes.CreateResolvedAttributes(context);
this.ModuleAttributes = unresolved.ModuleAttributes.CreateResolvedAttributes(context);
}
public IUnresolvedAssembly UnresolvedAssembly {

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

@ -98,5 +98,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -98,5 +98,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
return new DefaultResolvedEvent(this, context);
}
IEvent IUnresolvedEvent.Resolve(ITypeResolveContext context)
{
return (IEvent)Resolve(context);
}
}
}

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

@ -86,5 +86,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -86,5 +86,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
return new DefaultResolvedField(this, context);
}
IField IUnresolvedField.Resolve(ITypeResolveContext context)
{
return (IField)Resolve(context);
}
}
}

17
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@ -147,6 +148,22 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -147,6 +148,22 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return new DefaultResolvedMethod(this, context);
}
public override IMember Resolve(ITypeResolveContext context)
{
ITypeReference interfaceTypeReference = null;
if (this.IsExplicitInterfaceImplementation && this.ExplicitInterfaceImplementations.Count == 1)
interfaceTypeReference = this.ExplicitInterfaceImplementations[0].DeclaringTypeReference;
return Resolve(ExtendContextForType(context, this.DeclaringTypeDefinition),
this.EntityType, this.Name, interfaceTypeReference,
this.TypeParameters.Select(tp => tp.Name).ToList(),
this.Parameters.Select(p => p.Type).ToList());
}
IMethod IUnresolvedMethod.Resolve(ITypeResolveContext context)
{
return (IMethod)Resolve(context);
}
public static DefaultUnresolvedMethod CreateDefaultConstructor(IUnresolvedTypeDefinition typeDefinition)
{
if (typeDefinition == null)

16
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
@ -100,5 +101,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -100,5 +101,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
return new DefaultResolvedProperty(this, context);
}
public override IMember Resolve(ITypeResolveContext context)
{
ITypeReference interfaceTypeReference = null;
if (this.IsExplicitInterfaceImplementation && this.ExplicitInterfaceImplementations.Count == 1)
interfaceTypeReference = this.ExplicitInterfaceImplementations[0].DeclaringTypeReference;
return Resolve(ExtendContextForType(context, this.DeclaringTypeDefinition),
this.EntityType, this.Name, interfaceTypeReference,
parameterTypeReferences: this.Parameters.Select(p => p.Type).ToList());
}
IProperty IUnresolvedProperty.Resolve(ITypeResolveContext context)
{
return (IProperty)Resolve(context);
}
}
}

61
ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs

@ -61,6 +61,62 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -61,6 +61,62 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return tps[index];
}
sealed class NormalizeMethodTypeParametersVisitor : TypeVisitor
{
public override IType VisitTypeParameter(ITypeParameter type)
{
if (type.OwnerType == EntityType.Method) {
return DummyTypeParameter.GetMethodTypeParameter(type.Index);
} else {
return base.VisitTypeParameter(type);
}
}
}
sealed class NormalizeClassTypeParametersVisitor : TypeVisitor
{
public override IType VisitTypeParameter(ITypeParameter type)
{
if (type.OwnerType == EntityType.TypeDefinition) {
return DummyTypeParameter.GetClassTypeParameter(type.Index);
} else {
return base.VisitTypeParameter(type);
}
}
}
static readonly NormalizeMethodTypeParametersVisitor normalizeMethodTypeParameters = new NormalizeMethodTypeParametersVisitor();
static readonly NormalizeClassTypeParametersVisitor normalizeClassTypeParameters = new NormalizeClassTypeParametersVisitor();
/// <summary>
/// Replaces all occurrences of method type parameters in the given type
/// by normalized type parameters. This allows comparing parameter types from different
/// generic methods.
/// </summary>
public static IType NormalizeMethodTypeParameters(IType type)
{
return type.AcceptVisitor(normalizeMethodTypeParameters);
}
/// <summary>
/// Replaces all occurrences of class type parameters in the given type
/// by normalized type parameters. This allows comparing parameter types from different
/// generic methods.
/// </summary>
public static IType NormalizeClassTypeParameters(IType type)
{
return type.AcceptVisitor(normalizeClassTypeParameters);
}
/// <summary>
/// Replaces all occurrences of class and method type parameters in the given type
/// by normalized type parameters. This allows comparing parameter types from different
/// generic methods.
/// </summary>
public static IType NormalizeAllTypeParameters(IType type)
{
return type.AcceptVisitor(normalizeClassTypeParameters).AcceptVisitor(normalizeMethodTypeParameters);
}
readonly EntityType ownerType;
readonly int index;
@ -95,6 +151,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -95,6 +151,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return new TypeParameterReference(ownerType, index);
}
public override IType AcceptVisitor(TypeVisitor visitor)
{
return visitor.VisitTypeParameter(this);
}
public int Index {
get { return index; }
}

9
ICSharpCode.NRefactory/TypeSystem/Implementation/ExplicitInterfaceImplementationMemberReference.cs

@ -24,6 +24,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -24,6 +24,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// <summary>
/// References a member that is an explicit interface implementation.
/// </summary>
/// <remarks>
/// Resolving an ExplicitInterfaceImplementationMemberReference requires a context
/// that provides enough information for resolving the declaring type reference
/// and the interface member reference.
/// </remarks>
[Serializable]
public sealed class ExplicitInterfaceImplementationMemberReference : IMemberReference
{
@ -40,6 +45,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -40,6 +45,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.interfaceMemberReference = interfaceMemberReference;
}
public ITypeReference DeclaringTypeReference {
get { return typeReference; }
}
public IMember Resolve(ITypeResolveContext context)
{
IMember interfaceMember = interfaceMemberReference.Resolve(context);

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

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
: base(eventDefinition)
{
AddSubstitution(substitution);
this.eventDefinition = (IEvent)base.MemberDefinition;
this.eventDefinition = (IEvent)base.baseMember;
}
public bool CanAdd {

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

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
: base(fieldDefinition)
{
AddSubstitution(substitution);
this.fieldDefinition = (IField)base.MemberDefinition;
this.fieldDefinition = (IField)base.baseMember;
}
public bool IsReadOnly {

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

@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary>
public abstract class SpecializedMember : IMember
{
readonly IMember memberDefinition;
protected readonly IMember baseMember;
TypeParameterSubstitution substitution;
IType declaringType;
@ -45,10 +45,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -45,10 +45,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
SpecializedMember sm = memberDefinition as SpecializedMember;
if (sm != null) {
this.memberDefinition = sm.memberDefinition;
this.baseMember = sm.baseMember;
this.substitution = sm.substitution;
} else {
this.memberDefinition = memberDefinition;
this.baseMember = memberDefinition;
this.substitution = TypeParameterSubstitution.Identity;
}
}
@ -80,15 +80,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -80,15 +80,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
}
public IMemberReference ToMemberReference()
public virtual IMemberReference ToMemberReference()
{
return new SpecializingMemberReference(
memberDefinition.ToMemberReference(),
baseMember.ToMemberReference(),
ToTypeReference(substitution.ClassTypeArguments),
ToTypeReference(substitution.MethodTypeArguments));
null);
}
static IList<ITypeReference> ToTypeReference(IList<IType> typeArguments)
internal static IList<ITypeReference> ToTypeReference(IList<IType> typeArguments)
{
if (typeArguments == null)
return null;
@ -119,7 +119,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -119,7 +119,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
var result = LazyInit.VolatileRead(ref this.declaringType);
if (result != null)
return result;
IType definitionDeclaringType = memberDefinition.DeclaringType;
IType definitionDeclaringType = baseMember.DeclaringType;
ITypeDefinition definitionDeclaringTypeDef = definitionDeclaringType as ITypeDefinition;
if (definitionDeclaringTypeDef != null && definitionDeclaringType.TypeParameterCount > 0) {
if (substitution.ClassTypeArguments != null && substitution.ClassTypeArguments.Count == definitionDeclaringType.TypeParameterCount) {
@ -144,11 +144,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -144,11 +144,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public IMember MemberDefinition {
get { return memberDefinition.MemberDefinition; }
get { return baseMember.MemberDefinition; }
}
public IUnresolvedMember UnresolvedMember {
get { return memberDefinition.UnresolvedMember; }
get { return baseMember.UnresolvedMember; }
}
public IType ReturnType {
@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (result != null)
return result;
else
return LazyInit.GetOrSet(ref this.returnType, memberDefinition.ReturnType.AcceptVisitor(substitution));
return LazyInit.GetOrSet(ref this.returnType, baseMember.ReturnType.AcceptVisitor(substitution));
}
protected set {
// This setter is used for LiftedUserDefinedOperator, a special case of specialized member
@ -170,35 +170,35 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -170,35 +170,35 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public bool IsVirtual {
get { return memberDefinition.IsVirtual; }
get { return baseMember.IsVirtual; }
}
public bool IsOverride {
get { return memberDefinition.IsOverride; }
get { return baseMember.IsOverride; }
}
public bool IsOverridable {
get { return memberDefinition.IsOverridable; }
get { return baseMember.IsOverridable; }
}
public EntityType EntityType {
get { return memberDefinition.EntityType; }
get { return baseMember.EntityType; }
}
public DomRegion Region {
get { return memberDefinition.Region; }
get { return baseMember.Region; }
}
public DomRegion BodyRegion {
get { return memberDefinition.BodyRegion; }
get { return baseMember.BodyRegion; }
}
public ITypeDefinition DeclaringTypeDefinition {
get { return memberDefinition.DeclaringTypeDefinition; }
get { return baseMember.DeclaringTypeDefinition; }
}
public IList<IAttribute> Attributes {
get { return memberDefinition.Attributes; }
get { return baseMember.Attributes; }
}
IList<IMember> implementedInterfaceMembers;
@ -211,7 +211,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -211,7 +211,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IList<IMember> FindImplementedInterfaceMembers()
{
var definitionImplementations = memberDefinition.ImplementedInterfaceMembers;
var definitionImplementations = baseMember.ImplementedInterfaceMembers;
IMember[] result = new IMember[definitionImplementations.Count];
for (int i = 0; i < result.Length; i++) {
result[i] = SpecializedMember.Create(definitionImplementations[i], substitution);
@ -220,83 +220,83 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -220,83 +220,83 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public bool IsExplicitInterfaceImplementation {
get { return memberDefinition.IsExplicitInterfaceImplementation; }
get { return baseMember.IsExplicitInterfaceImplementation; }
}
public DocumentationComment Documentation {
get { return memberDefinition.Documentation; }
get { return baseMember.Documentation; }
}
public Accessibility Accessibility {
get { return memberDefinition.Accessibility; }
get { return baseMember.Accessibility; }
}
public bool IsStatic {
get { return memberDefinition.IsStatic; }
get { return baseMember.IsStatic; }
}
public bool IsAbstract {
get { return memberDefinition.IsAbstract; }
get { return baseMember.IsAbstract; }
}
public bool IsSealed {
get { return memberDefinition.IsSealed; }
get { return baseMember.IsSealed; }
}
public bool IsShadowing {
get { return memberDefinition.IsShadowing; }
get { return baseMember.IsShadowing; }
}
public bool IsSynthetic {
get { return memberDefinition.IsSynthetic; }
get { return baseMember.IsSynthetic; }
}
public bool IsPrivate {
get { return memberDefinition.IsPrivate; }
get { return baseMember.IsPrivate; }
}
public bool IsPublic {
get { return memberDefinition.IsPublic; }
get { return baseMember.IsPublic; }
}
public bool IsProtected {
get { return memberDefinition.IsProtected; }
get { return baseMember.IsProtected; }
}
public bool IsInternal {
get { return memberDefinition.IsInternal; }
get { return baseMember.IsInternal; }
}
public bool IsProtectedOrInternal {
get { return memberDefinition.IsProtectedOrInternal; }
get { return baseMember.IsProtectedOrInternal; }
}
public bool IsProtectedAndInternal {
get { return memberDefinition.IsProtectedAndInternal; }
get { return baseMember.IsProtectedAndInternal; }
}
public string FullName {
get { return memberDefinition.FullName; }
get { return baseMember.FullName; }
}
public string Name {
get { return memberDefinition.Name; }
get { return baseMember.Name; }
}
public string Namespace {
get { return memberDefinition.Namespace; }
get { return baseMember.Namespace; }
}
public string ReflectionName {
get { return memberDefinition.ReflectionName; }
get { return baseMember.ReflectionName; }
}
public ICompilation Compilation {
get { return memberDefinition.Compilation; }
get { return baseMember.Compilation; }
}
public IAssembly ParentAssembly {
get { return memberDefinition.ParentAssembly; }
get { return baseMember.ParentAssembly; }
}
public override bool Equals(object obj)
@ -304,13 +304,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -304,13 +304,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
SpecializedMember other = obj as SpecializedMember;
if (other == null)
return false;
return this.memberDefinition.Equals(other.memberDefinition) && this.substitution.Equals(other.substitution);
return this.baseMember.Equals(other.baseMember) && this.substitution.Equals(other.substitution);
}
public override int GetHashCode()
{
unchecked {
return 1000000007 * memberDefinition.GetHashCode() + 1000000009 * substitution.GetHashCode();
return 1000000007 * baseMember.GetHashCode() + 1000000009 * substitution.GetHashCode();
}
}
@ -358,7 +358,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -358,7 +358,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
protected IList<IParameter> CreateParameters(TypeVisitor substitution)
{
var paramDefs = ((IParameterizedMember)this.MemberDefinition).Parameters;
var paramDefs = ((IParameterizedMember)this.baseMember).Parameters;
if (paramDefs.Count == 0) {
return EmptyList<IParameter>.Instance;
} else {
@ -380,7 +380,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -380,7 +380,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
StringBuilder b = new StringBuilder("[");
b.Append(GetType().Name);
b.Append(' ');
b.Append(this.DeclaringType.ToString());
b.Append(this.DeclaringType.ReflectionName);
b.Append('.');
b.Append(this.Name);
b.Append('(');
@ -389,7 +389,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -389,7 +389,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append(this.Parameters[i].ToString());
}
b.Append("):");
b.Append(this.ReturnType.ToString());
b.Append(this.ReturnType.ReflectionName);
b.Append(']');
return b.ToString();
}

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

@ -33,28 +33,46 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -33,28 +33,46 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
readonly IMethod methodDefinition;
readonly ITypeParameter[] specializedTypeParameters;
readonly bool genericMethodIsSpecialized;
readonly TypeParameterSubstitution substitutionWithoutSpecializedTypeParameters;
public SpecializedMethod(IMethod methodDefinition, TypeParameterSubstitution substitution)
: base(methodDefinition)
{
SpecializedMethod specializedMethodDefinition = methodDefinition as SpecializedMethod;
if (specializedMethodDefinition != null)
this.genericMethodIsSpecialized = specializedMethodDefinition.genericMethodIsSpecialized;
// The base ctor might have unpacked a SpecializedMember
// (in case we are specializing an already-specialized method)
methodDefinition = (IMethod)base.MemberDefinition;
methodDefinition = (IMethod)base.baseMember;
this.methodDefinition = methodDefinition;
if (methodDefinition.TypeParameters.Any(ConstraintNeedsSpecialization)) {
// The method is generic, and we need to specialize the type parameters
if (methodDefinition.TypeParameters.Count > 0) {
// The method is generic, so we need to specialize the type parameters
// (for specializing the constraints, and also to set the correct Owner)
specializedTypeParameters = new ITypeParameter[methodDefinition.TypeParameters.Count];
for (int i = 0; i < specializedTypeParameters.Length; i++) {
ITypeParameter tp = methodDefinition.TypeParameters[i];
if (ConstraintNeedsSpecialization(tp))
tp = new SpecializedTypeParameter(tp, this);
specializedTypeParameters[i] = tp;
specializedTypeParameters[i] = new SpecializedTypeParameter(methodDefinition.TypeParameters[i], this);
}
if (!genericMethodIsSpecialized) {
// Add substitution that replaces the base method's type parameters with our specialized version
// but do this only if the type parameters on the baseMember have not already been substituted
substitutionWithoutSpecializedTypeParameters = this.Substitution;
AddSubstitution(new TypeParameterSubstitution(null, specializedTypeParameters));
}
// add substitution that replaces the base method's type parameters with our specialized version
AddSubstitution(new TypeParameterSubstitution(null, specializedTypeParameters));
}
// Add the main substitution after the method type parameter specialization.
AddSubstitution(substitution);
if (substitutionWithoutSpecializedTypeParameters != null) {
// If we already have a substitution without specialized type parameters, update that:
substitutionWithoutSpecializedTypeParameters = TypeParameterSubstitution.Compose(substitution, substitutionWithoutSpecializedTypeParameters);
} else {
// Otherwise just use the whole substitution, as that doesn't contain specialized type parameters
// in this case.
substitutionWithoutSpecializedTypeParameters = this.Substitution;
}
if (substitution != null && substitution.MethodTypeArguments != null && methodDefinition.TypeParameters.Count > 0)
this.genericMethodIsSpecialized = true;
if (specializedTypeParameters != null) {
// Set the substitution on the type parameters to the final composed substitution
foreach (var tp in specializedTypeParameters.OfType<SpecializedTypeParameter>()) {
@ -64,30 +82,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -64,30 +82,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
}
static bool ConstraintNeedsSpecialization(ITypeParameter tp)
{
// TODO: can we avoid specialization if a type parameter doesn't have any constraints?
return true;
}
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;
}
/// <summary>
/// Gets the type arguments passed to this method.
/// If only the type parameters for the class were specified and the generic method
/// itself is not specialized yet, this property will return an empty list.
/// </summary>
public IList<IType> TypeArguments {
get { return this.Substitution.MethodTypeArguments ?? EmptyList<IType>.Instance; }
get { return genericMethodIsSpecialized ? this.Substitution.MethodTypeArguments : EmptyList<IType>.Instance; }
}
public IList<IUnresolvedMethod> Parts {
@ -120,19 +121,57 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -120,19 +121,57 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return methodDefinition.IsOperator; }
}
public override IMemberReference ToMemberReference()
{
// Pass the MethodTypeArguments to the SpecializingMemberReference only if
// the generic method itself is specialized, not if the generic method is only
// specialized with class type arguments.
// This is necessary due to this part of the ToMemberReference() contract:
// If this member is specialized using open generic types, the resulting member reference will need to be looked up in an appropriate generic context.
// Otherwise, the main resolve context of a compilation is sufficient.
// ->
// This means that if the method itself isn't specialized,
// we must not include TypeParameterReferences for the specialized type parameters
// in the resulting member reference.
if (genericMethodIsSpecialized) {
return new SpecializingMemberReference(
baseMember.ToMemberReference(),
ToTypeReference(base.Substitution.ClassTypeArguments),
ToTypeReference(base.Substitution.MethodTypeArguments));
} else {
return base.ToMemberReference();
}
}
public override bool Equals(object obj)
{
SpecializedMethod other = obj as SpecializedMethod;
if (other == null)
return false;
return this.baseMember.Equals(other.baseMember) && this.substitutionWithoutSpecializedTypeParameters.Equals(other.substitutionWithoutSpecializedTypeParameters);
}
public override int GetHashCode()
{
unchecked {
return 1000000013 * baseMember.GetHashCode() + 1000000009 * substitutionWithoutSpecializedTypeParameters.GetHashCode();
}
}
public override string ToString()
{
StringBuilder b = new StringBuilder("[");
b.Append(GetType().Name);
b.Append(' ');
b.Append(this.DeclaringType.ToString());
b.Append(this.DeclaringType.ReflectionName);
b.Append('.');
b.Append(this.Name);
if (this.TypeArguments.Count > 0) {
b.Append('[');
for (int i = 0; i < this.TypeArguments.Count; i++) {
if (i > 0) b.Append(", ");
b.Append(this.TypeArguments[i].ToString());
b.Append(this.TypeArguments[i].ReflectionName);
}
b.Append(']');
}
@ -142,7 +181,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -142,7 +181,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append(this.Parameters[i].ToString());
}
b.Append("):");
b.Append(this.ReturnType.ToString());
b.Append(this.ReturnType.ReflectionName);
b.Append(']');
return b.ToString();
}
@ -169,6 +208,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -169,6 +208,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override bool Equals(IType other)
{
// Compare the owner, not the substitution, because the substitution may contain this specialized type parameter recursively
SpecializedTypeParameter o = other as SpecializedTypeParameter;
return o != null && baseTp.Equals(o.baseTp) && this.Owner.Equals(o.Owner);
}

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

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
: base(propertyDefinition)
{
AddSubstitution(substitution);
this.propertyDefinition = (IProperty)base.MemberDefinition;
this.propertyDefinition = (IProperty)base.baseMember;
}
public bool CanGet {

9
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializingMemberReference.cs

@ -48,5 +48,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -48,5 +48,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
)
);
}
public ITypeReference DeclaringTypeReference {
get {
if (classTypeArgumentReferences != null)
return new ParameterizedTypeReference(memberDefinitionReference.DeclaringTypeReference, classTypeArgumentReferences);
else
return memberDefinitionReference.DeclaringTypeReference;
}
}
}
}

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

@ -54,12 +54,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -54,12 +54,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// <summary>
/// Gets the list of class type arguments.
/// Returns <c>null</c> if this substitution keeps class type parameter unmodified.
/// Returns <c>null</c> if this substitution keeps class type parameters unmodified.
/// </summary>
public IList<IType> ClassTypeArguments {
get { return classTypeArguments; }
}
/// <summary>
/// Gets the list of method type arguments.
/// Returns <c>null</c> if this substitution keeps method type parameters unmodified.
/// </summary>
public IList<IType> MethodTypeArguments {
get { return methodTypeArguments; }
}
@ -170,7 +174,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -170,7 +174,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append('`');
b.Append(i);
b.Append(" -> ");
b.Append(classTypeArguments[i]);
b.Append(classTypeArguments[i].ReflectionName);
}
}
if (methodTypeArguments != null) {
@ -179,7 +183,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -179,7 +183,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append("``");
b.Append(i);
b.Append(" -> ");
b.Append(methodTypeArguments[i]);
b.Append(methodTypeArguments[i].ReflectionName);
}
}
b.Append(']');

30
ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs

@ -29,28 +29,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -29,28 +29,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <remarks>
/// 'ref int' and 'out int' are considered to be equal.
/// "Method{T}(T a)" and "Method{S}(S b)" are also considered equal.
/// However, "Method(T a)" and "Method(S b)" are not considered equal when the type parameters T and S belong to classes.
/// </remarks>
public sealed class ParameterListComparer : IEqualityComparer<IList<IParameter>>
{
public static readonly ParameterListComparer Instance = new ParameterListComparer();
// We want to consider the parameter lists "Method<T>(T a)" and "Method<S>(S b)" as equal.
// However, the parameter types are not considered equal, as T is a different type parameter than S.
// In order to compare the method signatures, we will normalize all method type parameters.
sealed class NormalizeMethodTypeParametersVisitor : TypeVisitor
{
public override IType VisitTypeParameter(ITypeParameter type)
{
if (type.OwnerType == EntityType.Method) {
return DummyTypeParameter.GetMethodTypeParameter(type.Index);
} else {
return base.VisitTypeParameter(type);
}
}
}
readonly NormalizeMethodTypeParametersVisitor normalization = new NormalizeMethodTypeParametersVisitor();
/// <summary>
/// Replaces all occurrences of method type parameters in the given type
/// by normalized type parameters. This allows comparing parameter types from different
@ -58,7 +42,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -58,7 +42,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
public IType NormalizeMethodTypeParameters(IType type)
{
return type.AcceptVisitor(normalization);
return DummyTypeParameter.NormalizeMethodTypeParameters(type);
}
public bool Equals(IList<IParameter> x, IList<IParameter> y)
@ -74,8 +58,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -74,8 +58,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
continue;
if (a == null || b == null)
return false;
IType aType = a.Type.AcceptVisitor(normalization);
IType bType = b.Type.AcceptVisitor(normalization);
// We want to consider the parameter lists "Method<T>(T a)" and "Method<S>(S b)" as equal.
// However, the parameter types are not considered equal, as T is a different type parameter than S.
// In order to compare the method signatures, we will normalize all method type parameters.
IType aType = DummyTypeParameter.NormalizeMethodTypeParameters(a.Type);
IType bType = DummyTypeParameter.NormalizeMethodTypeParameters(b.Type);
if (!aType.Equals(bType))
return false;
@ -89,7 +77,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -89,7 +77,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
unchecked {
foreach (IParameter p in obj) {
hashCode *= 27;
IType type = p.Type.AcceptVisitor(normalization);
IType type = DummyTypeParameter.NormalizeMethodTypeParameters(p.Type);
hashCode += type.GetHashCode();
}
}

Loading…
Cancel
Save