diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
index a62692406f..65cbb19826 100644
--- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
+++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
@@ -498,6 +498,7 @@
+
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantWhereWithPredicateIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantWhereWithPredicateIssue.cs
new file mode 100644
index 0000000000..45c930748f
--- /dev/null
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantWhereWithPredicateIssue.cs
@@ -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 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 ("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 ("target").Single ().Clone ();
+ script.Replace (anyInvoke, new InvocationExpression (new MemberReferenceExpression (target, "Any"), arg));
+ });
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantWhereWithPredicateIssueTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantWhereWithPredicateIssueTests.cs
new file mode 100644
index 0000000000..9c712e6726
--- /dev/null
+++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantWhereWithPredicateIssueTests.cs
@@ -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 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);
+ }
+ }
+}
diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
index 37f23a1085..f738c7aa97 100644
--- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
+++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
@@ -359,6 +359,7 @@
+