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. Added more method calls that are considered extension points.
This commit is contained in:
@@ -14,6 +14,8 @@ class AssertJClassNames {
|
||||
const val DESCRIPTABLE_INTERFACE = "org.assertj.core.api.Descriptable"
|
||||
@NonNls
|
||||
const val EXTENSION_POINTS_INTERFACE = "org.assertj.core.api.ExtensionPoints"
|
||||
@NonNls
|
||||
const val OBJECT_ENUMERABLE_ASSERT_INTERFACE = "org.assertj.core.api.ObjectEnumerableAssert"
|
||||
|
||||
@NonNls
|
||||
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 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 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(
|
||||
ALL_ASSERT_THAT_MATCHERS,
|
||||
|
||||
@@ -133,6 +133,7 @@ fun PsiExpression.getAllTheSameExpectedBooleanConstants(): Boolean? {
|
||||
} else {
|
||||
val isNotConstant = CallMatcher.anyOf(
|
||||
EXTENSION_POINTS,
|
||||
MORE_EXTENSION_POINTS,
|
||||
AbstractAssertJInspection.IS_EQUAL_TO_BOOLEAN,
|
||||
AbstractAssertJInspection.IS_EQUAL_TO_OBJECT,
|
||||
AbstractAssertJInspection.IS_NOT_EQUAL_TO_BOOLEAN,
|
||||
|
||||
@@ -84,6 +84,16 @@ class MethodNames {
|
||||
@NonNls
|
||||
const val CONTAINS_EXACTLY = "containsExactly"
|
||||
@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"
|
||||
@NonNls
|
||||
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(
|
||||
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
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.anyOf(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equals").parameterCount(1)!!,
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contentEquals").parameterCount(1)!!
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equals").parameterCount(1),
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contentEquals").parameterCount(1)
|
||||
),
|
||||
MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO
|
||||
),
|
||||
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
|
||||
),
|
||||
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
|
||||
),
|
||||
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
|
||||
),
|
||||
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
|
||||
)
|
||||
)
|
||||
|
||||
+3
-3
@@ -19,20 +19,20 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
|
||||
do {
|
||||
val commentsToKeep = ArrayList<PsiComment>()
|
||||
val stuffToDelete = ArrayList<PsiElement>()
|
||||
var previousStatement = lastStatement.prevSibling ?: throw IllegalStateException("Internal error")
|
||||
var previousStatement = lastStatement.prevSibling!!
|
||||
while (previousStatement !is PsiExpressionStatement) {
|
||||
if (previousStatement is PsiComment) {
|
||||
commentsToKeep.add(previousStatement.copy() as PsiComment)
|
||||
}
|
||||
stuffToDelete.add(previousStatement)
|
||||
previousStatement = previousStatement.prevSibling ?: throw IllegalStateException("Internal error")
|
||||
previousStatement = previousStatement.prevSibling!!
|
||||
}
|
||||
stuffToDelete.forEach { if (it.isValid) it.delete() }
|
||||
|
||||
val statementComments = PsiTreeUtil.getChildrenOfAnyType(previousStatement, PsiComment::class.java)
|
||||
commentsToKeep.addAll(statementComments)
|
||||
|
||||
val assertThatCallOfCursorStatement = lastStatement.findStaticMethodCall() ?: throw IllegalStateException("Internal error")
|
||||
val assertThatCallOfCursorStatement = lastStatement.findStaticMethodCall()!!
|
||||
|
||||
val lastElementBeforeConcat = assertThatCallOfCursorStatement.parent
|
||||
commentsToKeep.forEach {
|
||||
|
||||
+7
-5
@@ -34,11 +34,13 @@ class ReplaceIfByAssumeThatQuickFix(private val removeElse: Boolean) : AbstractC
|
||||
val anchorElement = ifStatement.nextSibling
|
||||
if (branchToKeep is PsiBlockStatement) {
|
||||
val codeBlock = branchToKeep.codeBlock
|
||||
val hasDeclarations = codeBlock.statements.any { it is PsiDeclarationStatement }
|
||||
if (hasDeclarations) {
|
||||
parentBlock.addAfter(branchToKeep, anchorElement)
|
||||
} else {
|
||||
parentBlock.addRangeAfter(codeBlock.firstBodyElement, codeBlock.lastBodyElement, anchorElement)
|
||||
if (codeBlock.statements.isNotEmpty()) {
|
||||
val hasDeclarations = codeBlock.statements.any { it is PsiDeclarationStatement }
|
||||
if (hasDeclarations) {
|
||||
parentBlock.addAfter(branchToKeep, anchorElement)
|
||||
} else {
|
||||
parentBlock.addRangeAfter(codeBlock.firstBodyElement, codeBlock.lastBodyElement, anchorElement)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parentBlock.addAfter(branchToKeep, anchorElement)
|
||||
|
||||
@@ -42,10 +42,12 @@
|
||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBinaryExpressionInspection"/>
|
||||
<localInspection groupPath="Java" shortName="AssertThatStringExpression" enabledByDefault="true" level="WARNING"
|
||||
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"
|
||||
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"/>
|
||||
|
||||
<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>
|
||||
Turns assertThat(string.someMethod(arg)).isTrue/isFalse() into assertThat(string).someMethod(arg).
|
||||
<!-- 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>
|
||||
</html>
|
||||
Reference in New Issue
Block a user