Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ecb5029154 | ||
|
|
0e2007641c |
@@ -169,6 +169,31 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
|||||||
```
|
```
|
||||||
Analogously with ```isFalse()```.
|
Analogously with ```isFalse()```.
|
||||||
|
|
||||||
|
- AssertThatCollectionOrMapExpression
|
||||||
|
|
||||||
|
Moves collection and map operations inside assertThat() out.
|
||||||
|
|
||||||
|
```
|
||||||
|
from: assertThat(collection.isEmpty()).isTrue();
|
||||||
|
to: assertThat(collection).isEmpty();
|
||||||
|
|
||||||
|
from: assertThat(collection.contains("foobar")).isTrue();
|
||||||
|
to: assertThat(collection).contains("foobar");
|
||||||
|
|
||||||
|
from: assertThat(collection.containsAll(otherCollection)).isTrue();
|
||||||
|
to: assertThat(collection).containsAll(otherCollection);
|
||||||
|
|
||||||
|
from: assertThat(map.isEmpty()).isTrue();
|
||||||
|
to: assertThat(map).isEmpty();
|
||||||
|
|
||||||
|
from: assertThat(map.containsKey(key)).isTrue();
|
||||||
|
to: assertThat(map).containsKey(key);
|
||||||
|
|
||||||
|
from: assertThat(map.containsValue(value)).isTrue();
|
||||||
|
to: assertThat(map).containsValue(value);
|
||||||
|
```
|
||||||
|
Analogously with ```isFalse()``` (except for containsAll()).
|
||||||
|
|
||||||
- AssertThatEnumerableIsEmpty
|
- AssertThatEnumerableIsEmpty
|
||||||
|
|
||||||
Uses ```isEmpty()``` for ```hasSize(0)``` iterable assertions instead.
|
Uses ```isEmpty()``` for ```hasSize(0)``` iterable assertions instead.
|
||||||
@@ -428,10 +453,14 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro
|
|||||||
to: assertThat(object).extracting(type::getPropOne, it -> it.propNoGetter, it -> it.getPropTwo().getInnerProp())...
|
to: assertThat(object).extracting(type::getPropOne, it -> it.propNoGetter, it -> it.getPropTwo().getInnerProp())...
|
||||||
```
|
```
|
||||||
|
|
||||||
- Kotlin support (right now, however, with less than 100 downloads after a month, this is unlikely to happen)
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
#### V1.0 (06-May-19)
|
||||||
|
- First release to be considered stable enough for production use.
|
||||||
|
- Fixed a NPE in AssumeThatInsteadOfReturn inspection quickfix for empty else branches.
|
||||||
|
- Fixed missing description for AssumeThatInsteadOfReturn inspection.
|
||||||
|
- Added new AssertThatCollectionOrMapExpression inspection that tries to pull out methods such as ```isEmpty()``` or ```contains()``` out of an actual assertThat() expression.
|
||||||
|
|
||||||
#### V0.8 (05-May-19)
|
#### V0.8 (05-May-19)
|
||||||
- Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
|
- Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
|
||||||
- Fixed ```isEmpty()``` for enumerables and strings and ```isNull()``` for object conversions to be applied only if it is the terminal method call as ```isEmpty()``` and ```isNull()``` return void.
|
- Fixed ```isEmpty()``` for enumerables and strings and ```isNull()``` for object conversions to be applied only if it is the terminal method call as ```isEmpty()``` and ```isNull()``` return void.
|
||||||
|
|||||||
+8
-9
@@ -7,7 +7,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group 'de.platon42'
|
group 'de.platon42'
|
||||||
version '0.8'
|
version '1.0'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -42,6 +42,13 @@ intellij {
|
|||||||
|
|
||||||
patchPluginXml {
|
patchPluginXml {
|
||||||
changeNotes """
|
changeNotes """
|
||||||
|
<h4>V1.0 (06-May-19)</h4>
|
||||||
|
<ul>
|
||||||
|
<li>First release to be considered stable enough for production use.
|
||||||
|
<li>Fixed a NPE in AssumeThatInsteadOfReturn inspection quickfix for empty else branches.
|
||||||
|
<li>Fixed missing description for AssumeThatInsteadOfReturn inspection.
|
||||||
|
<li>Added new AssertThatCollectionOrMapExpression inspection that tries to pull out methods such as isEmpty() or contains() out of an actual assertThat() expression.
|
||||||
|
</ul>
|
||||||
<h4>V0.8 (05-May-19)</h4>
|
<h4>V0.8 (05-May-19)</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
|
<li>Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
|
||||||
@@ -53,14 +60,6 @@ patchPluginXml {
|
|||||||
<li>Reworded many inspection messages for better understanding.
|
<li>Reworded many inspection messages for better understanding.
|
||||||
<li>Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls.
|
<li>Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls.
|
||||||
</ul>
|
</ul>
|
||||||
<h4>V0.7 (28-Apr-19)</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Another fix for AssertThatGuavaOptional inspection regarding using the same family name for slightly different quick fix executions
|
|
||||||
(really, Jetbrains, this sucks for no reason).
|
|
||||||
<li>Extended AssertThatSize inspection to transform hasSize() into hasSameSizeAs(), if possible.
|
|
||||||
<li>Implemented first version of JoinAssertThatStatements inspection that will try to merge assertThat() statements with the same
|
|
||||||
actual object together, preserving comments.
|
|
||||||
</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>
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class AssertJClassNames {
|
|||||||
const val DESCRIPTABLE_INTERFACE = "org.assertj.core.api.Descriptable"
|
const val DESCRIPTABLE_INTERFACE = "org.assertj.core.api.Descriptable"
|
||||||
@NonNls
|
@NonNls
|
||||||
const val EXTENSION_POINTS_INTERFACE = "org.assertj.core.api.ExtensionPoints"
|
const val EXTENSION_POINTS_INTERFACE = "org.assertj.core.api.ExtensionPoints"
|
||||||
|
@NonNls
|
||||||
|
const val OBJECT_ENUMERABLE_ASSERT_INTERFACE = "org.assertj.core.api.ObjectEnumerableAssert"
|
||||||
|
|
||||||
@NonNls
|
@NonNls
|
||||||
const val ASSERT_INTERFACE = "org.assertj.core.api.Assert"
|
const val ASSERT_INTERFACE = "org.assertj.core.api.Assert"
|
||||||
|
|||||||
@@ -23,7 +23,18 @@ val DESCRIBED_AS = CallMatcher.instanceCall(AssertJClassNames.DESCRIPTABLE_INTER
|
|||||||
val WITH_REPRESENTATION_AND_SUCH = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, "withRepresentation", "withThreadDumpOnError")!!
|
val WITH_REPRESENTATION_AND_SUCH = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, "withRepresentation", "withThreadDumpOnError")!!
|
||||||
val USING_COMPARATOR = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, "usingComparator", "usingDefaultComparator")!!
|
val USING_COMPARATOR = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, "usingComparator", "usingDefaultComparator")!!
|
||||||
val IN_HEXADECIMAL_OR_BINARY = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ASSERT_CLASSNAME, MethodNames.IN_HEXADECIMAL, MethodNames.IN_BINARY)!!
|
val IN_HEXADECIMAL_OR_BINARY = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ASSERT_CLASSNAME, MethodNames.IN_HEXADECIMAL, MethodNames.IN_BINARY)!!
|
||||||
val EXTENSION_POINTS = CallMatcher.instanceCall(AssertJClassNames.EXTENSION_POINTS_INTERFACE, "is", "isNot", "has", "doesNotHave", "satisfies")!!
|
val EXTENSION_POINTS = CallMatcher.instanceCall(
|
||||||
|
AssertJClassNames.EXTENSION_POINTS_INTERFACE,
|
||||||
|
"is", "isNot", "has", "doesNotHave",
|
||||||
|
"satisfies"
|
||||||
|
)!!
|
||||||
|
val MORE_EXTENSION_POINTS = CallMatcher.instanceCall(
|
||||||
|
AssertJClassNames.OBJECT_ENUMERABLE_ASSERT_INTERFACE,
|
||||||
|
"are", "areNot", "have", "doNotHave",
|
||||||
|
"areAtLeast", "areAtLeastOne", "areAtMost", "areExactly",
|
||||||
|
"haveAtLeastOne", "haveAtLeast", "haveAtMost", "haveExactly",
|
||||||
|
"hasOnlyOneElementSatisfying", "anyMatch", "noneMatch", "anySatisfy", "noneSatisfy"
|
||||||
|
)!!
|
||||||
|
|
||||||
val NOT_ACTUAL_ASSERTIONS = CallMatcher.anyOf(
|
val NOT_ACTUAL_ASSERTIONS = CallMatcher.anyOf(
|
||||||
ALL_ASSERT_THAT_MATCHERS,
|
ALL_ASSERT_THAT_MATCHERS,
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ fun PsiExpression.getAllTheSameExpectedBooleanConstants(): Boolean? {
|
|||||||
} else {
|
} else {
|
||||||
val isNotConstant = CallMatcher.anyOf(
|
val isNotConstant = CallMatcher.anyOf(
|
||||||
EXTENSION_POINTS,
|
EXTENSION_POINTS,
|
||||||
|
MORE_EXTENSION_POINTS,
|
||||||
AbstractAssertJInspection.IS_EQUAL_TO_BOOLEAN,
|
AbstractAssertJInspection.IS_EQUAL_TO_BOOLEAN,
|
||||||
AbstractAssertJInspection.IS_EQUAL_TO_OBJECT,
|
AbstractAssertJInspection.IS_EQUAL_TO_OBJECT,
|
||||||
AbstractAssertJInspection.IS_NOT_EQUAL_TO_BOOLEAN,
|
AbstractAssertJInspection.IS_NOT_EQUAL_TO_BOOLEAN,
|
||||||
|
|||||||
@@ -84,6 +84,16 @@ class MethodNames {
|
|||||||
@NonNls
|
@NonNls
|
||||||
const val CONTAINS_EXACTLY = "containsExactly"
|
const val CONTAINS_EXACTLY = "containsExactly"
|
||||||
@NonNls
|
@NonNls
|
||||||
|
const val CONTAINS_ALL = "containsAll"
|
||||||
|
@NonNls
|
||||||
|
const val CONTAINS_KEY = "containsKey"
|
||||||
|
@NonNls
|
||||||
|
const val DOES_NOT_CONTAIN_KEY = "doesNotContainKey"
|
||||||
|
@NonNls
|
||||||
|
const val CONTAINS_VALUE = "containsValue"
|
||||||
|
@NonNls
|
||||||
|
const val DOES_NOT_CONTAIN_VALUE = "doesNotContainValue"
|
||||||
|
@NonNls
|
||||||
const val IS_EQUAL_TO_IC = "isEqualToIgnoringCase"
|
const val IS_EQUAL_TO_IC = "isEqualToIgnoringCase"
|
||||||
@NonNls
|
@NonNls
|
||||||
const val IS_NOT_EQUAL_TO_IC = "isNotEqualToIgnoringCase"
|
const val IS_NOT_EQUAL_TO_IC = "isNotEqualToIgnoringCase"
|
||||||
|
|||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
package de.platon42.intellij.plugins.cajon.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import com.siyeh.ig.callMatcher.CallMatcher
|
||||||
|
import de.platon42.intellij.plugins.cajon.*
|
||||||
|
import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
|
||||||
|
|
||||||
|
class AssertThatCollectionOrMapExpressionInspection : AbstractAssertJInspection() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DISPLAY_NAME = "Asserting a collection or map specific expression"
|
||||||
|
|
||||||
|
private val MAPPINGS = listOf(
|
||||||
|
Mapping(
|
||||||
|
CallMatcher.anyOf(
|
||||||
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "isEmpty").parameterCount(0),
|
||||||
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "isEmpty").parameterCount(0)
|
||||||
|
),
|
||||||
|
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY
|
||||||
|
),
|
||||||
|
Mapping(
|
||||||
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "contains").parameterCount(1),
|
||||||
|
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN
|
||||||
|
),
|
||||||
|
Mapping(
|
||||||
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "containsAll").parameterCount(1),
|
||||||
|
MethodNames.CONTAINS_ALL, null
|
||||||
|
),
|
||||||
|
Mapping(
|
||||||
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "containsKey").parameterCount(1),
|
||||||
|
MethodNames.CONTAINS_KEY, MethodNames.DOES_NOT_CONTAIN_KEY
|
||||||
|
),
|
||||||
|
Mapping(
|
||||||
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "containsValue").parameterCount(1),
|
||||||
|
MethodNames.CONTAINS_VALUE, MethodNames.DOES_NOT_CONTAIN_VALUE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDisplayName() = DISPLAY_NAME
|
||||||
|
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||||
|
return object : JavaElementVisitor() {
|
||||||
|
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
|
||||||
|
super.visitExpressionStatement(statement)
|
||||||
|
if (!statement.hasAssertThat()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val staticMethodCall = statement.findStaticMethodCall() ?: return
|
||||||
|
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
|
||||||
|
val mapping = MAPPINGS.firstOrNull { it.callMatcher.test(assertThatArgument) } ?: return
|
||||||
|
|
||||||
|
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
|
||||||
|
val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
|
||||||
|
|
||||||
|
val replacementMethod = if (expectedResult) mapping.replacementForTrue else mapping.replacementForFalse ?: return
|
||||||
|
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod, ::MoveOutMethodCallExpressionQuickFix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Mapping(
|
||||||
|
val callMatcher: CallMatcher,
|
||||||
|
val replacementForTrue: String,
|
||||||
|
val replacementForFalse: String?
|
||||||
|
)
|
||||||
|
}
|
||||||
+7
-7
@@ -13,30 +13,30 @@ class AssertThatStringExpressionInspection : AbstractAssertJInspection() {
|
|||||||
|
|
||||||
private val MAPPINGS = listOf(
|
private val MAPPINGS = listOf(
|
||||||
Mapping(
|
Mapping(
|
||||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "isEmpty").parameterCount(0)!!,
|
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "isEmpty").parameterCount(0),
|
||||||
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY
|
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY
|
||||||
),
|
),
|
||||||
Mapping(
|
Mapping(
|
||||||
CallMatcher.anyOf(
|
CallMatcher.anyOf(
|
||||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equals").parameterCount(1)!!,
|
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equals").parameterCount(1),
|
||||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contentEquals").parameterCount(1)!!
|
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contentEquals").parameterCount(1)
|
||||||
),
|
),
|
||||||
MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO
|
MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO
|
||||||
),
|
),
|
||||||
Mapping(
|
Mapping(
|
||||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equalsIgnoreCase").parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!,
|
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equalsIgnoreCase").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
|
||||||
MethodNames.IS_EQUAL_TO_IC, MethodNames.IS_NOT_EQUAL_TO_IC
|
MethodNames.IS_EQUAL_TO_IC, MethodNames.IS_NOT_EQUAL_TO_IC
|
||||||
),
|
),
|
||||||
Mapping(
|
Mapping(
|
||||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contains").parameterCount(1)!!,
|
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contains").parameterCount(1),
|
||||||
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN
|
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN
|
||||||
),
|
),
|
||||||
Mapping(
|
Mapping(
|
||||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "startsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!,
|
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "startsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
|
||||||
MethodNames.STARTS_WITH, MethodNames.DOES_NOT_START_WITH
|
MethodNames.STARTS_WITH, MethodNames.DOES_NOT_START_WITH
|
||||||
),
|
),
|
||||||
Mapping(
|
Mapping(
|
||||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "endsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!,
|
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "endsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
|
||||||
MethodNames.ENDS_WITH, MethodNames.DOES_NOT_END_WITH
|
MethodNames.ENDS_WITH, MethodNames.DOES_NOT_END_WITH
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-2
@@ -15,7 +15,7 @@ class AssumeThatInsteadOfReturnInspection : AbstractAssertJInspection() {
|
|||||||
private const val MAX_RECURSION_DEPTH = 5
|
private const val MAX_RECURSION_DEPTH = 5
|
||||||
private const val MAX_STATEMENTS_COUNT = 50
|
private const val MAX_STATEMENTS_COUNT = 50
|
||||||
|
|
||||||
private val TEST_ANNOTATIONS = listOf(
|
private val TEST_ANNOTATIONS = setOf(
|
||||||
"org.junit.Test",
|
"org.junit.Test",
|
||||||
"org.junit.jupiter.api.Test",
|
"org.junit.jupiter.api.Test",
|
||||||
"org.junit.jupiter.api.TestTemplate",
|
"org.junit.jupiter.api.TestTemplate",
|
||||||
@@ -52,7 +52,9 @@ class AssumeThatInsteadOfReturnInspection : AbstractAssertJInspection() {
|
|||||||
return object : JavaElementVisitor() {
|
return object : JavaElementVisitor() {
|
||||||
override fun visitMethod(method: PsiMethod) {
|
override fun visitMethod(method: PsiMethod) {
|
||||||
super.visitMethod(method)
|
super.visitMethod(method)
|
||||||
if (TEST_ANNOTATIONS.none(method::hasAnnotation)) {
|
// Note: replace with if(TEST_ANNOTATIONS.none(method::hasAnnotation)) for IDEA >= 2018.2
|
||||||
|
val annotations = method.annotations.mapNotNull { it.qualifiedName }
|
||||||
|
if (annotations.none(TEST_ANNOTATIONS::contains)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val containingClass = method.containingClass ?: return
|
val containingClass = method.containingClass ?: return
|
||||||
|
|||||||
+5
-3
@@ -4,7 +4,7 @@ import com.intellij.codeInspection.ProblemHighlightType
|
|||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.siyeh.ig.psiutils.TrackingEquivalenceChecker
|
import com.siyeh.ig.psiutils.EquivalenceChecker
|
||||||
import de.platon42.intellij.plugins.cajon.*
|
import de.platon42.intellij.plugins.cajon.*
|
||||||
import de.platon42.intellij.plugins.cajon.quickfixes.JoinStatementsQuickFix
|
import de.platon42.intellij.plugins.cajon.quickfixes.JoinStatementsQuickFix
|
||||||
|
|
||||||
@@ -25,7 +25,8 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
|
|||||||
var sameCount = 0
|
var sameCount = 0
|
||||||
var firstStatement: PsiStatement? = null
|
var firstStatement: PsiStatement? = null
|
||||||
var lastStatement: PsiStatement? = null
|
var lastStatement: PsiStatement? = null
|
||||||
val equivalenceChecker = TrackingEquivalenceChecker()
|
// Note: replace with TrackingEquivalenceChecker() for IDEA >= 2019.1
|
||||||
|
val equivalenceChecker = EquivalenceChecker.getCanonicalPsiEquivalence()!!
|
||||||
for (statement in block.statements) {
|
for (statement in block.statements) {
|
||||||
val assertThatCall = isLegitAssertThatCall(statement)
|
val assertThatCall = isLegitAssertThatCall(statement)
|
||||||
var reset = true
|
var reset = true
|
||||||
@@ -36,9 +37,10 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
|
|||||||
if (!reset) {
|
if (!reset) {
|
||||||
val isSame = when (actualExpression) {
|
val isSame = when (actualExpression) {
|
||||||
is PsiMethodCallExpression -> equivalenceChecker.expressionsAreEquivalent(actualExpression, lastActualExpression)
|
is PsiMethodCallExpression -> equivalenceChecker.expressionsAreEquivalent(actualExpression, lastActualExpression)
|
||||||
|
// Note: replace with PsiTreeUtil.findChildrenOfAnyType(strict = false) for IDEA >= 2018.1
|
||||||
|
&& !KNOWN_METHODS_WITH_SIDE_EFFECTS.test(actualExpression)
|
||||||
&& PsiTreeUtil.findChildrenOfAnyType(
|
&& PsiTreeUtil.findChildrenOfAnyType(
|
||||||
actualExpression,
|
actualExpression,
|
||||||
false,
|
|
||||||
PsiMethodCallExpression::class.java
|
PsiMethodCallExpression::class.java
|
||||||
).none { KNOWN_METHODS_WITH_SIDE_EFFECTS.test(it) }
|
).none { KNOWN_METHODS_WITH_SIDE_EFFECTS.test(it) }
|
||||||
else -> equivalenceChecker.expressionsAreEquivalent(actualExpression, lastActualExpression)
|
else -> equivalenceChecker.expressionsAreEquivalent(actualExpression, lastActualExpression)
|
||||||
|
|||||||
+3
-3
@@ -19,20 +19,20 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
|
|||||||
do {
|
do {
|
||||||
val commentsToKeep = ArrayList<PsiComment>()
|
val commentsToKeep = ArrayList<PsiComment>()
|
||||||
val stuffToDelete = ArrayList<PsiElement>()
|
val stuffToDelete = ArrayList<PsiElement>()
|
||||||
var previousStatement = lastStatement.prevSibling ?: throw IllegalStateException("Internal error")
|
var previousStatement = lastStatement.prevSibling!!
|
||||||
while (previousStatement !is PsiExpressionStatement) {
|
while (previousStatement !is PsiExpressionStatement) {
|
||||||
if (previousStatement is PsiComment) {
|
if (previousStatement is PsiComment) {
|
||||||
commentsToKeep.add(previousStatement.copy() as PsiComment)
|
commentsToKeep.add(previousStatement.copy() as PsiComment)
|
||||||
}
|
}
|
||||||
stuffToDelete.add(previousStatement)
|
stuffToDelete.add(previousStatement)
|
||||||
previousStatement = previousStatement.prevSibling ?: throw IllegalStateException("Internal error")
|
previousStatement = previousStatement.prevSibling!!
|
||||||
}
|
}
|
||||||
stuffToDelete.forEach { if (it.isValid) it.delete() }
|
stuffToDelete.forEach { if (it.isValid) it.delete() }
|
||||||
|
|
||||||
val statementComments = PsiTreeUtil.getChildrenOfAnyType(previousStatement, PsiComment::class.java)
|
val statementComments = PsiTreeUtil.getChildrenOfAnyType(previousStatement, PsiComment::class.java)
|
||||||
commentsToKeep.addAll(statementComments)
|
commentsToKeep.addAll(statementComments)
|
||||||
|
|
||||||
val assertThatCallOfCursorStatement = lastStatement.findStaticMethodCall() ?: throw IllegalStateException("Internal error")
|
val assertThatCallOfCursorStatement = lastStatement.findStaticMethodCall()!!
|
||||||
|
|
||||||
val lastElementBeforeConcat = assertThatCallOfCursorStatement.parent
|
val lastElementBeforeConcat = assertThatCallOfCursorStatement.parent
|
||||||
commentsToKeep.forEach {
|
commentsToKeep.forEach {
|
||||||
|
|||||||
+2
@@ -34,12 +34,14 @@ class ReplaceIfByAssumeThatQuickFix(private val removeElse: Boolean) : AbstractC
|
|||||||
val anchorElement = ifStatement.nextSibling
|
val anchorElement = ifStatement.nextSibling
|
||||||
if (branchToKeep is PsiBlockStatement) {
|
if (branchToKeep is PsiBlockStatement) {
|
||||||
val codeBlock = branchToKeep.codeBlock
|
val codeBlock = branchToKeep.codeBlock
|
||||||
|
if (codeBlock.statements.isNotEmpty()) {
|
||||||
val hasDeclarations = codeBlock.statements.any { it is PsiDeclarationStatement }
|
val hasDeclarations = codeBlock.statements.any { it is PsiDeclarationStatement }
|
||||||
if (hasDeclarations) {
|
if (hasDeclarations) {
|
||||||
parentBlock.addAfter(branchToKeep, anchorElement)
|
parentBlock.addAfter(branchToKeep, anchorElement)
|
||||||
} else {
|
} else {
|
||||||
parentBlock.addRangeAfter(codeBlock.firstBodyElement, codeBlock.lastBodyElement, anchorElement)
|
parentBlock.addRangeAfter(codeBlock.firstBodyElement, codeBlock.lastBodyElement, anchorElement)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
parentBlock.addAfter(branchToKeep, anchorElement)
|
parentBlock.addAfter(branchToKeep, anchorElement)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,12 @@
|
|||||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBinaryExpressionInspection"/>
|
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBinaryExpressionInspection"/>
|
||||||
<localInspection groupPath="Java" shortName="AssertThatStringExpression" enabledByDefault="true" level="WARNING"
|
<localInspection groupPath="Java" shortName="AssertThatStringExpression" enabledByDefault="true" level="WARNING"
|
||||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatStringExpressionInspection"/>
|
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatStringExpressionInspection"/>
|
||||||
|
<localInspection groupPath="Java" shortName="AssertThatCollectionOrMapExpression" enabledByDefault="true" level="WARNING"
|
||||||
|
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatCollectionOrMapExpressionInspection"/>
|
||||||
|
|
||||||
<localInspection groupPath="Java" shortName="JoinAssertThatStatements" enabledByDefault="true" level="WARNING"
|
<localInspection groupPath="Java" shortName="JoinAssertThatStatements" enabledByDefault="true" level="WARNING"
|
||||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.JoinAssertThatStatementsInspection"/>
|
implementationClass="de.platon42.intellij.plugins.cajon.inspections.JoinAssertThatStatementsInspection"/>
|
||||||
<localInspection groupPath="Java" shortName="AssumeThatInsteadOfReturnInspection" enabledByDefault="true" level="WARNING"
|
<localInspection groupPath="Java" shortName="AssumeThatInsteadOfReturn" enabledByDefault="true" level="WARNING"
|
||||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssumeThatInsteadOfReturnInspection"/>
|
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssumeThatInsteadOfReturnInspection"/>
|
||||||
|
|
||||||
<localInspection groupPath="Java" shortName="AssertThatJava8Optional" enabledByDefault="true" level="WARNING"
|
<localInspection groupPath="Java" shortName="AssertThatJava8Optional" enabledByDefault="true" level="WARNING"
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
Turns assertThat(collectionOrMap.someMethod(arg)).isTrue/isFalse() into assertThat(collectionOrMap).someMethod(arg).
|
||||||
|
<!-- tooltip end -->
|
||||||
|
<br>someMethod() can be isEmpty(), contains(), and containsAll() for collections and
|
||||||
|
isEmpty(), containsKey(), and containsValue() for maps.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2,6 +2,6 @@
|
|||||||
<body>
|
<body>
|
||||||
Turns assertThat(string.someMethod(arg)).isTrue/isFalse() into assertThat(string).someMethod(arg).
|
Turns assertThat(string.someMethod(arg)).isTrue/isFalse() into assertThat(string).someMethod(arg).
|
||||||
<!-- tooltip end -->
|
<!-- tooltip end -->
|
||||||
<br>someMethod() can be equals(), equalsIgnoreCase(), contentEquals(), contains(), startsWith(), and endsWith().
|
<br>someMethod() can be isEmpty(), equals(), equalsIgnoreCase(), contentEquals(), contains(), startsWith(), and endsWith().
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
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 AssertThatCollectionOrMapExpressionInspectionTest : AbstractCajonTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestDataSubPath("inspections/CollectionMapExpression")
|
||||||
|
internal fun assertThat_with_certain_Collection_and_Map_methods(@MyFixture myFixture: JavaCodeInsightTestFixture) {
|
||||||
|
runTest {
|
||||||
|
myFixture.enableInspections(AssertThatCollectionOrMapExpressionInspection::class.java)
|
||||||
|
myFixture.configureByFile("CollectionMapExpressionBefore.java")
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of actual expression and use assertThat().isEmpty() instead"), 4)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().contains() instead"), 2)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsAll() of actual expression and use assertThat().containsAll() instead"), 2)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsKey() of actual expression and use assertThat().containsKey() instead"), 2)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsValue() of actual expression and use assertThat().containsValue() instead"), 2)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of actual expression and use assertThat().isNotEmpty() instead"), 5)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().doesNotContain() instead"), 2)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsKey() of actual expression and use assertThat().doesNotContainKey() instead"), 2)
|
||||||
|
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsValue() of actual expression and use assertThat().doesNotContainValue() instead"), 2)
|
||||||
|
myFixture.checkResultByFile("CollectionMapExpressionAfter.java")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -17,7 +17,7 @@ internal class AssumeThatInsteadOfReturnInspectionTest : AbstractCajonTest() {
|
|||||||
runTest {
|
runTest {
|
||||||
myFixture.enableInspections(AssumeThatInsteadOfReturnInspection::class.java)
|
myFixture.enableInspections(AssumeThatInsteadOfReturnInspection::class.java)
|
||||||
myFixture.configureByFile("AssumeThatBefore.java")
|
myFixture.configureByFile("AssumeThatBefore.java")
|
||||||
executeQuickFixes(myFixture, Regex.fromLiteral("Replace if statement by assumeTrue()"), 4)
|
executeQuickFixes(myFixture, Regex.fromLiteral("Replace if statement by assumeTrue()"), 5)
|
||||||
myFixture.checkResultByFile("AssumeThatAfter.java")
|
myFixture.checkResultByFile("AssumeThatAfter.java")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ public class AssumeThat {
|
|||||||
assertThat(foobar).isNotEmpty();
|
assertThat(foobar).isNotEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
public void junit5_return_with_empty_else_block() {
|
||||||
|
String foobar = System.getProperty("car_manufacturer");
|
||||||
|
assumeThat(foobar.equals("Volkswagen")).isFalse();
|
||||||
|
assertThat(foobar).isNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.TestTemplate
|
@org.junit.jupiter.api.TestTemplate
|
||||||
public void junit5_return_inside_recursion_with_comments() {
|
public void junit5_return_inside_recursion_with_comments() {
|
||||||
String foobar = System.getProperty("car_manufacturer");
|
String foobar = System.getProperty("car_manufacturer");
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ public class AssumeThat {
|
|||||||
assertThat(foobar).isNotEmpty();
|
assertThat(foobar).isNotEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
public void junit5_return_with_empty_else_block() {
|
||||||
|
String foobar = System.getProperty("car_manufacturer");
|
||||||
|
if (foobar.equals("Volkswagen")) return; else {}
|
||||||
|
assertThat(foobar).isNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.TestTemplate
|
@org.junit.jupiter.api.TestTemplate
|
||||||
public void junit5_return_inside_recursion_with_comments() {
|
public void junit5_return_inside_recursion_with_comments() {
|
||||||
String foobar = System.getProperty("car_manufacturer");
|
String foobar = System.getProperty("car_manufacturer");
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class CollectionMapExpression {
|
||||||
|
|
||||||
|
private void collectionMapExpression() {
|
||||||
|
List<String> stringList = new ArrayList<>();
|
||||||
|
List<String> anotherList = new ArrayList<>();
|
||||||
|
Map<String, Integer> keyValueMap = new HashMap<>();
|
||||||
|
|
||||||
|
assertThat(stringList).as("foo").isEmpty();
|
||||||
|
assertThat(stringList).isEmpty();
|
||||||
|
assertThat(stringList).contains("foo");
|
||||||
|
assertThat(stringList).contains("foo");
|
||||||
|
assertThat(stringList).containsAll(anotherList);
|
||||||
|
assertThat(stringList).containsAll(anotherList);
|
||||||
|
|
||||||
|
assertThat(stringList).as("foo").isNotEmpty();
|
||||||
|
assertThat(stringList).isNotEmpty();
|
||||||
|
assertThat(stringList).doesNotContain("foo");
|
||||||
|
assertThat(stringList).doesNotContain("foo");
|
||||||
|
assertThat(stringList.containsAll(anotherList)).isEqualTo(false);
|
||||||
|
assertThat(stringList.containsAll(anotherList)).isFalse();
|
||||||
|
|
||||||
|
assertThat(keyValueMap).as("foo").isEmpty();
|
||||||
|
assertThat(keyValueMap).isEmpty();
|
||||||
|
assertThat(keyValueMap).containsKey("foo");
|
||||||
|
assertThat(keyValueMap).containsKey("foo");
|
||||||
|
assertThat(keyValueMap).containsValue(2);
|
||||||
|
assertThat(keyValueMap).containsValue(2);
|
||||||
|
|
||||||
|
assertThat(keyValueMap).as("foo").isNotEmpty();
|
||||||
|
assertThat(keyValueMap).isNotEmpty();
|
||||||
|
assertThat(keyValueMap).doesNotContainKey("foo");
|
||||||
|
assertThat(keyValueMap).doesNotContainKey("foo");
|
||||||
|
assertThat(keyValueMap).doesNotContainValue(2);
|
||||||
|
assertThat(keyValueMap).doesNotContainValue(2);
|
||||||
|
|
||||||
|
assertThat(stringList).as("foo").isNotEmpty().as("bar").isNotEmpty();
|
||||||
|
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false).as("bar").isTrue();
|
||||||
|
assertThat(stringList.isEmpty()).as("foo").satisfies(it -> it.booleanValue()).as("bar").isFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class CollectionMapExpression {
|
||||||
|
|
||||||
|
private void collectionMapExpression() {
|
||||||
|
List<String> stringList = new ArrayList<>();
|
||||||
|
List<String> anotherList = new ArrayList<>();
|
||||||
|
Map<String, Integer> keyValueMap = new HashMap<>();
|
||||||
|
|
||||||
|
assertThat(stringList.isEmpty()).as("foo").isEqualTo(true);
|
||||||
|
assertThat(stringList.isEmpty()).isTrue();
|
||||||
|
assertThat(stringList.contains("foo")).isEqualTo(true);
|
||||||
|
assertThat(stringList.contains("foo")).isTrue();
|
||||||
|
assertThat(stringList.containsAll(anotherList)).isEqualTo(true);
|
||||||
|
assertThat(stringList.containsAll(anotherList)).isTrue();
|
||||||
|
|
||||||
|
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false);
|
||||||
|
assertThat(stringList.isEmpty()).isFalse();
|
||||||
|
assertThat(stringList.contains("foo")).isEqualTo(false);
|
||||||
|
assertThat(stringList.contains("foo")).isFalse();
|
||||||
|
assertThat(stringList.containsAll(anotherList)).isEqualTo(false);
|
||||||
|
assertThat(stringList.containsAll(anotherList)).isFalse();
|
||||||
|
|
||||||
|
assertThat(keyValueMap.isEmpty()).as("foo").isEqualTo(true);
|
||||||
|
assertThat(keyValueMap.isEmpty()).isTrue();
|
||||||
|
assertThat(keyValueMap.containsKey("foo")).isEqualTo(true);
|
||||||
|
assertThat(keyValueMap.containsKey("foo")).isTrue();
|
||||||
|
assertThat(keyValueMap.containsValue(2)).isEqualTo(true);
|
||||||
|
assertThat(keyValueMap.containsValue(2)).isTrue();
|
||||||
|
|
||||||
|
assertThat(keyValueMap.isEmpty()).as("foo").isEqualTo(false);
|
||||||
|
assertThat(keyValueMap.isEmpty()).isFalse();
|
||||||
|
assertThat(keyValueMap.containsKey("foo")).isEqualTo(false);
|
||||||
|
assertThat(keyValueMap.containsKey("foo")).isFalse();
|
||||||
|
assertThat(keyValueMap.containsValue(2)).isEqualTo(false);
|
||||||
|
assertThat(keyValueMap.containsValue(2)).isFalse();
|
||||||
|
|
||||||
|
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false).as("bar").isFalse();
|
||||||
|
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false).as("bar").isTrue();
|
||||||
|
assertThat(stringList.isEmpty()).as("foo").satisfies(it -> it.booleanValue()).as("bar").isFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user