Added several cases for hasSizeGreaterThan/LessThan/OrEqualTo() for EnumerablesEmpty inspection.

This commit is contained in:
Chris Hodges 2020-10-02 19:24:22 +02:00
parent 1340a34782
commit d48c71d4ea
8 changed files with 90 additions and 11 deletions

View File

@ -415,11 +415,21 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
- AssertThatEnumerableIsEmpty - AssertThatEnumerableIsEmpty
Uses ```isEmpty()``` for ```hasSize(0)``` iterable assertions instead. Uses ```isEmpty()``` for ```hasSize(0)```, ```hasSizeLessThanOrEqualTo(0)```, and
```hasSizeLessThan(1)``` iterable (enumerable) assertions instead.
Also suggests ```isNotEmpty()``` for ```hasSizeGreaterThan(0)``` and
```hasSizeGreaterThanOrEqualTo(1)```.
``` ```
from: assertThat(enumerable).hasSize(0); from: assertThat(enumerable).hasSize(0);
from: assertThat(enumerable).hasSizeLessThanOrEqualTo(0);
from: assertThat(enumerable).hasSizeLessThan(1);
to: assertThat(enumerable).isEmpty(); to: assertThat(enumerable).isEmpty();
from: assertThat(enumerable).hasSizeGreaterThan(0);
from: assertThat(enumerable).hasSizeGreaterThanOrEqualTo(1);
to: assertThat(enumerable).isNotEmpty();
``` ```
- AssertThatSize - AssertThatSize
@ -805,6 +815,7 @@ Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for yo
- Updated various dependencies and AssertJ 3.17.2. - Updated various dependencies and AssertJ 3.17.2.
- Fixed the ImplicitAssertionInspection that broke the plugin with IntelliJ 2020.3 EAP as reported by Frédéric Thomas. Thanks! - Fixed the ImplicitAssertionInspection that broke the plugin with IntelliJ 2020.3 EAP as reported by Frédéric Thomas. Thanks!
- Added new singleElement() from AssertJ >= 3.17.0 to ImplicitAssertionInspection. - Added new singleElement() from AssertJ >= 3.17.0 to ImplicitAssertionInspection.
- Added several cases for ```hasSizeGreaterThan/LessThan/OrEqualTo()``` for EnumerablesEmpty inspection.
#### V1.10 (31-Jul-20) Friday the 31st Edition #### V1.10 (31-Jul-20) Friday the 31st Edition
- Updated libraries to the latest versions (including AssertJ 3.16.1 and Kotlin 1.40-rc). - Updated libraries to the latest versions (including AssertJ 3.16.1 and Kotlin 1.40-rc).

View File

