diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
index 195a6ccb0d..1da07f14a9 100644
--- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
+++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
@@ -270,6 +270,7 @@
+
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionIsNeverOfProvidedTypeIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionIsNeverOfProvidedTypeIssue.cs
new file mode 100644
index 0000000000..c366c529e0
--- /dev/null
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionIsNeverOfProvidedTypeIssue.cs
@@ -0,0 +1,152 @@
+//
+// ExpressionIsNeverOfProvidedTypeIssue.cs
+//
+// Author:
+// Mansheng Yang
+//
+// Copyright (c) 2012 Mansheng Yang
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.NRefactory.TypeSystem;
+
+namespace ICSharpCode.NRefactory.CSharp.Refactoring
+{
+ [IssueDescription ("CS0184:Given expression is never of the provided type",
+ Description = "CS0184:Given expression is never of the provided type.",
+ Category = IssueCategories.CompilerWarnings,
+ Severity = Severity.Warning,
+ IssueMarker = IssueMarker.Underline)]
+ public class ExpressionIsNeverOfProvidedTypeIssue : ICodeIssueProvider
+ {
+ public IEnumerable GetIssues (BaseRefactoringContext context)
+ {
+ return new GatherVisitor (context).GetIssues ();
+ }
+
+ class GatherVisitor : GatherVisitorBase
+ {
+ public GatherVisitor (BaseRefactoringContext ctx)
+ : base (ctx)
+ {
+ }
+
+ void AddIssue(IsExpression isExpression)
+ {
+ AddIssue (isExpression, ctx.TranslateString ("Given expression is never of the provided type"));
+ }
+
+ static bool CheckTypeParameterConstraints (IType type, IEnumerable baseTypes,
+ ITypeParameter typeParameter)
+ {
+ if (!typeParameter.DirectBaseTypes.All (t => baseTypes.Any (t2 => t2.Equals (t))))
+ return false;
+ if (typeParameter.HasDefaultConstructorConstraint &&
+ !type.GetConstructors (c => c.IsPublic && c.Parameters.Count == 0).Any ())
+ return false;
+ return true;
+ }
+
+ public override void VisitIsExpression (IsExpression isExpression)
+ {
+ base.VisitIsExpression (isExpression);
+
+ var exprType = ctx.Resolve (isExpression.Expression).Type;
+ var providedType = ctx.ResolveType (isExpression.Type);
+
+ var exprBaseTypes = exprType.GetAllBaseTypes ().ToArray ();
+
+ // providedType is a base type of exprType
+ if (exprBaseTypes.Any (t => t.Equals (providedType)))
+ return;
+
+ if ((exprType.IsReferenceType == true && providedType.IsReferenceType == false) ||
+ (exprType.IsReferenceType == false && providedType.IsReferenceType == true)) {
+ AddIssue (isExpression);
+ return;
+ }
+
+ var typeParameter = exprType as ITypeParameter;
+ var providedTypeParameter = providedType as ITypeParameter;
+
+ if (typeParameter != null) {
+ // check if providedType can be a derived type
+ var providedBaseTypes = providedType.GetAllBaseTypes ().ToArray ();
+ var providedTypeDef = providedType.GetDefinition ();
+ // if providedType is sealed, check if it fullfills all the type parameter constraints,
+ // otherwise, only check if it is derived from EffectiveBaseClass
+ if (providedTypeParameter == null && (providedTypeDef == null || providedTypeDef.IsSealed)) {
+ if (CheckTypeParameterConstraints (providedType, providedBaseTypes, typeParameter))
+ return;
+ } else if (providedBaseTypes.Any (t => t.Equals (typeParameter.EffectiveBaseClass))) {
+ return;
+ }
+
+ // if providedType is also a type parameter, check if base classes are compatible
+ if (providedTypeParameter != null &&
+ exprBaseTypes.Any (t => t.Equals (providedTypeParameter.EffectiveBaseClass)))
+ return;
+
+ AddIssue (isExpression);
+ return;
+ }
+ // check if exprType fullfills all the type parameter constraints
+ if (providedTypeParameter != null &&
+ CheckTypeParameterConstraints (exprType, exprBaseTypes, providedTypeParameter))
+ return;
+
+ switch (exprType.Kind) {
+ case TypeKind.Class:
+ var exprTypeDef = exprType.GetDefinition ();
+ if (exprTypeDef == null)
+ return;
+ // exprType is sealed, but providedType is not a base type of it or it does not
+ // fullfill all the type parameter constraints
+ if (exprTypeDef.IsSealed)
+ break;
+
+ // check if providedType can be a derived type
+ if (providedType.Kind == TypeKind.Interface ||
+ providedType.GetAllBaseTypes ().Any (t => t.Equals (exprType)))
+ return;
+
+ if (providedTypeParameter != null &&
+ exprBaseTypes.Any (t => t.Equals (providedTypeParameter.EffectiveBaseClass)))
+ return;
+
+ break;
+
+ case TypeKind.Struct:
+ case TypeKind.Delegate:
+ case TypeKind.Enum:
+ case TypeKind.Array:
+ case TypeKind.Anonymous:
+ case TypeKind.Null:
+ break;
+
+ default:
+ return;
+ }
+ AddIssue (isExpression);
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionIsNeverOfProvidedTypeIssueTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionIsNeverOfProvidedTypeIssueTests.cs
new file mode 100644
index 0000000000..fc73329b43
--- /dev/null
+++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionIsNeverOfProvidedTypeIssueTests.cs
@@ -0,0 +1,263 @@
+//
+// ExpressionIsNeverOfProvidedTypeIssueTests.cs
+//
+// Author:
+// Mansheng Yang
+//
+// Copyright (c) 2012 Mansheng Yang
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using ICSharpCode.NRefactory.CSharp.Refactoring;
+using NUnit.Framework;
+
+namespace ICSharpCode.NRefactory.CSharp.CodeIssues
+{
+ [TestFixture]
+ public class ExpressionIsNeverOfProvidedTypeIssueTests : InspectionActionTestBase
+ {
+ [Test]
+ public void TestClass ()
+ {
+ var input = @"
+class AnotherClass { }
+class TestClass
+{
+ void TestMethod (AnotherClass x)
+ {
+ if (x is TestClass) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestClassNoIssue ()
+ {
+ var input = @"
+interface ITest { }
+class TestClass
+{
+ void TestMethod (object x)
+ {
+ if (x is ITest) ;
+ if (x is TestClass) ;
+ }
+}";
+ Test (input, 0);
+ }
+
+ [Test]
+ public void TestSealedClass ()
+ {
+ var input = @"
+interface ITest { }
+sealed class TestClass
+{
+ void TestMethod (TestClass x)
+ {
+ if (x is ITest) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestNull ()
+ {
+ var input = @"
+class TestClass
+{
+ void TestMethod ()
+ {
+ if (null is object) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestClassIsTypeParameter ()
+ {
+ var input = @"
+class TestClass2 { }
+class TestClass
+{
+ void TestMethod (TestClass x) where T : TestClass2 where T2 : struct
+ {
+ if (x is T) ;
+ if (x is T2) ;
+ }
+}";
+ Test (input, 2);
+ }
+
+ [Test]
+ public void TestClassIsTypeParameter2 ()
+ {
+ var input = @"
+interface ITest { }
+class TestBase { }
+class TestClass2 : TestClass { }
+class TestClass : TestBase
+{
+ void TestMethod (TestClass x) where T : TestBase where T2 : ITest where T3 : TestClass2
+ {
+ if (x is T3) ;
+ }
+}";
+ Test (input, 0);
+ }
+
+ [Test]
+ public void TestStructIsTypeParameter ()
+ {
+ var input = @"
+interface ITest { }
+struct TestStruct : ITest { }
+class TestClass
+{
+ void TestMethod (TestStruct x) where T : ITest
+ {
+ if (x is T) ;
+ }
+}";
+ Test (input, 0);
+ }
+
+ [Test]
+ public void TestStructIsTypeParameter2 ()
+ {
+ var input = @"
+struct TestStruct { }
+class TestClass
+{
+ void TestMethod (TestStruct x) where T : class
+ {
+ if (x is T) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestTypeParameter ()
+ {
+ var input = @"
+class TestClass2 { }
+class TestClass
+{
+ void TestMethod (T x) where T : TestClass2
+ {
+ if (x is TestClass) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestTypeParameter2 ()
+ {
+ var input = @"
+class TestClass
+{
+ void TestMethod (T x) where T : struct
+ {
+ if (x is TestClass) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestTypeParameter3 ()
+ {
+ var input = @"
+interface ITest { }
+class TestClass
+{
+ void TestMethod (T x) where T : ITest, new()
+ {
+ if (x is TestClass) ;
+ }
+}";
+ Test (input, 0);
+ }
+
+ [Test]
+ public void TestTypeParameter4 ()
+ {
+ var input = @"
+interface ITest { }
+sealed class TestClass
+{
+ void TestMethod (T x) where T : ITest
+ {
+ if (x is TestClass) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestTypeParameter5 ()
+ {
+ var input = @"
+sealed class TestClass
+{
+ public TestClass (int i) { }
+ void TestMethod (T x) where T : new()
+ {
+ if (x is TestClass) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestTypeParameterIsTypeParameter ()
+ {
+ var input = @"
+class TestClass2 { }
+class TestClass
+{
+ void TestMethod (T x) where T : TestClass where T2 : TestClass2
+ {
+ if (x is T2) ;
+ }
+}";
+ Test (input, 1);
+ }
+
+ [Test]
+ public void TestTypeParameterIsTypeParameter2 ()
+ {
+ var input = @"
+interface ITest { }
+class TestClass
+{
+ void TestMethod (T x) where T : TestClass where T2 : ITest, new()
+ {
+ if (x is T2) ;
+ }
+}";
+ Test (input, 0);
+ }
+ }
+}
diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
index 996a1d35ac..562e9dae9d 100644
--- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
+++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
@@ -109,6 +109,7 @@
+