Browse Source

Added support for explicit method and property implementations to the cecil loader.

newNRvisualizers
erikkallen 13 years ago
parent
commit
7640141783
  1. 57
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs
  2. 4
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  3. 67
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  4. 42
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  5. 8
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs

57
ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs

@ -61,63 +61,6 @@ namespace ICSharpCode.NRefactory.CSharp.Parser @@ -61,63 +61,6 @@ namespace ICSharpCode.NRefactory.CSharp.Parser
Assert.AreEqual(compilation.FindType(KnownTypeCode.Array), typeRef.Resolve(compilation.TypeResolveContext));
}
[Test]
public void ExplicitDisposableImplementation()
{
ITypeDefinition disposable = GetTypeDefinition(typeof(NRefactory.TypeSystem.TestCase.ExplicitDisposableImplementation));
IMethod method = disposable.Methods.Single(m => m.Name == "Dispose");
Assert.IsTrue(method.IsExplicitInterfaceImplementation);
Assert.AreEqual("System.IDisposable.Dispose", method.ImplementedInterfaceMembers.Single().FullName);
}
[Test]
public void ExplicitGenericInterfaceImplementation()
{
ITypeDefinition impl = GetTypeDefinition(typeof(NRefactory.TypeSystem.TestCase.ExplicitGenericInterfaceImplementation));
IType genericInterfaceOfString = compilation.FindType(typeof(IGenericInterface<string>));
IMethod implMethod1 = impl.Methods.Single(m => m.Name == "Test" && !m.Parameters[1].IsRef);
IMethod implMethod2 = impl.Methods.Single(m => m.Name == "Test" && m.Parameters[1].IsRef);
Assert.IsTrue(implMethod1.IsExplicitInterfaceImplementation);
Assert.IsTrue(implMethod2.IsExplicitInterfaceImplementation);
IMethod interfaceMethod1 = (IMethod)implMethod1.ImplementedInterfaceMembers.Single();
Assert.AreEqual(genericInterfaceOfString, interfaceMethod1.DeclaringType);
Assert.IsTrue(!interfaceMethod1.Parameters[1].IsRef);
IMethod interfaceMethod2 = (IMethod)implMethod2.ImplementedInterfaceMembers.Single();
Assert.AreEqual(genericInterfaceOfString, interfaceMethod2.DeclaringType);
Assert.IsTrue(interfaceMethod2.Parameters[1].IsRef);
}
[Test]
public void ExplicitImplementationOfUnifiedMethods()
{
IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods<int, int>));
Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count());
foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) {
Assert.AreEqual(1, method.ImplementedInterfaceMembers.Count, method.ToString());
Assert.AreEqual("System.Int32", method.Parameters.Single().Type.ReflectionName);
IMethod interfaceMethod = (IMethod)method.ImplementedInterfaceMembers.Single();
Assert.AreEqual("System.Int32", interfaceMethod.Parameters.Single().Type.ReflectionName);
var genericParamType = ((IMethod)method.MemberDefinition).Parameters.Single().Type;
var interfaceGenericParamType = ((IMethod)interfaceMethod.MemberDefinition).Parameters.Single().Type;
Assert.AreEqual(TypeKind.TypeParameter, genericParamType.Kind);
Assert.AreEqual(TypeKind.TypeParameter, interfaceGenericParamType.Kind);
Assert.AreEqual(genericParamType.ReflectionName, interfaceGenericParamType.ReflectionName);
}
}
[Test]
public void ExplicitImplementationOfUnifiedMethods_ToMemberReference()
{
IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods<int, int>));
Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count());
foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) {
IMethod resolvedMethod = (IMethod)method.ToMemberReference().Resolve(compilation.TypeResolveContext);
Assert.AreEqual(method, resolvedMethod);
}
}
[Test]
public void PartialMethodWithImplementation()
{

4
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -249,6 +249,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -249,6 +249,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
public int Prop { get; set; }
}
public class ClassThatImplementsPropertyExplicitly : IInterfaceWithProperty {
int IInterfaceWithProperty.Prop { get; set; }
}
public interface IInterfaceWithIndexers {
int this[int x] { get; set; }
int this[string x] { get; set; }

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

@ -894,5 +894,72 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -894,5 +894,72 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.That(type.Properties.All(p => p.Getter.ImplementedInterfaceMembers.Count == 1));
Assert.That(type.Properties.All(p => p.Setter.ImplementedInterfaceMembers.Count == 1));
}
[Test]
public void ExplicitDisposableImplementation()
{
ITypeDefinition disposable = GetTypeDefinition(typeof(NRefactory.TypeSystem.TestCase.ExplicitDisposableImplementation));
IMethod method = disposable.Methods.Single(m => !m.IsConstructor);
Assert.IsTrue(method.IsExplicitInterfaceImplementation);
Assert.AreEqual("System.IDisposable.Dispose", method.ImplementedInterfaceMembers.Single().FullName);
}
[Test]
public void ExplicitImplementationOfUnifiedMethods()
{
IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods<int, int>));
Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count());
foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) {
Assert.AreEqual(1, method.ImplementedInterfaceMembers.Count, method.ToString());
Assert.AreEqual("System.Int32", method.Parameters.Single().Type.ReflectionName);
IMethod interfaceMethod = (IMethod)method.ImplementedInterfaceMembers.Single();
Assert.AreEqual("System.Int32", interfaceMethod.Parameters.Single().Type.ReflectionName);
var genericParamType = ((IMethod)method.MemberDefinition).Parameters.Single().Type;
var interfaceGenericParamType = ((IMethod)interfaceMethod.MemberDefinition).Parameters.Single().Type;
Assert.AreEqual(TypeKind.TypeParameter, genericParamType.Kind);
Assert.AreEqual(TypeKind.TypeParameter, interfaceGenericParamType.Kind);
Assert.AreEqual(genericParamType.ReflectionName, interfaceGenericParamType.ReflectionName);
}
}
[Test]
public void ExplicitImplementationOfUnifiedMethods_ToMemberReference()
{
IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods<int, int>));
Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count());
foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) {
IMethod resolvedMethod = (IMethod)method.ToMemberReference().Resolve(compilation.TypeResolveContext);
Assert.AreEqual(method, resolvedMethod);
}
}
[Test]
public void ExplicitGenericInterfaceImplementation()
{
ITypeDefinition impl = GetTypeDefinition(typeof(ExplicitGenericInterfaceImplementation));
IType genericInterfaceOfString = compilation.FindType(typeof(IGenericInterface<string>));
IMethod implMethod1 = impl.Methods.Single(m => !m.IsConstructor && !m.Parameters[1].IsRef);
IMethod implMethod2 = impl.Methods.Single(m => !m.IsConstructor && m.Parameters[1].IsRef);
Assert.IsTrue(implMethod1.IsExplicitInterfaceImplementation);
Assert.IsTrue(implMethod2.IsExplicitInterfaceImplementation);
IMethod interfaceMethod1 = (IMethod)implMethod1.ImplementedInterfaceMembers.Single();
Assert.AreEqual(genericInterfaceOfString, interfaceMethod1.DeclaringType);
Assert.IsTrue(!interfaceMethod1.Parameters[1].IsRef);
IMethod interfaceMethod2 = (IMethod)implMethod2.ImplementedInterfaceMembers.Single();
Assert.AreEqual(genericInterfaceOfString, interfaceMethod2.DeclaringType);
Assert.IsTrue(interfaceMethod2.Parameters[1].IsRef);
}
[Test]
public void ExplicitlyImplementedPropertiesShouldBeReportedAsBeingImplemented() {
ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsPropertyExplicitly));
var prop = type.Properties.Single();
Assert.That(prop.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.Prop" }));
Assert.That(prop.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.get_Prop" }));
Assert.That(prop.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.set_Prop" }));
}
}
}