@ -8,6 +8,8 @@ plugins {
group 'de.platon42' group 'de.platon42'
version '1.11' version '1.11'
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
repositories { repositories {
mavenCentral() mavenCentral()
@ -30,14 +32,10 @@ dependencies {
compileKotlin { compileKotlin {
kotlinOptions.jvmTarget = "1.8" kotlinOptions.jvmTarget = "1.8"
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
} }
compileTestKotlin { compileTestKotlin {
kotlinOptions.jvmTarget = "1.8" kotlinOptions.jvmTarget = "1.8"
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
} }
intellij { intellij {
@ -55,6 +53,7 @@ patchPluginXml {
<li>Updated various dependencies and AssertJ 3.17.2. <li>Updated various dependencies and AssertJ 3.17.2.
<li>Fixed the ImplicitAssertionInspection that broke the plugin with IntelliJ 2020.3 EAP as reported by Frédéric Thomas. Thanks! <li>Fixed the ImplicitAssertionInspection that broke the plugin with IntelliJ 2020.3 EAP as reported by Frédéric Thomas. Thanks!
<li>Added new singleElement() from AssertJ >= 3.17.0 to ImplicitAssertionInspection. <li>Added new singleElement() from AssertJ >= 3.17.0 to ImplicitAssertionInspection.
<li>Added several cases for hasSizeGreaterThan/LessThan/OrEqualTo() for EnumerablesEmpty inspection.
</ul> </ul>
<p>Full changelog available at <a href="https://github.com/chrisly42/cajon-plugin#changelog">Github project site</a>.</p> <p>Full changelog available at <a href="https://github.com/chrisly42/cajon-plugin#changelog">Github project site</a>.</p>
""" """

View File

@ -126,6 +126,14 @@ abstract class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool()
.parameterCount(0)!! .parameterCount(0)!!
val HAS_SIZE = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE) val HAS_SIZE = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE)
.parameterTypes("int")!! .parameterTypes("int")!!
val HAS_SIZE_GREATER_THAN_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_GREATER_THAN)
.parameterTypes("int")!!
val HAS_SIZE_GREATER_THAN_OR_EQUAL_TO_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_GREATER_THAN_OR_EQUAL_TO)
.parameterTypes("int")!!
val HAS_SIZE_LESS_THAN_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_LESS_THAN)
.parameterTypes("int")!!
val HAS_SIZE_LESS_THAN_OR_EQUAL_TO_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_LESS_THAN_OR_EQUAL_TO)
.parameterTypes("int")!!
val IS_GREATER_THAN_INT = CallMatcher.instanceCall(ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_GREATER_THAN) val IS_GREATER_THAN_INT = CallMatcher.instanceCall(ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_GREATER_THAN)
.parameterTypes("int")!! .parameterTypes("int")!!

View File

@ -5,6 +5,7 @@ import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiStatement import com.intellij.psi.PsiStatement
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue
import de.platon42.intellij.plugins.cajon.hasAssertThat import de.platon42.intellij.plugins.cajon.hasAssertThat
@ -12,7 +13,7 @@ import de.platon42.intellij.plugins.cajon.hasAssertThat
class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() { class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Asserting an empty enumerable" private const val DISPLAY_NAME = "Asserting an empty or not empty enumerable"
} }
override fun getDisplayName() = DISPLAY_NAME override fun getDisplayName() = DISPLAY_NAME
@ -23,11 +24,17 @@ class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
super.visitMethodCallExpression(expression) super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) return if (!expression.hasAssertThat()) return
val isLastExpression = expression.parent is PsiStatement val isLastExpression = expression.parent is PsiStatement
if (!(HAS_SIZE.test(expression) && isLastExpression)) return
val value = expression.calculateConstantParameterValue(0) ?: return val value = expression.calculateConstantParameterValue(0) ?: return
if (value == 0) {
val isEmpty = (CallMatcher.anyOf(HAS_SIZE, HAS_SIZE_LESS_THAN_OR_EQUAL_TO_INT).test(expression) && (value == 0)) ||
(HAS_SIZE_LESS_THAN_INT.test(expression) && (value == 1));
val isNotEmpty = (HAS_SIZE_GREATER_THAN_INT.test(expression) && (value == 0)) ||
(HAS_SIZE_GREATER_THAN_OR_EQUAL_TO_INT.test(expression) && (value == 1));
if (isEmpty && isLastExpression) {
registerSimplifyMethod(holder, expression, MethodNames.IS_EMPTY) registerSimplifyMethod(holder, expression, MethodNames.IS_EMPTY)
} else if (isNotEmpty) {
registerSimplifyMethod(holder, expression, MethodNames.IS_NOT_EMPTY)
} }
} }
} }

View File

@ -1,6 +1,6 @@
<html> <html>
<body> <body>
Turns assertThat(enumerable).hasSize(0) into assertThat(enumerable).isEmpty(). Turns assertThat(enumerable).hasSize(0) and similar into assertThat(enumerable).isEmpty() or .isNotEmpty().
<!-- tooltip end --> <!-- tooltip end -->
<br>Works with anything that is enumerable such as arrays, iterables, collections, etc. <br>Works with anything that is enumerable such as arrays, iterables, collections, etc.
</body> </body>

View File

@ -10,10 +10,14 @@ internal class AssertThatEnumerableIsEmptyInspectionTest : AbstractCajonTest() {
@Test @Test
@TestDataSubPath("inspections/EnumerableIsEmpty") @TestDataSubPath("inspections/EnumerableIsEmpty")
internal fun assertThat_with_hasSize_zero_can_use_isEmpty(@MyFixture myFixture: JavaCodeInsightTestFixture) { internal fun assertThat_with_hasSize_zero_and_similar_can_use_isEmpty(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatEnumerableIsEmptyInspection::class.java) myFixture.enableInspections(AssertThatEnumerableIsEmptyInspection::class.java)
myFixture.configureByFile("EnumerableIsEmptyBefore.java") myFixture.configureByFile("EnumerableIsEmptyBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSize() with isEmpty()"), 5) executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSize() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeLessThan() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeLessThanOrEqualTo() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeGreaterThan() with isNotEmpty()"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeGreaterThanOrEqualTo() with isNotEmpty()"), 6)
myFixture.checkResultByFile("EnumerableIsEmptyAfter.java") myFixture.checkResultByFile("EnumerableIsEmptyAfter.java")
} }
} }

View File

