Extended AssertThatSize inspection to transform hasSize() into hasSameSizeAs(), if possible.

This commit is contained in:
2019-04-23 20:16:43 +02:00
parent 8b0da63f86
commit 666e373405
11 changed files with 83 additions and 33 deletions
@@ -29,7 +29,7 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
const val REPLACE_DESCRIPTION_TEMPLATE = "Replace %s() with %s()"
const val REMOVE_EXPECTED_OUTMOST_DESCRIPTION_TEMPLATE = "Remove unwrapping of expected expression and replace %s() with %s()"
const val REMOVE_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE = "Unwrap actual expression and replace %s() with %s()"
const val UNWRAP_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE = "Unwrap actual expression and replace %s() with %s()"
val TOKEN_TO_ASSERTJ_FOR_PRIMITIVE_MAP = mapOf<IElementType, String>(
JavaTokenType.EQEQ to MethodNames.IS_EQUAL_TO,
@@ -219,7 +219,7 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
replacementMethod: String,
quickFixSupplier: (String, String) -> LocalQuickFix
) {
registerConciseMethod(REMOVE_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod, quickFixSupplier)
registerConciseMethod(UNWRAP_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod, quickFixSupplier)
}
protected fun calculateConstantParameterValue(expression: PsiMethodCallExpression, argIndex: Int): Any? {
@@ -39,7 +39,7 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
if (isEqualTo) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
if (CallMatcher.anyOf(GUAVA_OPTIONAL_OF, GUAVA_OPTIONAL_FROM_NULLABLE).test(innerExpectedCall)) {
registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::RemoveExpectedOutmostMethodCallQuickFix)
registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::UnwrapExpectedStaticMethodCallQuickFix)
} else if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) {
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_ABSENT)
}
@@ -88,7 +88,7 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
) {
registerConciseMethod(REMOVE_EXPECTED_OUTMOST_GUAVA_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod) { desc, method ->
QuickFixWithPostfixDelegate(
RemoveExpectedOutmostMethodCallQuickFix(desc, method),
UnwrapExpectedStaticMethodCallQuickFix(desc, method),
ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
)
}
@@ -10,7 +10,7 @@ import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
import de.platon42.intellij.plugins.cajon.quickfixes.RemoveActualOutmostMethodCallQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.RemoveExpectedOutmostMethodCallQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.UnwrapExpectedStaticMethodCallQuickFix
class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
@@ -33,7 +33,7 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
if (CallMatcher.anyOf(OPTIONAL_OF, OPTIONAL_OF_NULLABLE).test(innerExpectedCall)) {
registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::RemoveExpectedOutmostMethodCallQuickFix)
registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::UnwrapExpectedStaticMethodCallQuickFix)
} else if (OPTIONAL_EMPTY.test(innerExpectedCall)) {
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_NOT_PRESENT)
}
@@ -2,17 +2,17 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_ITERABLE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSizeMethodCallQuickFix
class AssertThatSizeInspection : AbstractAssertJInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting the size of an collection, array or string"
private const val REMOVE_SIZE_DESCRIPTION_TEMPLATE = "Remove size determination of expected expression and replace %s() with %s()"
private val BONUS_EXPRESSIONS_CALL_MATCHER_MAP = listOf(
IS_LESS_THAN_INT to MethodNames.HAS_SIZE_LESS_THAN,
@@ -28,14 +28,29 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!ASSERT_THAT_INT.test(expression)) {
val isAssertThatWithInt = ASSERT_THAT_INT.test(expression)
val isHasSize = HAS_SIZE.test(expression)
if (!(isAssertThatWithInt || isHasSize)) {
return
}
val actualExpression = expression.firstArg
val isForArrayOrCollection = isArrayLength(actualExpression) || isCollectionSize(actualExpression)
val isForString = isCharSequenceLength(actualExpression)
if (isForArrayOrCollection || isForString) {
if (isHasSize && (isForArrayOrCollection
|| (isForString && checkAssertedType(expression, ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME)))
) {
val assertThatCall = PsiTreeUtil.findChildrenOfType(expression, PsiMethodCallExpression::class.java).find { CORE_ASSERT_THAT_MATCHER.test(it) } ?: return
registerConciseMethod(
REMOVE_SIZE_DESCRIPTION_TEMPLATE,
holder,
assertThatCall,
expression,
MethodNames.HAS_SAME_SIZE_AS
) { desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method, expectedIsCollection = true, keepActualAsIs = true)
}
} else if (isForArrayOrCollection || isForString) {
val expectedCallExpression = expression.findOutmostMethodCall() ?: return
val constValue = calculateConstantParameterValue(expectedCallExpression, 0)
if (IS_EQUAL_TO_INT.test(expectedCallExpression)) {
@@ -11,14 +11,17 @@ class ReplaceSizeMethodCallQuickFix(
description: String,
private val replacementMethod: String,
private val noExpectedExpression: Boolean = false,
private val expectedIsCollection: Boolean = false
private val expectedIsCollection: Boolean = false,
private val keepActualAsIs: Boolean = false
) : AbstractCommonQuickFix(description) {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return
val assertExpression = methodCallExpression.firstArg
replaceCollectionSizeOrArrayLength(assertExpression)
if (!keepActualAsIs) {
val assertExpression = methodCallExpression.firstArg
replaceCollectionSizeOrArrayLength(assertExpression)
}
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
if (expectedIsCollection) {
@@ -8,7 +8,7 @@ import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class RemoveExpectedOutmostMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
class UnwrapExpectedStaticMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement
@@ -27,6 +27,7 @@ internal class AssertThatSizeInspectionTest : AbstractCajonTest() {
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isGreaterThanOrEqualTo() with hasSizeGreaterThanOrEqualTo()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThan() with hasSizeLessThan()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThanOrEqualTo() with hasSizeLessThanOrEqualTo()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove size determination of expected expression and replace hasSize() with hasSameSizeAs()"), 12)
myFixture.checkResultByFile("SizeAfter.java")
}
}
@@ -24,10 +24,14 @@ public class Size {
assertThat(list).hasSize(string.length());
assertThat(list).hasSize(stringBuilder.length());
assertThat(list).hasSize(1);
assertThat(list).hasSizeGreaterThan(list.size() * 2);
assertThat(list).hasSizeGreaterThanOrEqualTo(list.size() * 2);
assertThat(list).hasSizeLessThan(list.size() * 2);
assertThat(list).hasSizeLessThanOrEqualTo(list.size() * 2);
assertThat(list).hasSizeGreaterThan(otherList.size() * 2);
assertThat(list).hasSizeGreaterThanOrEqualTo(otherList.size() * 2);
assertThat(list).hasSizeLessThan(otherList.size() * 2);
assertThat(list).hasSizeLessThanOrEqualTo(otherList.size() * 2);
assertThat(list).hasSameSizeAs(otherList);
assertThat(list).hasSameSizeAs(array);
assertThat(list).hasSize(string.length());
assertThat(list).hasSize(stringBuilder.length());
assertThat(array).isEmpty();
assertThat(array).isEmpty();
@@ -45,6 +49,10 @@ public class Size {
assertThat(array).hasSizeGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(array).hasSizeLessThan(otherArray.length - 3);
assertThat(array).hasSizeLessThanOrEqualTo(1 - otherArray.length);
assertThat(array).hasSameSizeAs(list);
assertThat(array).hasSameSizeAs(otherArray);
assertThat(array).hasSize(string.length());
assertThat(array).hasSize(stringBuilder.length());
assertThat(string).isEmpty();
assertThat(string).isEmpty();
@@ -62,6 +70,10 @@ public class Size {
assertThat(string).hasSizeGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(string).hasSizeLessThan(otherArray.length - 3);
assertThat(string).hasSizeLessThanOrEqualTo(1 - otherArray.length);
assertThat(string).hasSameSizeAs(otherList);
assertThat(string).hasSameSizeAs(array);
assertThat(string).hasSameSizeAs(string);
assertThat(string).hasSameSizeAs(stringBuilder);
assertThat(stringBuilder).isEmpty();
assertThat(stringBuilder).isEmpty();
@@ -79,5 +91,9 @@ public class Size {
assertThat(stringBuilder).hasSizeGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(stringBuilder).hasSizeLessThan(otherArray.length - 3);
assertThat(stringBuilder).hasSizeLessThanOrEqualTo(1 - otherArray.length);
assertThat(stringBuilder).hasSameSizeAs(otherList);
assertThat(stringBuilder).hasSameSizeAs(array);
assertThat(stringBuilder).hasSameSizeAs(string);
assertThat(stringBuilder).hasSameSizeAs(stringBuilder);
}
}
@@ -24,10 +24,14 @@ public class Size {
assertThat(list.size()).isEqualTo(string.length());
assertThat(list.size()).isEqualTo(stringBuilder.length());
assertThat(list.size()).isEqualTo(1);
assertThat(list.size()).isGreaterThan(list.size() * 2);
assertThat(list.size()).isGreaterThanOrEqualTo(list.size() * 2);
assertThat(list.size()).isLessThan(list.size() * 2);
assertThat(list.size()).isLessThanOrEqualTo(list.size() * 2);
assertThat(list.size()).isGreaterThan(otherList.size() * 2);
assertThat(list.size()).isGreaterThanOrEqualTo(otherList.size() * 2);
assertThat(list.size()).isLessThan(otherList.size() * 2);
assertThat(list.size()).isLessThanOrEqualTo(otherList.size() * 2);
assertThat(list).hasSize(otherList.size());
assertThat(list).hasSize(array.length);
assertThat(list).hasSize(string.length());
assertThat(list).hasSize(stringBuilder.length());
assertThat(array.length).isEqualTo(0);
assertThat(array.length).isZero();
@@ -45,6 +49,10 @@ public class Size {
assertThat(array.length).isGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(array.length).isLessThan(otherArray.length - 3);
assertThat(array.length).isLessThanOrEqualTo(1 - otherArray.length);
assertThat(array).hasSize(list.size());
assertThat(array).hasSize(otherArray.length);
assertThat(array).hasSize(string.length());
assertThat(array).hasSize(stringBuilder.length());
assertThat(string.length()).isEqualTo(0);
assertThat(string.length()).isZero();
@@ -62,6 +70,10 @@ public class Size {
assertThat(string.length()).isGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(string.length()).isLessThan(otherArray.length - 3);
assertThat(string.length()).isLessThanOrEqualTo(1 - otherArray.length);
assertThat(string).hasSize(otherList.size());
assertThat(string).hasSize(array.length);
assertThat(string).hasSize(string.length());
assertThat(string).hasSize(stringBuilder.length());
assertThat(stringBuilder.length()).isEqualTo(0);
assertThat(stringBuilder.length()).isZero();
@@ -79,5 +91,9 @@ public class Size {
assertThat(stringBuilder.length()).isGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(stringBuilder.length()).isLessThan(otherArray.length - 3);
assertThat(stringBuilder.length()).isLessThanOrEqualTo(1 - otherArray.length);
assertThat(stringBuilder).hasSize(otherList.size());
assertThat(stringBuilder).hasSize(array.length);
assertThat(stringBuilder).hasSize(string.length());
assertThat(stringBuilder).hasSize(stringBuilder.length());
}
}