diff --git a/README.md b/README.md
index 93af54d..c34fbf1 100644
--- a/README.md
+++ b/README.md
@@ -156,6 +156,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
from: assertThat(array.length).isEqualTo(anotherArray.length);
to: assertThat(array).hasSameSizeAs(anotherArray);
+
+ from: assertThat(array).hasSize(anotherArray.length);
+ to: assertThat(array).hasSameSizeAs(anotherArray);
```
and additionally with AssertJ 13.2.0 or later
@@ -181,6 +184,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
from: assertThat("string".length()).isEqualTo(collection.size())
to: assertThat("string").hasSameSizeAs(collection);
+
+ from: assertThat("string".length()).hasSize("strong".length())
+ to: assertThat("string").hasSameSizeAs("strong");
```
- AssertThatBinaryExpression
@@ -330,6 +336,7 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro
#### V0.7 (unreleased)
- Another fix for AssertThatGuavaOptional inspection regarding using the same family name for slightly different quick fix executions
(really, Jetbrains, this sucks for no reason).
+- Extended AssertThatSize inspection to transform ```hasSize()``` into ```hasSameSizeAs()```, if possible.
#### V0.6 (22-Apr-19)
- New AssertThatStringExpression inspection that will move ```isEmpty()```, ```equals()```, ```equalsIgnoreCase()```, ```contains()```,
diff --git a/build.gradle b/build.gradle
index cef0c0c..2823f93 100644
--- a/build.gradle
+++ b/build.gradle
@@ -44,6 +44,7 @@ patchPluginXml {
- Another fix for AssertThatGuavaOptional inspection regarding using the same family name for slightly different quick fix executions
(really, Jetbrains, this sucks for no reason).
+
- Extended AssertThatSize inspection to transform hasSize() into hasSameSizeAs(), if possible.
V0.6 (22-Apr-19)
@@ -54,15 +55,6 @@ patchPluginXml {
- Renamed a few inspections to better/shorter names.
- New AssertThatInstanceOf inspection that moves instanceof expressions out of assertThat().
- V0.5 (18-Apr-19)
-
- - Fixed incompatibility with IDEA versions < 2018.2 (affected AssertThatSizeInspection). Minimal version is now 2017.3.
-
- Fixed missing Guava imports (if not already present) for AssertThatGuavaInspection. This was a major PITA to get right.
-
- Added support for referencing and refactoring inside .extracting() methods with fields, properties and methods (though
- getter renaming does not work that perfect, but I'm giving up for now as the IntelliJ SDK docs are seriously lacking).
-
- Fixed an exception in batch mode if the description string was the same but for different fixes.
- Now descriptions are different for quick fixes triggered by AssertThatJava8OptionalInspection and AssertThatGuavaOptionalInspection.
-
Full changelog available at Github project site.
"""
}
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt
index 892dd5b..3e5cecb 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt
@@ -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(
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? {
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt
index ead9119..2ca223e 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt
@@ -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
)
}
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt
index 28c869f..5c3a788 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt
@@ -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)
}
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspection.kt
index cfef00b..3357b24 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspection.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspection.kt
@@ -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)) {
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceSizeMethodCallQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceSizeMethodCallQuickFix.kt
index fe9968a..e986d58 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceSizeMethodCallQuickFix.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceSizeMethodCallQuickFix.kt
@@ -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) {
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveExpectedOutmostMethodCallQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/UnwrapExpectedStaticMethodCallQuickFix.kt
similarity index 87%
rename from src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveExpectedOutmostMethodCallQuickFix.kt
rename to src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/UnwrapExpectedStaticMethodCallQuickFix.kt
index 17022b6..9ac6f4f 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveExpectedOutmostMethodCallQuickFix.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/UnwrapExpectedStaticMethodCallQuickFix.kt
@@ -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
diff --git a/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspectionTest.kt b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspectionTest.kt
index e8f13d0..5a1f8ba 100644
--- a/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspectionTest.kt
+++ b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatSizeInspectionTest.kt
@@ -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")
}
}
diff --git a/src/test/resources/inspections/Size/SizeAfter.java b/src/test/resources/inspections/Size/SizeAfter.java
index 18c5077..f807a52 100644
--- a/src/test/resources/inspections/Size/SizeAfter.java
+++ b/src/test/resources/inspections/Size/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);
}
}
diff --git a/src/test/resources/inspections/Size/SizeBefore.java b/src/test/resources/inspections/Size/SizeBefore.java
index bc7ea07..af48da1 100644
--- a/src/test/resources/inspections/Size/SizeBefore.java
+++ b/src/test/resources/inspections/Size/SizeBefore.java
@@ -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());
}
}