42
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -88,6 +88,15 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -88,6 +88,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
// Enable interning by default.
this.InterningProvider = new SimpleInterningProvider();
}
void ReadExplicitInterfaceImplementation(DefaultUnresolvedMethod m, MethodDefinition method) {
if (method.Name.Contains(".") && method.HasOverrides) {
m.IsExplicitInterfaceImplementation = true;
foreach (var or in method.Overrides) {
m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(EntityType.Method, ReadTypeReference(or.DeclaringType), or.Name, or.GenericParameters.Count, m.Parameters.Select(p => p.Type).ToList(), false));
}
}
}
#region Load From AssemblyDefinition
/// <summary>
@ -1650,7 +1659,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1650,7 +1659,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
return ReadMethod(method, parentType, null, methodType);
}
IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, IUnresolvedMember accessorOwner, EntityType methodType = EntityType.Method)
IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, IUnresolvedMember accessorOwner, EntityType methodType = EntityType.Method, bool readExplicitInterfaceImplementation = true)
{
if (method == null)
return null;
@ -1685,6 +1694,9 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1685,6 +1694,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (method.IsStatic && HasExtensionAttribute(method)) {
m.IsExtensionMethod = true;
}
if (readExplicitInterfaceImplementation)
ReadExplicitInterfaceImplementation(m, method);
FinishReadMember(m, method);
return m;
@ -1870,6 +1882,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1870,6 +1882,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion
#region Read Property
[CLSCompliant(false)]
public IUnresolvedProperty ReadProperty(PropertyDefinition property, IUnresolvedTypeDefinition parentType, EntityType propertyType = EntityType.Property)
{
@ -1891,6 +1904,33 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1891,6 +1904,33 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
}
AddAttributes(property, p);
int lastDot = property.Name.LastIndexOf('.');
if (lastDot >= 0) {
string name = property.Name.Substring(lastDot + 1);
if (p.Getter != null && p.Getter.IsExplicitInterfaceImplementation) {
p.IsExplicitInterfaceImplementation = true;
foreach (var x in p.Getter.ExplicitInterfaceImplementations) {
var r = new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList());
p.ExplicitInterfaceImplementations.Add(r);
}
}
else if (p.Setter != null && p.Setter.IsExplicitInterfaceImplementation) {
p.IsExplicitInterfaceImplementation = true;
foreach (var x in p.Setter.ExplicitInterfaceImplementations) {
var r = new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList());
p.ExplicitInterfaceImplementations.Add(r);
}
}
}
// This is very hacky. Due to which code parts are taken later in the execution, we need to pretend that the accessors are not explicit interface implementations at this stage.
if (p.Getter != null && p.Getter.IsExplicitInterfaceImplementation) {
p.Getter = ReadMethod(property.GetMethod, parentType, p, readExplicitInterfaceImplementation: false);
}
if (p.Setter != null && p.Setter.IsExplicitInterfaceImplementation) {
p.Setter = ReadMethod(property.GetMethod, parentType, p, readExplicitInterfaceImplementation: false);
}
FinishReadMember(p, property);
return p;

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

