diff --git a/README.md b/README.md
index c34fbf1..d366b1c 100644
--- a/README.md
+++ b/README.md
@@ -70,8 +70,21 @@ assertThat(array).hasSameSizeAs(collection);
You can toggle the various inspections in the Settings/Editor/Inspections in the AssertJ group.
-## Implemented inspections
+## Implemented inspections and quickfixes
+- JoinAssertThatStatements
+ ```
+ from: assertThat(expected).someCondition();
+ assertThat(expected).anotherCondition();
+ to: assertThat(expected).someCondition().anotherCondition();
+ ```
+ Joining will work on actual expressions inside assertThat() that are
+ - the same variable reference
+ - textually equal binary expressions
+ - the same method calls (except for known side-effect methods such as ```Iterator.next()``` -- please notify me about others)
+
+ The comments of the statements will be preserved. When using ```.extracting()``` or similar, the statements will not be merged.
+
- AssertThatObjectIsNullOrNotNull
```
from: assertThat(object).isEqualTo(null);
@@ -320,9 +333,8 @@ Cajon is probably the only plugin that uses JUnit 5 Jupiter for unit testing so
The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing and it took me quite a while to make it work with JUnit 5.
Feel free to use the code (in package de.platon42.intellij.jupiter) for your projects (with attribution).
-## TODO
+## Planned features
- AssumeThatInsteadOfReturn
-- Join consecutive assertThats
- Extraction with property names to lambda with Java 8
```
from: assertThat(object).extracting("propOne", "propNoGetter", "propTwo.innerProp")...
@@ -333,10 +345,12 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro
## Changelog
-#### V0.7 (unreleased)
+#### V0.7 (28-Apr-19)
- 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.
+- Implemented first version of JoinAssertThatStatements inspection that will try to merge ```assertThat()``` statements with the same
+ actual object together, preserving comments.
#### V0.6 (22-Apr-19)
- New AssertThatStringExpression inspection that will move ```isEmpty()```, ```equals()```, ```equalsIgnoreCase()```, ```contains()```,
diff --git a/build.gradle b/build.gradle
index 2823f93..e1bcef4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,7 @@
plugins {
id 'java'
id 'org.jetbrains.intellij' version '0.4.8'
- id 'org.jetbrains.kotlin.jvm' version '1.3.30'
+ id 'org.jetbrains.kotlin.jvm' version '1.3.31'
}
group 'de.platon42'
@@ -40,12 +40,14 @@ intellij {
patchPluginXml {
changeNotes """
-
V0.7 (unreleased)
+ V0.7 (28-Apr-19)
- 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.
-
+ Implemented first version of JoinAssertThatStatements inspection that will try to merge assertThat() statements with the same
+ actual object together, preserving comments.
+
V0.6 (22-Apr-19)
- New AssertThatStringExpression inspection that will move isEmpty(), equals(), equalsIgnoreCase(), contains(),
@@ -54,7 +56,7 @@ patchPluginXml {
- New AssertThatInvertedBooleanCondition inspection that will remove inverted boolean expressions inside assertThat().
- Renamed a few inspections to better/shorter names.
- New AssertThatInstanceOf inspection that moves instanceof expressions out of assertThat().
-
+
Full changelog available at Github project site.
"""
}
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/CommonMatchers.kt b/src/main/java/de/platon42/intellij/plugins/cajon/CommonMatchers.kt
new file mode 100644
index 0000000..bafe3c2
--- /dev/null
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/CommonMatchers.kt
@@ -0,0 +1,23 @@
+package de.platon42.intellij.plugins.cajon
+
+import com.intellij.psi.CommonClassNames
+import com.siyeh.ig.callMatcher.CallMatcher
+
+val CORE_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!!
+val GUAVA_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.GUAVA_ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!!
+val ALL_ASSERT_THAT_MATCHERS = CallMatcher.anyOf(CORE_ASSERT_THAT_MATCHER, GUAVA_ASSERT_THAT_MATCHER)!!
+val EXTRACTING_FROM_OBJECT = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ASSERT_CLASSNAME, "extracting")!!
+val EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extracting")!!
+val FLAT_EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "flatExtracting")!!
+val EXTRACTING_RESULT_OF_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extractingResultOf")!!
+
+val EXTRACTING_CALL_MATCHERS = CallMatcher.anyOf(
+ EXTRACTING_FROM_OBJECT,
+ EXTRACTING_FROM_ITERABLE,
+ FLAT_EXTRACTING_FROM_ITERABLE,
+ EXTRACTING_RESULT_OF_FROM_ITERABLE
+)!!
+
+val KNOWN_METHODS_WITH_SIDE_EFFECTS = CallMatcher.anyOf(
+ CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_ITERATOR, "next")
+)!!
\ No newline at end of file
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/Extensions.kt b/src/main/java/de/platon42/intellij/plugins/cajon/Extensions.kt
index fcb26a7..c9d5563 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/Extensions.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/Extensions.kt
@@ -4,6 +4,7 @@ import com.intellij.psi.*
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.util.PsiTreeUtil
+import com.siyeh.ig.callMatcher.CallMatcher
val PsiMethodCallExpression.qualifierExpression: PsiExpression get() = this.methodExpression.qualifierExpression!!
val PsiMethodCallExpression.firstArg: PsiExpression get() = this.argumentList.expressions[0]!!
@@ -21,6 +22,17 @@ fun PsiElement.findOutmostMethodCall(): PsiMethodCallExpression? {
return PsiTreeUtil.findChildOfType(statement, PsiMethodCallExpression::class.java)
}
+fun PsiMethodCallExpression.findFluentCallTo(matcher: CallMatcher): PsiMethodCallExpression? {
+ var currentMethodCall: PsiMethodCallExpression? = this
+ while (currentMethodCall != null) {
+ if (matcher.test(currentMethodCall)) {
+ return currentMethodCall
+ }
+ currentMethodCall = PsiTreeUtil.getParentOfType(currentMethodCall, PsiMethodCallExpression::class.java, true, PsiStatement::class.java)
+ }
+ return null
+}
+
fun PsiMethodCallExpression.getArg(n: Int): PsiExpression = this.argumentList.expressions[n]
fun Boolean.map(forTrue: T, forFalse: T) = if (this) forTrue else forFalse
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt b/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt
index 66ef68e..6509572 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt
@@ -4,9 +4,6 @@ import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiMethodCallExpression
-import com.siyeh.ig.callMatcher.CallMatcher
-
-val CORE_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!!
fun createAssertThat(context: PsiElement, actualExpression: PsiExpression): PsiMethodCallExpression {
return createAssertThat(context, AssertJClassNames.ASSERTIONS_CLASSNAME, actualExpression)
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JoinAssertThatStatementsInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JoinAssertThatStatementsInspection.kt
new file mode 100644
index 0000000..0948727
--- /dev/null
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JoinAssertThatStatementsInspection.kt
@@ -0,0 +1,87 @@
+package de.platon42.intellij.plugins.cajon.inspections
+
+import com.intellij.codeInspection.ProblemHighlightType
+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.quickfixes.JoinStatementsQuickFix
+
+class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
+
+ companion object {
+ private const val DISPLAY_NAME = "Joining multiple assertThat() statements with same actual expression"
+ private const val CAN_BE_JOINED_DESCRIPTION = "Multiple assertThat() statements can be joined together"
+ }
+
+ override fun getDisplayName() = DISPLAY_NAME
+
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
+ return object : JavaElementVisitor() {
+ 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
+ for (statement in statements) {
+ val assertThatCall = isLegitAssertThatCall(statement)
+ var reset = true
+ var actualExpression: PsiExpression? = null
+ if (assertThatCall != null) {
+ reset = (lastActualExpression == null)
+ actualExpression = assertThatCall.firstArg
+ if (!reset) {
+ val isSame = when (actualExpression) {
+ is PsiReferenceExpression -> (actualExpression.qualifierExpression == (lastActualExpression as? PsiReferenceExpression)?.qualifierExpression)
+ is PsiMethodCallExpression -> (actualExpression.text == (lastActualExpression as? PsiMethodCallExpression)?.text)
+ && !KNOWN_METHODS_WITH_SIDE_EFFECTS.test(actualExpression)
+ is PsiPolyadicExpression -> (actualExpression.text == (lastActualExpression as? PsiPolyadicExpression)?.text)
+ else -> false
+ }
+ if (isSame) {
+ sameCount++
+ lastStatement = statement
+ } else {
+ reset = true
+ }
+ }
+ }
+ if (reset) {
+ if (sameCount > 1) {
+ registerProblem(firstStatement, lastStatement)
+ }
+ firstStatement = statement
+ lastStatement = null
+ lastActualExpression = actualExpression
+ sameCount = 1
+ }
+ }
+ if (sameCount > 1) {
+ registerProblem(firstStatement, lastStatement)
+ }
+ }
+
+ private fun registerProblem(firstStatement: PsiStatement?, lastStatement: PsiStatement?) {
+ val problemDescriptor = holder.manager.createProblemDescriptor(
+ firstStatement!!,
+ lastStatement!!,
+ CAN_BE_JOINED_DESCRIPTION,
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ isOnTheFly,
+ JoinStatementsQuickFix()
+ )
+ holder.registerProblem(problemDescriptor)
+ }
+
+ private fun isLegitAssertThatCall(statement: PsiStatement?): PsiMethodCallExpression? {
+ if ((statement is PsiExpressionStatement) && (statement.expression is PsiMethodCallExpression)) {
+ val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) }
+ return assertThatCall?.takeIf { it.findFluentCallTo(EXTRACTING_CALL_MATCHERS) == null }
+ }
+ return null
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/JoinStatementsQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/JoinStatementsQuickFix.kt
new file mode 100644
index 0000000..ed94fcc
--- /dev/null
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/JoinStatementsQuickFix.kt
@@ -0,0 +1,54 @@
+package de.platon42.intellij.plugins.cajon.quickfixes
+
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.*
+import com.intellij.psi.codeStyle.CodeStyleManager
+import com.intellij.psi.util.PsiTreeUtil
+import de.platon42.intellij.plugins.cajon.ALL_ASSERT_THAT_MATCHERS
+
+class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
+ companion object {
+ private const val JOIN_STATEMENTS_MESSAGE = "Join assertThat() statements"
+ }
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val firstStatement = descriptor.startElement as PsiExpressionStatement
+ val lastStatement = descriptor.endElement as PsiExpressionStatement
+ do {
+ val commentsToKeep = ArrayList()
+ val stuffToDelete = ArrayList()
+ var previousStatement = lastStatement.prevSibling ?: throw IllegalStateException("Internal error")
+ while (previousStatement !is PsiExpressionStatement) {
+ if (previousStatement is PsiComment) {
+ commentsToKeep.add(previousStatement.copy() as PsiComment)
+ }
+ stuffToDelete.add(previousStatement)
+ previousStatement = previousStatement.prevSibling ?: throw IllegalStateException("Internal error")
+ }
+ stuffToDelete.forEach { if (it.isValid) it.delete() }
+
+ val statementComments = PsiTreeUtil.getChildrenOfAnyType(previousStatement, PsiComment::class.java)
+ commentsToKeep.addAll(statementComments)
+
+ val assertThatCallOfCursorStatement =
+ PsiTreeUtil.findChildrenOfType(lastStatement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) }
+ ?: throw IllegalStateException("Internal error")
+
+ val lastElementBeforeConcat = assertThatCallOfCursorStatement.parent
+ commentsToKeep.forEach {
+ lastElementBeforeConcat.addAfter(it, lastElementBeforeConcat.firstChild)
+ val newLineNode =
+ PsiParserFacade.SERVICE.getInstance(project).createWhiteSpaceFromText("\n\t")
+
+ lastElementBeforeConcat.addAfter(newLineNode, lastElementBeforeConcat.firstChild)
+ }
+
+ val newLeaf = previousStatement.firstChild
+ assertThatCallOfCursorStatement.replace(newLeaf)
+ previousStatement.delete()
+ } while (previousStatement !== firstStatement)
+ val codeBlock = PsiTreeUtil.getParentOfType(lastStatement, PsiCodeBlock::class.java) ?: return
+ CodeStyleManager.getInstance(project).reformat(codeBlock)
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveInstanceOfExpressionQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveInstanceOfExpressionQuickFix.kt
index b5874d2..6692b10 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveInstanceOfExpressionQuickFix.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveInstanceOfExpressionQuickFix.kt
@@ -5,7 +5,7 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiInstanceOfExpression
import com.intellij.psi.PsiMethodCallExpression
-import com.intellij.psi.PsiParenthesizedExpression
+import com.intellij.psi.util.PsiUtil
import de.platon42.intellij.plugins.cajon.createExpectedMethodCall
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
@@ -21,11 +21,7 @@ class RemoveInstanceOfExpressionQuickFix(description: String, private val replac
val factory = JavaPsiFacade.getElementFactory(project)
val classObjectAccess = factory.createExpressionFromText("${expectedClass.type.canonicalText}.class", null)
- var operand = assertExpression.operand
- while (operand is PsiParenthesizedExpression) {
- operand = operand.expression ?: return
- }
-
+ val operand = PsiUtil.deparenthesizeExpression(assertExpression.operand) ?: return
assertExpression.replace(operand)
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveUnaryExpressionQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveUnaryExpressionQuickFix.kt
index fc453ee..e29e248 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveUnaryExpressionQuickFix.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveUnaryExpressionQuickFix.kt
@@ -3,8 +3,8 @@ package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMethodCallExpression
-import com.intellij.psi.PsiParenthesizedExpression
import com.intellij.psi.PsiUnaryExpression
+import com.intellij.psi.util.PsiUtil
import de.platon42.intellij.plugins.cajon.createExpectedMethodCall
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
@@ -16,10 +16,7 @@ class RemoveUnaryExpressionQuickFix(description: String, private val replacement
val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return
val assertExpression = methodCallExpression.firstArg as? PsiUnaryExpression ?: return
- var operand = assertExpression.operand ?: return
- while (operand is PsiParenthesizedExpression) {
- operand = operand.expression ?: return
- }
+ val operand = PsiUtil.skipParenthesizedExprDown(assertExpression.operand) ?: return
assertExpression.replace(operand)
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributor.kt b/src/main/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributor.kt
index 97d7684..5f41ed4 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributor.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributor.kt
@@ -10,19 +10,11 @@ import com.intellij.psi.util.PsiTypesUtil
import com.intellij.util.ArrayUtil
import com.intellij.util.ProcessingContext
import com.siyeh.ig.callMatcher.CallMatcher
-import de.platon42.intellij.plugins.cajon.AssertJClassNames
-import de.platon42.intellij.plugins.cajon.CORE_ASSERT_THAT_MATCHER
-import de.platon42.intellij.plugins.cajon.firstArg
+import de.platon42.intellij.plugins.cajon.*
class ExtractorReferenceContributor : PsiReferenceContributor() {
companion object {
-
- private val EXTRACTING_FROM_OBJECT = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ASSERT_CLASSNAME, "extracting")
- private val EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extracting")
- private val FLAT_EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "flatExtracting")
- private val EXTRACTING_RESULT_OF_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extractingResultOf")
-
private val BY_NAME = CallMatcher.staticCall(AssertJClassNames.EXTRACTORS_CLASSNAME, "byName")
private val RESULT_OF = CallMatcher.staticCall(AssertJClassNames.EXTRACTORS_CLASSNAME, "resultOf")
.parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index c40a17a..416cbcd 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -43,6 +43,9 @@
+
+
list = new ArrayList<>();
+ assertThat(list).as("foo").hasSize(2);
+ assertThat(list).as("bar").contains("barbar"); // comment to keep
+ assertThat(list).as("etc").contains("etcetc");
+
+ // moar!
+ assertThat(list).doesNotContain("foobar");
+
+ assertThat("narf").isNotEqualTo("puit");
+ assertThat(list).as("bar").contains("barbar");
+ assertThat(list).as("foo").hasSize(2);
+ assertThat(list).as("evil").extracting(String::length).contains(2);
+
+ assertThat(list).as("bar").contains("barbar");
+ assertThat("narf").isNotEqualTo("puit");
+ assertThat(list).as("foo").hasSize(2);
+ if (true) {
+ assertThat(list).doesNotContain("narf");
+ assertThat(list).as("bar").contains("barbar");
+ }
+ assertThat(list.get(0)).isNotEmpty();
+ assertThat(list.get(0)).hasSize(3);
+ assertThat(list.get(0)).isEqualTo("bar");
+
+ assertThat(list.get(0) + "foo").isEqualTo("bar");
+ assertThat(list.get(0) + "foo").doesNotStartWith("foo");
+
+ Iterator iterator = list.iterator();
+ assertThat(iterator.next()).isEqualTo("foo");
+ assertThat(iterator.next()).isEqualTo("bar");
+ }
+
private void sizeOfArray() {
assertThat(new String[1].length).isLessThanOrEqualTo(1);
assertThat(new String[1]).hasSameSizeAs(new Object());
diff --git a/src/test/java/de/platon42/intellij/plugins/cajon/inspections/JoinAssertThatStatementsInspectionTest.kt b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/JoinAssertThatStatementsInspectionTest.kt
new file mode 100644
index 0000000..c760ff2
--- /dev/null
+++ b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/JoinAssertThatStatementsInspectionTest.kt
@@ -0,0 +1,21 @@
+package de.platon42.intellij.plugins.cajon.inspections
+
+import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
+import de.platon42.intellij.jupiter.MyFixture
+import de.platon42.intellij.jupiter.TestDataSubPath
+import de.platon42.intellij.plugins.cajon.AbstractCajonTest
+import org.junit.jupiter.api.Test
+
+internal class JoinAssertThatStatementsInspectionTest : AbstractCajonTest() {
+
+ @Test
+ @TestDataSubPath("inspections/JoinStatements")
+ internal fun assertThat_size_of_array_or_collection_can_be_simplified(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.enableInspections(JoinAssertThatStatementsInspection::class.java)
+ myFixture.configureByFile("JoinStatementsBefore.java")
+ executeQuickFixes(myFixture, Regex.fromLiteral("Join assertThat() statements"), 6)
+ myFixture.checkResultByFile("JoinStatementsAfter.java")
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/inspections/JoinStatements/JoinStatementsAfter.java b/src/test/resources/inspections/JoinStatements/JoinStatementsAfter.java
new file mode 100644
index 0000000..3b18060
--- /dev/null
+++ b/src/test/resources/inspections/JoinStatements/JoinStatementsAfter.java
@@ -0,0 +1,40 @@
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JoinStatements {
+
+ private void joinStatements() {
+ List list = new ArrayList<>();
+ // the future is always born in pain
+ /* tricky */
+ assertThat(list).as("foo").hasSize(2)
+ /* do another */
+ /* do one */.as("bar").contains("barbar")
+ // comment to keep
+ .doesNotContain("barbara") // another comment to keep
+ .doesNotContain("wrzlbrmpft")
+ /* and a multi line comment
+ after the statement */
+ // across two lines
+ .as("etc")/* what a nasty comment */.contains("etcetc")
+ // moar!
+ .doesNotContain("foobar");
+
+ assertThat("narf").isNotEqualTo("puit").as("bar").contains("barbar").as("foo").hasSize(2);
+ assertThat(list).as("evil").extracting(String::length).contains(2);
+
+ assertThat(list).as("bar").contains("barbar");
+ assertThat("narf").isNotEqualTo("puit").as("foo").hasSize(2);
+ if (true) {
+ assertThat(list).doesNotContain("narf").as("bar").contains("barbar");
+ }
+ assertThat(list.get(0)).isNotEmpty().hasSize(3).isEqualTo("bar");
+
+ assertThat(list.get(0) + "foo").isEqualTo("bar").doesNotStartWith("foo");
+
+ Iterator iterator = list.iterator();
+ assertThat(iterator.next()).isEqualTo("foo");
+ assertThat(iterator.next()).isEqualTo("bar");
+ }
+}
diff --git a/src/test/resources/inspections/JoinStatements/JoinStatementsBefore.java b/src/test/resources/inspections/JoinStatements/JoinStatementsBefore.java
new file mode 100644
index 0000000..7e924d1
--- /dev/null
+++ b/src/test/resources/inspections/JoinStatements/JoinStatementsBefore.java
@@ -0,0 +1,44 @@
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JoinStatements {
+
+ private void joinStatements() {
+ List list = new ArrayList<>();
+ // the future is always born in pain
+ /* tricky */assertThat(list).as("foo").hasSize(2); /* do one */ /* do another */
+ assertThat(list).as("bar").contains("barbar"); // comment to keep
+ assertThat(list).doesNotContain("barbara") // another comment to keep
+ .doesNotContain("wrzlbrmpft") // across two lines
+ ; /* and a multi line comment
+ after the statement */
+ assertThat(list).as("etc")/* what a nasty comment */.contains("etcetc");
+
+ // moar!
+ assertThat(list).doesNotContain("foobar");
+
+ assertThat("narf").isNotEqualTo("puit");
+ assertThat(list).as("bar").contains("barbar");
+ assertThat(list).as("foo").hasSize(2);
+ assertThat(list).as("evil").extracting(String::length).contains(2);
+
+ assertThat(list).as("bar").contains("barbar");
+ assertThat("narf").isNotEqualTo("puit");
+ assertThat(list).as("foo").hasSize(2);
+ if (true) {
+ assertThat(list).doesNotContain("narf");
+ assertThat(list).as("bar").contains("barbar");
+ }
+ assertThat(list.get(0)).isNotEmpty();
+ assertThat(list.get(0)).hasSize(3);
+ assertThat(list.get(0)).isEqualTo("bar");
+
+ assertThat(list.get(0) + "foo").isEqualTo("bar");
+ assertThat(list.get(0) + "foo").doesNotStartWith("foo");
+
+ Iterator iterator = list.iterator();
+ assertThat(iterator.next()).isEqualTo("foo");
+ assertThat(iterator.next()).isEqualTo("bar");
+ }
+}