Browse Source

[CodeIssues] Improve ParameterCouldBeDemotedIssue.

newNRvisualizers
Simon Lindgren 13 years ago
parent
commit
be0d89c486
  1. 65
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ParameterCanBeDemotedIssue/ParameterCanBeDemotedIssue.cs
  2. 116
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ParameterCanBeDemotedIssue/ParameterCanBeDemotedTests.cs

65
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ParameterCanBeDemotedIssue/ParameterCanBeDemotedIssue.cs

@ -68,8 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -68,8 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
continue;
var currentType = localResolveResult.Type;
var candidateTypes = localResolveResult.Type.GetAllBaseTypes().ToList();
candidateTypes.Add(localResolveResult.Type);
var possibleTypes = GetLeastDerivedImplementors(candidateTypes, invocations);
var possibleTypes = GetPossibleTypes(candidateTypes, invocations);
var suggestedTypes = possibleTypes.Where(t => t != currentType);
if (suggestedTypes.Any())
AddIssue(parameter, context.TranslateString("Parameter can be demoted to base class"),
@ -89,45 +88,45 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -89,45 +88,45 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
}
static IEnumerable<IMember> GetDeclaredMembers(IMember member)
{
var implementedInterfaceMembers = member.ImplementedInterfaceMembers;
if (implementedInterfaceMembers.Count == 0) {
yield return member;
}
else {
foreach (var interfaceMember in implementedInterfaceMembers) {
yield return interfaceMember;
}
}
}
HashSet<IMember> GetNeededMembers(IEnumerable<InvocationResolveResult> invocations)
{
var members = new HashSet<IMember>();
foreach (var invocation in invocations) {
foreach (var member in GetDeclaredMembers(invocation.Member)) {
members.Add(member);
}
members.Add(invocation.Member);
}
return members;
}
bool SatisfiesMemberRequests(IType type, HashSet<IMember> members)
static bool HasCommonMemberDeclaration(IEnumerable<IMember> acceptableMembers, IMember member)
{
var implementedInterfaceMembers = member.MemberDefinition.ImplementedInterfaceMembers;
if (implementedInterfaceMembers.Any()) {
return acceptableMembers.ContainsAny(implementedInterfaceMembers);
}
else {
return acceptableMembers.Contains(member.MemberDefinition);
}
}
bool SatisfiesMemberRequests(IType candidateType, HashSet<IMember> wantedMembers)
{
var unsatisfiedMembers = new HashSet<IMember>(members);
foreach (var member in type.GetMembers()) {
var interfaceMembers = member.ImplementedInterfaceMembers;
if (interfaceMembers.Count > 0) {
unsatisfiedMembers.RemoveWhere(m => interfaceMembers.Contains(m));
var allMembers = candidateType.GetMembers();
foreach (var wantedMember in wantedMembers) {
IEnumerable<IMember> acceptableMembers;
if (wantedMember.ImplementedInterfaceMembers.Any()) {
acceptableMembers = wantedMember.ImplementedInterfaceMembers.ToList();
} else {
unsatisfiedMembers.RemoveWhere(m => m == member);
acceptableMembers = new List<IMember>() { wantedMember.MemberDefinition };
}
var hasMember = allMembers.Any(m => HasCommonMemberDeclaration(acceptableMembers, m));
if (!hasMember)
return false;
}
return unsatisfiedMembers.Count == 0;
return true;
}
IEnumerable<IType> GetLeastDerivedImplementors(IEnumerable<IType> types, IEnumerable<InvocationResolveResult> invocations)
IEnumerable<IType> GetPossibleTypes(IEnumerable<IType> types, IEnumerable<InvocationResolveResult> invocations)
{
var members = GetNeededMembers(invocations);
return from type in types
@ -176,5 +175,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -176,5 +175,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
}
}
static class IEnumerableExtensions
{
public static bool ContainsAny<T>(this IEnumerable<T> collection, IEnumerable<T> items)
{
foreach (var item in items) {
if (collection.Contains(item))
return true;
}
return false;
}
}
}

