4 changed files with 136 additions and 0 deletions
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.PatternMatching; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Refactoring |
||||
{ |
||||
[IssueDescription("Any() should be used with predicate and Where() removed", |
||||
Description= "Detects redundant Where() with predicate calls followed by Any().", |
||||
Category = IssueCategories.CodeQualityIssues, |
||||
Severity = Severity.Hint)] |
||||
public class RedundantWhereWithPredicateIssue : ICodeIssueProvider |
||||
{ |
||||
static readonly AstNode pattern = |
||||
new InvocationExpression ( |
||||
new MemberReferenceExpression ( |
||||
new NamedNode ("whereInvoke", |
||||
new InvocationExpression ( |
||||
new MemberReferenceExpression (new AnyNode ("target"), "Where"), |
||||
new AnyNode ())), |
||||
"Any")); |
||||
|
||||
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context) |
||||
{ |
||||
return new GatherVisitor(context).GetIssues(); |
||||
} |
||||
|
||||
class GatherVisitor : GatherVisitorBase |
||||
{ |
||||
public GatherVisitor (BaseRefactoringContext ctx) : base (ctx) |
||||
{ |
||||
} |
||||
|
||||
public override void VisitInvocationExpression (InvocationExpression anyInvoke) |
||||
{ |
||||
base.VisitInvocationExpression (anyInvoke); |
||||
|
||||
var match = pattern.Match (anyInvoke); |
||||
if (!match.Success) |
||||
return; |
||||
|
||||
var anyResolve = ctx.Resolve (anyInvoke) as InvocationResolveResult; |
||||
if (anyResolve == null || anyResolve.Member.FullName != "System.Linq.Enumerable.Any") |
||||
return; |
||||
var whereInvoke = match.Get<InvocationExpression> ("whereInvoke").Single (); |
||||
var whereResolve = ctx.Resolve (whereInvoke) as InvocationResolveResult; |
||||
if (whereResolve == null || whereResolve.Member.FullName != "System.Linq.Enumerable.Where") |
||||
return; |
||||
if (whereResolve.Member.Parameters.Count != 2) |
||||
return; |
||||
var predResolve = whereResolve.Member.Parameters [1]; |
||||
if (predResolve.Type.TypeParameterCount != 2) |
||||
return; |
||||
|
||||
AddIssue (anyInvoke, "Redundant Where() call with predicate followed by Any()", script => { |
||||
var arg = whereInvoke.Arguments.Single ().Clone (); |
||||
var target = match.Get<Expression> ("target").Single ().Clone (); |
||||
script.Replace (anyInvoke, new InvocationExpression (new MemberReferenceExpression (target, "Any"), arg)); |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
using System; |
||||
using NUnit.Framework; |
||||
using ICSharpCode.NRefactory.CSharp.Refactoring; |
||||
using ICSharpCode.NRefactory.CSharp.CodeActions; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.CodeIssues |
||||
{ |
||||
[TestFixture] |
||||
public class RedundantWhereWithPredicateIssueTests : InspectionActionTestBase |
||||
{ |
||||
[Test] |
||||
public void TestWhereAnyCase1 () |
||||
{ |
||||
var input = @"using System.Linq;
|
||||
public class CSharpDemo { |
||||
public void Bla () { |
||||
int[] arr; |
||||
var bla = arr.Where (x => x < 4).Any (); |
||||
} |
||||
}";
|
||||
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues (new RedundantWhereWithPredicateIssue (), input, out context); |
||||
Assert.AreEqual (1, issues.Count); |
||||
CheckFix (context, issues, @"using System.Linq;
|
||||
public class CSharpDemo { |
||||
public void Bla () { |
||||
int[] arr; |
||||
var bla = arr.Any (x => x < 4); |
||||
} |
||||
}");
|
||||
} |
||||
|
||||
[Test] |
||||
public void TestWhereAnyWrongWhere1 () |
||||
{ |
||||
var input = @"using System.Linq;
|
||||
public class CSharpDemo { |
||||
public void Bla () { |
||||
int[] arr; |
||||
var bla = arr.Where ((x, i) => x + i < 4).Any (); |
||||
} |
||||
}";
|
||||
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues (new RedundantWhereWithPredicateIssue (), input, out context); |
||||
Assert.AreEqual (0, issues.Count); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestWhereAnyWrongWhere2 () |
||||
{ |
||||
var input = @"using System;
|
||||
using System.Linq; |
||||
public class X |
||||
{ |
||||
X Where (Func<int,int> f) { return null; } |
||||
bool Any () { return false; } |
||||
public void Bla () { |
||||
X ex = null; |
||||
var bla = ex.Where (x => x + 1).Any (); |
||||
} |
||||
}";
|
||||
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues (new RedundantWhereWithPredicateIssue (), input, out context); |
||||
Assert.AreEqual (0, issues.Count); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue