Implemented AssertThatEnumerableIsEmptyInspection. Improved literal values by constant value calculation, more refactoring.

This commit is contained in:
2019-03-24 14:42:02 +01:00
parent e2ffce753c
commit 582e254195
14 changed files with 160 additions and 31 deletions
@@ -27,19 +27,22 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
const val ABSTRACT_BOOLEAN_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractBooleanAssert"
const val ABSTRACT_STRING_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractStringAssert"
const val ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractCharSequenceAssert"
const val IS_EQUAL_TO = "isEqualTo"
const val IS_NOT_EQUAL_TO = "isNotEqualTo"
const val HAS_SIZE = "hasSize"
const val ABSTRACT_ENUMERABLE_ASSERT_CLASSNAME = "org.assertj.core.api.EnumerableAssert"
val IS_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, IS_EQUAL_TO)
const val IS_EQUAL_TO_METHOD = "isEqualTo"
const val IS_NOT_EQUAL_TO_METHOD = "isNotEqualTo"
const val HAS_SIZE_METHOD = "hasSize"
val IS_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, IS_EQUAL_TO_METHOD)
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val IS_NOT_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, IS_NOT_EQUAL_TO)
val IS_NOT_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, IS_NOT_EQUAL_TO_METHOD)
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val IS_EQUAL_TO_BOOLEAN = CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, IS_EQUAL_TO)
val IS_EQUAL_TO_BOOLEAN = CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, IS_EQUAL_TO_METHOD)
.parameterTypes("boolean")!!
val IS_NOT_EQUAL_TO_BOOLEAN = CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, IS_NOT_EQUAL_TO)
.parameterTypes("boolean")!!
val CHAR_SEQUENCE_HAS_SIZE = CallMatcher.instanceCall(ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME, HAS_SIZE)
val IS_NOT_EQUAL_TO_BOOLEAN =
CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, IS_NOT_EQUAL_TO_METHOD)
.parameterTypes("boolean")!!
val HAS_SIZE = CallMatcher.instanceCall(ABSTRACT_ENUMERABLE_ASSERT_CLASSNAME, HAS_SIZE_METHOD)
.parameterTypes("int")!!
}
@@ -77,4 +80,10 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
ReplaceSimpleMethodCallQuickFix(description, replacementMethod)
)
}
protected fun calculateConstantParameterValue(expression: PsiMethodCallExpression, argIndex: Int): Any? {
val valueExpression = expression.argumentList.expressions[argIndex] ?: return null
val constantEvaluationHelper = JavaPsiFacade.getInstance(expression.project).constantEvaluationHelper
return constantEvaluationHelper.computeConstantExpression(valueExpression)
}
}
@@ -31,22 +31,21 @@ class AssertThatBooleanIsTrueOrFalseInspection : AbstractAssertJInspection() {
return
}
val equalToExpression = expression.argumentList.expressions[0]!!
val equalToExpression = expression.argumentList.expressions[0] ?: return
if (!TypeConversionUtil.isBooleanType(equalToExpression.type)) {
return
}
val constantEvaluationHelper = JavaPsiFacade.getInstance(holder.project).constantEvaluationHelper
var result = constantEvaluationHelper.computeConstantExpression(equalToExpression)
if (result == null) {
var value = calculateConstantParameterValue(expression, 0)
if (value == null) {
val field = (equalToExpression as? PsiReferenceExpression)?.resolve() as? PsiField
if (field?.containingClass?.qualifiedName == CommonClassNames.JAVA_LANG_BOOLEAN) {
when {
field.name == "TRUE" -> result = true
field.name == "FALSE" -> result = false
field.name == "TRUE" -> value = true
field.name == "FALSE" -> value = false
}
}
}
val expectedResult = result as? Boolean ?: return
val expectedResult = value as? Boolean ?: return
val replacementMethod = if (expectedResult xor flippedBooleanTest) "isTrue()" else "isFalse()"
registerSimplifyMethod(holder, expression, replacementMethod)
@@ -0,0 +1,34 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import org.jetbrains.annotations.NonNls
class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
companion object {
@NonNls
private val DISPLAY_NAME = "Asserting an enumerable is empty"
}
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
val hasSize = HAS_SIZE.test(expression)
if (!hasSize) {
return
}
val value = calculateConstantParameterValue(expression, 0) ?: return
if (value == 0) {
registerSimplifyMethod(holder, expression, "isEmpty()")
}
}
}
}
}
@@ -3,7 +3,6 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiLiteralExpression
import com.intellij.psi.PsiMethodCallExpression
import org.jetbrains.annotations.NonNls
@@ -21,7 +20,7 @@ class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
val isEqual = IS_EQUAL_TO_OBJECT.test(expression)
val hasSize = CHAR_SEQUENCE_HAS_SIZE.test(expression)
val hasSize = HAS_SIZE.test(expression)
if (!(isEqual || hasSize)) {
return
}
@@ -30,17 +29,9 @@ class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
return
}
if (isEqual) {
val psiExpression = expression.argumentList.expressions[0] as? PsiLiteralExpression ?: return
if (psiExpression.value == "") {
registerSimplifyMethod(holder, expression, "isEmpty()")
}
} else {
val psiExpression = expression.argumentList.expressions[0] as? PsiLiteralExpression ?: return
if (psiExpression.value == 0) {
registerSimplifyMethod(holder, expression, "isEmpty()")
}
val value = calculateConstantParameterValue(expression, 0) ?: return
if ((isEqual && (value == "")) || (hasSize && (value == 0))) {
registerSimplifyMethod(holder, expression, "isEmpty()")
}
}
}
+3
View File
@@ -27,6 +27,9 @@
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBooleanIsTrueOrFalseInspection"/>
<localInspection groupPath="Java" shortName="AssertThatStringIsEmpty" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatStringIsEmptyInspection"/>
<localInspection groupPath="Java" shortName="AssertThatEnumerableIsEmpty" enabledByDefault="true"
level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatEnumerableIsEmptyInspection"/>
</extensions>
<actions>
@@ -3,5 +3,6 @@
Turns assertThat(booleanExpression).isEqualTo(true/false) or assertThat(booleanExpression).isNotEqualTo(true/false)
into assertThat(booleanExpression).isTrue() or assertThat(booleanExpression).isFalse().
<!-- tooltip end -->
<br>Also works with Boolean.TRUE/FALSE.
</body>
</html>
@@ -0,0 +1,7 @@
<html>
<body>
Turns assertThat(enumerable).hasSize(0) into assertThat(enumerable).isEmpty().
<!-- tooltip end -->
<br>Works with anything that is enumerable such as arrays, iterables, collections, etc.
</body>
</html>
@@ -2,6 +2,6 @@
<body>
Turns assertThat(string).isEqualTo("") or assertThat(string).hasSize(0) into assertThat(string).isEmpty().
<!-- tooltip end -->
Also works with CharSequences.
<br>Also works with CharSequences.
</body>
</html>