Added early bail-outs via simple text matchings to optimize speed of false positive detection.

This commit is contained in:
Chris Hodges 2019-05-04 15:54:27 +02:00
parent 6fb23ea89c
commit 0b79a6d7dc
13 changed files with 66 additions and 23 deletions

View File

@ -12,6 +12,8 @@ import de.platon42.intellij.plugins.cajon.inspections.AbstractAssertJInspection
val PsiMethodCallExpression.qualifierExpression: PsiExpression get() = methodExpression.qualifierExpression!!
val PsiMethodCallExpression.firstArg: PsiExpression get() = getArg(0)
fun PsiElement.hasAssertThat() = text.contains("assertThat")
fun PsiMethodCallExpression.replaceQualifier(qualifier: PsiElement) {
qualifierExpression.replace(qualifier)
}

View File

@ -20,9 +20,12 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement?) {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
val staticMethodCall = statement?.findStaticMethodCall() ?: return
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}

View File

@ -5,11 +5,8 @@ import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.util.TypeConversionUtil
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_BOOLEAN_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
class AssertThatBooleanConditionInspection : AbstractAssertJInspection() {
@ -23,6 +20,9 @@ class AssertThatBooleanConditionInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val matchingCalls = listOf(
IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_BOOLEAN,
IS_NOT_EQUAL_TO_OBJECT, IS_NOT_EQUAL_TO_BOOLEAN

View File

@ -7,6 +7,7 @@ import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiStatement
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue
import de.platon42.intellij.plugins.cajon.hasAssertThat
class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
@ -20,6 +21,9 @@ class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val isLastExpression = expression.parent is PsiStatement
if (!(HAS_SIZE.test(expression) && isLastExpression)) {
return

View File

@ -19,9 +19,12 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement?) {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
val staticMethodCall = statement?.findStaticMethodCall() ?: return
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!checkPreconditions(staticMethodCall)) {
return
@ -53,6 +56,9 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!checkPreconditions(staticMethodCall)) {
return

View File

@ -18,9 +18,12 @@ class AssertThatInstanceOfInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement?) {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
val staticMethodCall = statement?.findStaticMethodCall() ?: return
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}

View File

@ -2,10 +2,7 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.*
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.findStaticMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.getExpectedBooleanResult
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.InvertUnaryStatementQuickFix
class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection() {
@ -21,6 +18,9 @@ class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection()
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return

View File

@ -21,9 +21,12 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement?) {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
val staticMethodCall = statement?.findStaticMethodCall() ?: return
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_ANY.test(staticMethodCall)) {
return
}
@ -52,6 +55,9 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!ASSERT_THAT_JAVA8_OPTIONAL.test(staticMethodCall)) {
return

View File

@ -4,6 +4,7 @@ import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.*
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.hasAssertThat
import de.platon42.intellij.plugins.cajon.map
class AssertThatObjectIsNullOrNotNullInspection : AbstractAssertJInspection() {
@ -18,6 +19,9 @@ class AssertThatObjectIsNullOrNotNullInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val isNotEqualTo = IS_NOT_EQUAL_TO_OBJECT.test(expression)
val isEqualTo = IS_EQUAL_TO_OBJECT.test(expression)
val isLastExpression = expression.parent is PsiStatement

View File

@ -72,9 +72,12 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement?) {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
val staticMethodCall = statement?.findStaticMethodCall() ?: return
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_INT.test(staticMethodCall)) {
return
}
@ -109,6 +112,9 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val isHasSize = HAS_SIZE.test(expression)
if (!(isHasSize)) {
return

View File

@ -46,9 +46,12 @@ class AssertThatStringExpressionInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement?) {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
val staticMethodCall = statement?.findStaticMethodCall() ?: return
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}

View File

@ -8,6 +8,7 @@ import com.intellij.psi.PsiStatement
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue
import de.platon42.intellij.plugins.cajon.hasAssertThat
class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
@ -21,6 +22,9 @@ class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val isEqual = IS_EQUAL_TO_OBJECT.test(expression)
val hasSize = HAS_SIZE.test(expression)
val isLastExpression = expression.parent is PsiStatement

View File

@ -19,15 +19,14 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitCodeBlock(block: PsiCodeBlock?) {
override fun visitCodeBlock(block: PsiCodeBlock) {
super.visitCodeBlock(block)
val statements = block?.statements ?: return
var lastActualExpression: PsiExpression? = null
var sameCount = 0
var firstStatement: PsiStatement? = null
var lastStatement: PsiStatement? = null
val equivalenceChecker = TrackingEquivalenceChecker()
for (statement in statements) {
for (statement in block.statements) {
val assertThatCall = isLegitAssertThatCall(statement)
var reset = true
var actualExpression: PsiExpression? = null
@ -81,6 +80,9 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
private fun isLegitAssertThatCall(statement: PsiStatement?): PsiMethodCallExpression? {
if ((statement is PsiExpressionStatement) && (statement.expression is PsiMethodCallExpression)) {
if (!statement.hasAssertThat()) {
return null
}
val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) }
return assertThatCall?.takeIf { it.findFluentCallTo(EXTRACTING_CALL_MATCHERS) == null }
}