/** * @name Useless 'is' before 'as' * @description The C# 'as' operator performs a type test - there is no need to precede it with an 'is'. * @kind problem * @problem.severity recommendation * @precision medium * @id cs/useless-is-before-as * @tags maintainability * language-features * external/cwe/cwe-561 */ import csharp import semmle.code.csharp.commons.StructuralComparison class StructuralComparisonConfig extends StructuralComparisonConfiguration { StructuralComparisonConfig() { this = "UselessIsBeforeAs" } override predicate candidate(Element x, Element y) { exists(IfStmt is, AsExpr ae, IsTypeExpr ie | ie = is.getCondition().getAChild*() and ae.getTargetType() = ie.getCheckedType() and x = ie.getExpr() and y = ae.getExpr() | ae = is.getThen().getAChild*() or ae = is.getElse().getAChild*() ) } predicate uselessIsBeforeAs(AsExpr ae, IsExpr ie) { exists(Expr x, Expr y | same(x, y) and ie.getExpr() = x and ae.getExpr() = y ) } } from AsExpr ae, IsExpr ie where exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie)) and not exists(MethodCall mc | ae = mc.getAnArgument().getAChildExpr*()) select ae, "This 'as' expression performs a type test - it should be directly compared against null, rendering the 'is' $@ potentially redundant.", ie, "here"