@ -16,7 +16,32 @@ public class EnumerableIsEmpty {
assertThat(new ArrayList<Long>()).as("etc").hasSize(1); assertThat(new ArrayList<Long>()).as("etc").hasSize(1);
assertThat(new Long[1]).as("etc").hasSize(1); assertThat(new Long[1]).as("etc").hasSize(1);
assertThat("string").as("foo").isEmpty();
assertThat(new StringBuilder()).as("bar").isEmpty();
assertThat(new ArrayList<Long>()).as("etc").isEmpty();
assertThat(new Long[1]).as("etc").isEmpty();
assertThat("string").as("foo").isEmpty();
assertThat(new StringBuilder()).as("bar").isEmpty();
assertThat(new ArrayList<Long>()).as("etc").isEmpty();
assertThat(new Long[1]).as("etc").isEmpty();
assertThat("string").as("foo").isNotEmpty();
assertThat(new StringBuilder()).as("bar").isNotEmpty();
assertThat(new ArrayList<Long>()).as("etc").isNotEmpty();
assertThat(new Long[1]).as("etc").isNotEmpty();
assertThat("string").as("foo").isNotEmpty();
assertThat(new StringBuilder()).as("bar").isNotEmpty();
assertThat(new ArrayList<Long>()).as("etc").isNotEmpty();
assertThat(new Long[1]).as("etc").isNotEmpty();
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").isEmpty(); assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").isEmpty();
assertThat("string").as("foo").hasSizeLessThanOrEqualTo(0).hasSameSizeAs("foo").isEmpty();
assertThat("string").as("foo").hasSizeLessThan(1).hasSameSizeAs("foo").isEmpty();
assertThat("string").as("foo").isNotEmpty().hasSameSizeAs("foo").isNotEmpty();
assertThat("string").as("foo").isNotEmpty().hasSameSizeAs("foo").isNotEmpty();
org.junit.Assert.assertThat("foo", null); org.junit.Assert.assertThat("foo", null);
fail("oh no!"); fail("oh no!");

View File

@ -16,7 +16,32 @@ public class EnumerableIsEmpty {
assertThat(new ArrayList<Long>()).as("etc").hasSize(1); assertThat(new ArrayList<Long>()).as("etc").hasSize(1);
assertThat(new Long[1]).as("etc").hasSize(1); assertThat(new Long[1]).as("etc").hasSize(1);
assertThat("string").as("foo").hasSizeLessThanOrEqualTo(0);
assertThat(new StringBuilder()).as("bar").hasSizeLessThanOrEqualTo(0 + 0);
assertThat(new ArrayList<Long>()).as("etc").hasSizeLessThanOrEqualTo(10 / 100);
assertThat(new Long[1]).as("etc").hasSizeLessThanOrEqualTo(1 - 1);
assertThat("string").as("foo").hasSizeLessThan(1);
assertThat(new StringBuilder()).as("bar").hasSizeLessThan(0 + 1);
assertThat(new ArrayList<Long>()).as("etc").hasSizeLessThan(10 / 10);
assertThat(new Long[1]).as("etc").hasSizeLessThan(1 - 0);
assertThat("string").as("foo").hasSizeGreaterThan(0);
assertThat(new StringBuilder()).as("bar").hasSizeGreaterThan(0 + 0);
assertThat(new ArrayList<Long>()).as("etc").hasSizeGreaterThan(10 / 100);
assertThat(new Long[1]).as("etc").hasSizeGreaterThan(1 - 1);
assertThat("string").as("foo").hasSizeGreaterThanOrEqualTo(1);
assertThat(new StringBuilder()).as("bar").hasSizeGreaterThanOrEqualTo(0 + 1);
assertThat(new ArrayList<Long>()).as("etc").hasSizeGreaterThanOrEqualTo(10 / 10);
assertThat(new Long[1]).as("etc").hasSizeGreaterThanOrEqualTo(1 - 0);
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").hasSize(0); assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").hasSize(0);
assertThat("string").as("foo").hasSizeLessThanOrEqualTo(0).hasSameSizeAs("foo").hasSizeLessThanOrEqualTo(0);
assertThat("string").as("foo").hasSizeLessThan(1).hasSameSizeAs("foo").hasSizeLessThan(1);
assertThat("string").as("foo").hasSizeGreaterThan(0).hasSameSizeAs("foo").hasSizeGreaterThan(0);
assertThat("string").as("foo").hasSizeGreaterThanOrEqualTo(1).hasSameSizeAs("foo").hasSizeGreaterThanOrEqualTo(1);
org.junit.Assert.assertThat("foo", null); org.junit.Assert.assertThat("foo", null);
fail("oh no!"); fail("oh no!");