116
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ParameterCanBeDemotedIssue/ParameterCanBeDemotedTests.cs

@ -27,18 +27,17 @@ using System; @@ -27,18 +27,17 @@ using System;
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.CodeActions;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.CodeIssues
{
[TestFixture]
public class ParameterCanBeDemotedTests : InspectionActionTestBase
{
[TestFixture]
public class ParameterCanBeDemotedTests : InspectionActionTestBase
{
[Test]
public void BasicTest()
{
var input = @"
[Test]
public void BasicTest()
{
var input = @"
class A
{
public virtual void Foo() {}
@ -54,11 +53,13 @@ class C @@ -54,11 +53,13 @@ class C
b.Foo();
}
}";
TestRefactoringContext context;
var issues = GetIssues(new ParameterCanBeDemotedIssue(), input, out context);
Assert.AreEqual(1, issues.Count);
TestRefactoringContext context;
var issues = GetIssues(new ParameterCanBeDemotedIssue(), input, out context);
Assert.AreEqual(1, issues.Count);
var issue = issues [0];
Assert.AreEqual(1, issue.Actions.Count);
CheckFix(context, issues [0], @"
CheckFix(context, issues [0], @"
class A
{
public virtual void Foo() {}
@ -74,13 +75,13 @@ class C @@ -74,13 +75,13 @@ class C
b.Foo();
}
}"
);
}
);
}
[Test]
public void InterfaceTest()
{
var input = @"
[Test]
public void InterfaceTest()
{
var input = @"
interface IA
{
void Foo();
@ -97,11 +98,13 @@ class C @@ -97,11 +98,13 @@ class C
b.Foo();
}
}";
TestRefactoringContext context;
var issues = GetIssues(new ParameterCanBeDemotedIssue(), input, out context);
Assert.AreEqual(1, issues.Count);
TestRefactoringContext context;
var issues = GetIssues(new ParameterCanBeDemotedIssue(), input, out context);
Assert.AreEqual(1, issues.Count);
var issue = issues [0];
Assert.AreEqual(1, issue.Actions.Count);
CheckFix(context, issues [0], @"
CheckFix(context, issues [0], @"
interface IA
{
void Foo();
@ -118,8 +121,66 @@ class C @@ -118,8 +121,66 @@ class C
b.Foo();
}
}"
);
}
);
}
[Test]
public void MultipleInterfaceTest()
{
var input = @"
interface IA1
{
void Foo();
}
interface IA2
{
void Bar();
}
class B : IA1, IA2
{
public virtual void Foo() {}
public virtual void Bar() {}
}
class C : B {}
class Test
{
void F(C c)
{
c.Foo();
c.Bar();
}
}";
TestRefactoringContext context;
var issues = GetIssues(new ParameterCanBeDemotedIssue(), input, out context);
Assert.AreEqual(1, issues.Count);
var issue = issues [0];
Assert.AreEqual(1, issue.Actions.Count);
CheckFix(context, issues [0], @"
interface IA1
{
void Foo();
}
interface IA2
{
void Bar();
}
class B : IA1, IA2
{
public virtual void Foo() {}
public virtual void Bar() {}
}
class C : B {}
class Test
{
void F(B c)
{
c.Foo();
c.Bar();
}
}"
);
}
string baseInput = @"
interface IA
@ -160,7 +221,9 @@ class Test @@ -160,7 +221,9 @@ class Test
TestRefactoringContext context;
var issues = GetIssues(new ParameterCanBeDemotedIssue(), input, out context);
Assert.AreEqual(1, issues.Count);
var fixes = issues [0].Actions;
var issue = issues [0];
Assert.AreEqual(4, issue.Actions.Count);
CheckFix(context, issues [0], baseInput + @"
class Test
{
@ -168,7 +231,8 @@ class Test @@ -168,7 +231,8 @@ class Test
{
d.Foo();
}
}");
}"
);
}
}
}

Loading…
Cancel
Save