Added new AssertThatFileExpression to move out many common methods from inside the assertThat() expression (exists(), getName(), getParent(), and many more).
This commit is contained in:
@@ -44,6 +44,8 @@ class AssertJClassNames {
|
||||
@NonNls
|
||||
const val ABSTRACT_MAP_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractMapAssert"
|
||||
@NonNls
|
||||
const val ABSTRACT_OBJECT_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractObjectArrayAssert"
|
||||
@NonNls
|
||||
const val ABSTRACT_ITERABLE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractIterableAssert"
|
||||
@NonNls
|
||||
const val ABSTRACT_OPTIONAL_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractOptionalAssert"
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
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 AssertThatFileExpressionInspection : AbstractAssertJInspection() {
|
||||
|
||||
companion object {
|
||||
private const val DISPLAY_NAME = "Asserting a file specific expression"
|
||||
|
||||
private val MAPPINGS = listOf(
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "canRead"),
|
||||
"canRead", expectBoolean = true
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "canWrite"),
|
||||
"canWrite", expectBoolean = true
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "exists"),
|
||||
"exists", "doesNotExist", expectBoolean = true
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "isAbsolute"),
|
||||
"isAbsolute", "isRelative", expectBoolean = true
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "isDirectory"),
|
||||
"isDirectory", expectBoolean = true
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "isFile"),
|
||||
"isFile", expectBoolean = true
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getName"),
|
||||
"hasName",
|
||||
expectedMatcher = CallMatcher.anyOf(IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_STRING)
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getParent", "getParentFile"),
|
||||
"hasNoParent", expectNullNonNull = true
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getParent"),
|
||||
"hasParent",
|
||||
expectedMatcher = CallMatcher.anyOf(IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_STRING)
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getParentFile"),
|
||||
"hasParent",
|
||||
expectedMatcher = IS_EQUAL_TO_OBJECT
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "list", "listFiles"),
|
||||
"isEmptyDirectory",
|
||||
expectedMatcher = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ARRAY_ASSERT_CLASSNAME, MethodNames.IS_EMPTY)
|
||||
.parameterCount(0)!!
|
||||
),
|
||||
Mapping(
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "list", "listFiles"),
|
||||
"isNotEmptyDirectory",
|
||||
expectedMatcher = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ARRAY_ASSERT_CLASSNAME, MethodNames.IS_NOT_EMPTY)
|
||||
.parameterCount(0)!!
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
val assertThatArgument = staticMethodCall.getArgOrNull(0) as? PsiMethodCallExpression ?: return
|
||||
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
|
||||
|
||||
for (mapping in MAPPINGS.filter { it.callMatcher.test(assertThatArgument) }) {
|
||||
if (mapping.expectBoolean && ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
|
||||
val expectedBooleanResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: continue
|
||||
val replacementMethod = if (expectedBooleanResult) mapping.replacementForTrue else mapping.replacementForFalse ?: return
|
||||
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
|
||||
MoveOutMethodCallExpressionQuickFix(desc, method)
|
||||
}
|
||||
} else if (mapping.expectNullNonNull != null) {
|
||||
val expectedNullNonNullResult = expectedCallExpression.getExpectedNullNonNullResult() ?: continue
|
||||
val replacementMethod = if (expectedNullNonNullResult xor mapping.expectNullNonNull) mapping.replacementForTrue else mapping.replacementForFalse ?: continue
|
||||
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
|
||||
MoveOutMethodCallExpressionQuickFix(desc, method, useNullNonNull = true)
|
||||
}
|
||||
} else if (mapping.expectedMatcher?.test(expectedCallExpression) == true) {
|
||||
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, mapping.replacementForTrue) { desc, method ->
|
||||
MoveOutMethodCallExpressionQuickFix(desc, method, replaceOnlyThisMethod = mapping.expectedMatcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Mapping(
|
||||
val callMatcher: CallMatcher,
|
||||
val replacementForTrue: String,
|
||||
val replacementForFalse: String? = null,
|
||||
val expectBoolean: Boolean = false,
|
||||
val expectNullNonNull: Boolean? = null,
|
||||
val expectedMatcher: CallMatcher? = null
|
||||
)
|
||||
}
|
||||
+39
-20
@@ -4,6 +4,7 @@ import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiMethodCallExpression
|
||||
import com.siyeh.ig.callMatcher.CallMatcher
|
||||
import de.platon42.intellij.plugins.cajon.*
|
||||
|
||||
class MoveOutMethodCallExpressionQuickFix(
|
||||
@@ -11,7 +12,8 @@ class MoveOutMethodCallExpressionQuickFix(
|
||||
private val replacementMethod: String,
|
||||
private val useNullNonNull: Boolean = false,
|
||||
private val noExpectedExpression: Boolean = false,
|
||||
private val keepExpectedAsSecondArgument: Boolean = false
|
||||
private val keepExpectedAsSecondArgument: Boolean = false,
|
||||
private val replaceOnlyThisMethod: CallMatcher? = null
|
||||
) :
|
||||
AbstractCommonQuickFix(description) {
|
||||
|
||||
@@ -29,29 +31,46 @@ class MoveOutMethodCallExpressionQuickFix(
|
||||
val assertExpression = assertThatMethodCall.firstArg as? PsiMethodCallExpression ?: return
|
||||
val assertExpressionArg = if (noExpectedExpression) null else assertExpression.getArgOrNull(0)?.copy()
|
||||
|
||||
if (keepExpectedAsSecondArgument) {
|
||||
assertExpressionArg ?: return
|
||||
val secondArg =
|
||||
if (useNullNonNull) JavaPsiFacade.getElementFactory(project).createExpressionFromText("null", null) else outmostCallExpression.getArgOrNull(0)?.copy() ?: return
|
||||
when {
|
||||
replaceOnlyThisMethod != null -> {
|
||||
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
|
||||
.filter(replaceOnlyThisMethod::test)
|
||||
.toList()
|
||||
|
||||
assertExpression.replace(assertExpression.qualifierExpression)
|
||||
assertExpression.replace(assertExpression.qualifierExpression)
|
||||
|
||||
val expectedExpression = createExpectedMethodCall(outmostCallExpression, replacementMethod, assertExpressionArg, secondArg)
|
||||
expectedExpression.replaceQualifierFromMethodCall(outmostCallExpression)
|
||||
outmostCallExpression.replace(expectedExpression)
|
||||
} else {
|
||||
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
|
||||
.filter { (if (useNullNonNull) it.getExpectedNullNonNullResult() else it.getExpectedBooleanResult()) != null }
|
||||
.toList()
|
||||
methodsToFix
|
||||
.forEach {
|
||||
val expectedExpression = createExpectedMethodCall(it, replacementMethod, *it.argumentList.expressions)
|
||||
expectedExpression.replaceQualifierFromMethodCall(it)
|
||||
it.replace(expectedExpression)
|
||||
}
|
||||
}
|
||||
keepExpectedAsSecondArgument -> {
|
||||
assertExpressionArg ?: return
|
||||
val secondArg =
|
||||
if (useNullNonNull) JavaPsiFacade.getElementFactory(project).createExpressionFromText("null", null) else outmostCallExpression.getArgOrNull(0)?.copy() ?: return
|
||||
|
||||
assertExpression.replace(assertExpression.qualifierExpression)
|
||||
assertExpression.replace(assertExpression.qualifierExpression)
|
||||
|
||||
methodsToFix
|
||||
.forEach {
|
||||
val expectedExpression = createExpectedMethodCall(it, replacementMethod, *listOfNotNull(assertExpressionArg).toTypedArray())
|
||||
expectedExpression.replaceQualifierFromMethodCall(it)
|
||||
it.replace(expectedExpression)
|
||||
}
|
||||
val expectedExpression = createExpectedMethodCall(outmostCallExpression, replacementMethod, assertExpressionArg, secondArg)
|
||||
expectedExpression.replaceQualifierFromMethodCall(outmostCallExpression)
|
||||
outmostCallExpression.replace(expectedExpression)
|
||||
}
|
||||
else -> {
|
||||
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
|
||||
.filter { (if (useNullNonNull) it.getExpectedNullNonNullResult() else it.getExpectedBooleanResult()) != null }
|
||||
.toList()
|
||||
|
||||
assertExpression.replace(assertExpression.qualifierExpression)
|
||||
|
||||
methodsToFix
|
||||
.forEach {
|
||||
val expectedExpression = createExpectedMethodCall(it, replacementMethod, *listOfNotNull(assertExpressionArg).toTypedArray())
|
||||
expectedExpression.replaceQualifierFromMethodCall(it)
|
||||
it.replace(expectedExpression)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,8 @@
|
||||
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="AssertThatFileExpression" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatFileExpressionInspection"/>
|
||||
|
||||
<localInspection groupPath="Java" shortName="JoinAssertThatStatements" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.JoinAssertThatStatementsInspection"/>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<body>
|
||||
Operates on assertions on objects of type File. Turns assertThat(file.someMethod(arg)).someAssertion() into assertThat(file).someMethod(arg).
|
||||
<!-- tooltip end -->
|
||||
<br>someMethod() can be canRead(), canWrite(), exists(), isAbsolute(), isDirectory(), isFile(),
|
||||
getName(), getParent(), getParentFile(), list() and listFiles().
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user