@ -38,8 +38,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -38,8 +38,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
string name;
int typeParameterCount;
IList<ITypeReference> parameterTypes;
bool isExplicitInterfaceImplementation;
public DefaultMemberReference(EntityType entityType, ITypeReference typeReference, string name, int typeParameterCount = 0, IList<ITypeReference> parameterTypes = null)
public DefaultMemberReference(EntityType entityType, ITypeReference typeReference, string name, int typeParameterCount = 0, IList<ITypeReference> parameterTypes = null, bool isExplicitInterfaceImplementation = false)
{
if (typeReference == null)
throw new ArgumentNullException("typeReference");
@ -52,6 +53,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -52,6 +53,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.name = name;
this.typeParameterCount = typeParameterCount;
this.parameterTypes = parameterTypes ?? EmptyList<ITypeReference>.Instance;
this.isExplicitInterfaceImplementation = isExplicitInterfaceImplementation;
}
public ITypeReference DeclaringTypeReference {
@ -65,11 +67,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -65,11 +67,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (entityType == EntityType.Method) {
members = type.GetMethods(
m => m.Name == name && m.EntityType == EntityType.Method
&& m.TypeParameters.Count == typeParameterCount && !m.IsExplicitInterfaceImplementation,
&& m.TypeParameters.Count == typeParameterCount && m.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation,
GetMemberOptions.IgnoreInheritedMembers);
} else {
members = type.GetMembers(
m => m.Name == name && m.EntityType == entityType && !m.IsExplicitInterfaceImplementation,
m => m.Name == name && m.EntityType == entityType && m.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation,
GetMemberOptions.IgnoreInheritedMembers);
}
var resolvedParameterTypes = parameterTypes.Resolve(context);

Loading…
Cancel
Save