Implemented AssertThatStringIsEmpty.
This commit is contained in:
parent
8051511524
commit
5fa61a3004
26
README.md
26
README.md
@ -4,12 +4,25 @@ Cajon is an IntelliJ Plugin for shortening and optimizing AssertJ assertions.
|
|||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
|
|
||||||
First, code is easier to read, when is concise and reflects the intention clearly.
|
First, code is easier to read, when it is concise and reflects the intention clearly.
|
||||||
AssertJ has plenty of different convenience methods that make describing the various intentions.
|
AssertJ has plenty of different convenience methods that describing various intentions precisely.
|
||||||
Why write longer, more complex code that can be expressed in brevity?
|
Why write longer, more complex code that can be expressed in brevity?
|
||||||
|
|
||||||
Second, AssertJ is able to output more meaningful descriptions when an assertion fails.
|
Second, AssertJ is able to output more meaningful descriptions when an assertion fails.
|
||||||
This makes finding bugs and fixing failed tests easier.
|
This makes finding bugs and fixing failed tests more efficient.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
> assertThat(collection.size()).isEqualTo(5);
|
||||||
|
|
||||||
|
If the collection has more or less than 5 elements, the assertion will fail, but will not
|
||||||
|
tell you about the contents, making it hard to guess what went wrong.
|
||||||
|
|
||||||
|
Instead, if you wrote the same assertion the following way:
|
||||||
|
|
||||||
|
> assertThat(collection).hasSize(5);
|
||||||
|
|
||||||
|
Then AssertJ would tell you the contents of the collection on failure.
|
||||||
|
|
||||||
## Implemented
|
## Implemented
|
||||||
|
|
||||||
@ -22,11 +35,11 @@ This makes finding bugs and fixing failed tests easier.
|
|||||||
- AssertThatBooleanIsTrueOrFalse
|
- AssertThatBooleanIsTrueOrFalse
|
||||||
> from: assertThat(booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE);
|
> from: assertThat(booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE);
|
||||||
> to: assertThat(booleanValue).isTrue()/isFalse();
|
> to: assertThat(booleanValue).isTrue()/isFalse();
|
||||||
|
|
||||||
## TODO
|
|
||||||
- AssertThatStringIsEmpty
|
- AssertThatStringIsEmpty
|
||||||
> from: assertThat(string).isEqualTo("")
|
> from: assertThat(string).isEqualTo("")
|
||||||
> to: assertThat(string).isEmpty();
|
> to: assertThat(string).isEmpty();
|
||||||
|
|
||||||
|
## TODO
|
||||||
- AssertThatArrayHasLiteralSize
|
- AssertThatArrayHasLiteralSize
|
||||||
> from: assertThat(array.length).isEqualTo(literal); literal > 0
|
> from: assertThat(array.length).isEqualTo(literal); literal > 0
|
||||||
> to: assertThat(array).hasSize(literal);
|
> to: assertThat(array).hasSize(literal);
|
||||||
@ -62,3 +75,6 @@ This makes finding bugs and fixing failed tests easier.
|
|||||||
> from: assertThat(iterable.size()).isLessThan(1);
|
> from: assertThat(iterable.size()).isLessThan(1);
|
||||||
> from: assertThat(iterable).hasSize(0);
|
> from: assertThat(iterable).hasSize(0);
|
||||||
> to: assertThat(iterable).isEmpty();
|
> to: assertThat(iterable).isEmpty();
|
||||||
|
- JUnit Assertion to AssertJ
|
||||||
|
|
||||||
|
- AssertThatGuavaOptionalContains
|
@ -9,6 +9,7 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
|
|||||||
companion object {
|
companion object {
|
||||||
const val ABSTRACT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractAssert"
|
const val ABSTRACT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractAssert"
|
||||||
const val ABSTRACT_BOOLEAN_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractBooleanAssert"
|
const val ABSTRACT_BOOLEAN_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractBooleanAssert"
|
||||||
|
const val ABSTRACT_STRING_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractStringAssert"
|
||||||
const val IS_EQUAL_TO = "isEqualTo"
|
const val IS_EQUAL_TO = "isEqualTo"
|
||||||
const val IS_NOT_EQUAL_TO = "isNotEqualTo"
|
const val IS_NOT_EQUAL_TO = "isNotEqualTo"
|
||||||
|
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package de.platon42.intellij.plugins.cajon.inspections
|
package de.platon42.intellij.plugins.cajon.inspections
|
||||||
|
|
||||||
import com.intellij.codeInspection.LocalQuickFix
|
|
||||||
import com.intellij.codeInspection.ProblemDescriptor
|
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.util.TypeConversionUtil
|
import com.intellij.psi.util.TypeConversionUtil
|
||||||
|
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
|
|
||||||
class AssertThatBooleanIsTrueOrFalseInspection : AbstractAssertJInspection() {
|
class AssertThatBooleanIsTrueOrFalseInspection : AbstractAssertJInspection() {
|
||||||
@ -63,34 +61,17 @@ class AssertThatBooleanIsTrueOrFalseInspection : AbstractAssertJInspection() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val expectedResult = result as? Boolean ?: return
|
val expectedResult = result as? Boolean ?: return
|
||||||
|
val description =
|
||||||
|
if (flippedBooleanTest) QUICKFIX_DESCRIPTION_NOT_IS_TRUE else QUICKFIX_DESCRIPTION_IS_TRUE
|
||||||
|
val replacementMethod = if (expectedResult xor flippedBooleanTest) "isTrue()" else "isFalse()"
|
||||||
holder.registerProblem(
|
holder.registerProblem(
|
||||||
expression,
|
expression,
|
||||||
INSPECTION_MESSAGE,
|
INSPECTION_MESSAGE,
|
||||||
ProblemHighlightType.INFORMATION,
|
ProblemHighlightType.INFORMATION,
|
||||||
null as TextRange?,
|
null as TextRange?,
|
||||||
ReplaceWithIsNullQuickFix(
|
ReplaceSimpleMethodCallQuickFix(description, replacementMethod)
|
||||||
expectedResult xor flippedBooleanTest,
|
|
||||||
if (flippedBooleanTest) QUICKFIX_DESCRIPTION_NOT_IS_TRUE else QUICKFIX_DESCRIPTION_IS_TRUE
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class ReplaceWithIsNullQuickFix(val expectedResult: Boolean, val quickfixName: String) : LocalQuickFix {
|
|
||||||
override fun getFamilyName() = quickfixName
|
|
||||||
|
|
||||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
|
||||||
val element = descriptor.startElement
|
|
||||||
val factory = JavaPsiFacade.getElementFactory(element.project)
|
|
||||||
val methodCallExpression = element as? PsiMethodCallExpression ?: return
|
|
||||||
val oldQualifier = methodCallExpression.methodExpression.qualifierExpression ?: return
|
|
||||||
val methodName = if (expectedResult) "isTrue()" else "isFalse()"
|
|
||||||
val isNullExpression =
|
|
||||||
factory.createExpressionFromText("a.$methodName", null) as PsiMethodCallExpression
|
|
||||||
isNullExpression.methodExpression.qualifierExpression!!.replace(oldQualifier)
|
|
||||||
element.replace(isNullExpression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,12 +1,13 @@
|
|||||||
package de.platon42.intellij.plugins.cajon.inspections
|
package de.platon42.intellij.plugins.cajon.inspections
|
||||||
|
|
||||||
import com.intellij.codeInspection.LocalQuickFix
|
|
||||||
import com.intellij.codeInspection.ProblemDescriptor
|
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.JavaElementVisitor
|
||||||
|
import com.intellij.psi.PsiElementVisitor
|
||||||
|
import com.intellij.psi.PsiMethodCallExpression
|
||||||
|
import com.intellij.psi.PsiType
|
||||||
|
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
|
|
||||||
class AssertThatObjectIsNotNullInspection : AbstractAssertJInspection() {
|
class AssertThatObjectIsNotNullInspection : AbstractAssertJInspection() {
|
||||||
@ -38,25 +39,10 @@ class AssertThatObjectIsNotNullInspection : AbstractAssertJInspection() {
|
|||||||
INSPECTION_MESSAGE,
|
INSPECTION_MESSAGE,
|
||||||
ProblemHighlightType.INFORMATION,
|
ProblemHighlightType.INFORMATION,
|
||||||
null as TextRange?,
|
null as TextRange?,
|
||||||
ReplaceWithIsNotNullQuickFix()
|
ReplaceSimpleMethodCallQuickFix(QUICKFIX_DESCRIPTION, "isNotNull()")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ReplaceWithIsNotNullQuickFix : LocalQuickFix {
|
|
||||||
override fun getFamilyName() = QUICKFIX_DESCRIPTION
|
|
||||||
|
|
||||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
|
||||||
val element = descriptor.startElement
|
|
||||||
val factory = JavaPsiFacade.getElementFactory(element.project)
|
|
||||||
val methodCallExpression = element as? PsiMethodCallExpression ?: return
|
|
||||||
val oldQualifier = methodCallExpression.methodExpression.qualifierExpression ?: return
|
|
||||||
val isNotNullExpression =
|
|
||||||
factory.createExpressionFromText("a.isNotNull()", null) as PsiMethodCallExpression
|
|
||||||
isNotNullExpression.methodExpression.qualifierExpression!!.replace(oldQualifier)
|
|
||||||
element.replace(isNotNullExpression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,12 +1,13 @@
|
|||||||
package de.platon42.intellij.plugins.cajon.inspections
|
package de.platon42.intellij.plugins.cajon.inspections
|
||||||
|
|
||||||
import com.intellij.codeInspection.LocalQuickFix
|
|
||||||
import com.intellij.codeInspection.ProblemDescriptor
|
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.JavaElementVisitor
|
||||||
|
import com.intellij.psi.PsiElementVisitor
|
||||||
|
import com.intellij.psi.PsiMethodCallExpression
|
||||||
|
import com.intellij.psi.PsiType
|
||||||
|
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
|
|
||||||
class AssertThatObjectIsNullInspection : AbstractAssertJInspection() {
|
class AssertThatObjectIsNullInspection : AbstractAssertJInspection() {
|
||||||
@ -38,25 +39,10 @@ class AssertThatObjectIsNullInspection : AbstractAssertJInspection() {
|
|||||||
INSPECTION_MESSAGE,
|
INSPECTION_MESSAGE,
|
||||||
ProblemHighlightType.INFORMATION,
|
ProblemHighlightType.INFORMATION,
|
||||||
null as TextRange?,
|
null as TextRange?,
|
||||||
ReplaceWithIsNullQuickFix()
|
ReplaceSimpleMethodCallQuickFix(QUICKFIX_DESCRIPTION, "isNull()")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ReplaceWithIsNullQuickFix : LocalQuickFix {
|
|
||||||
override fun getFamilyName() = QUICKFIX_DESCRIPTION
|
|
||||||
|
|
||||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
|
||||||
val element = descriptor.startElement
|
|
||||||
val factory = JavaPsiFacade.getElementFactory(element.project)
|
|
||||||
val methodCallExpression = element as? PsiMethodCallExpression ?: return
|
|
||||||
val oldQualifier = methodCallExpression.methodExpression.qualifierExpression ?: return
|
|
||||||
val isNullExpression =
|
|
||||||
factory.createExpressionFromText("a.isNull()", null) as PsiMethodCallExpression
|
|
||||||
isNullExpression.methodExpression.qualifierExpression!!.replace(oldQualifier)
|
|
||||||
element.replace(isNullExpression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package de.platon42.intellij.plugins.cajon.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.JavaElementVisitor
|
||||||
|
import com.intellij.psi.PsiElementVisitor
|
||||||
|
import com.intellij.psi.PsiLiteralExpression
|
||||||
|
import com.intellij.psi.PsiMethodCallExpression
|
||||||
|
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix
|
||||||
|
import org.jetbrains.annotations.NonNls
|
||||||
|
|
||||||
|
class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@NonNls
|
||||||
|
private val DISPLAY_NAME = "Asserting an empty string"
|
||||||
|
|
||||||
|
@NonNls
|
||||||
|
private val INSPECTION_MESSAGE = "isEqualTo(\"\") can be simplified to isEmpty()"
|
||||||
|
|
||||||
|
@NonNls
|
||||||
|
private val QUICKFIX_DESCRIPTION = "Replace isEqualTo(\"\") with isEmpty()"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDisplayName() = DISPLAY_NAME
|
||||||
|
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||||
|
return object : JavaElementVisitor() {
|
||||||
|
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
|
||||||
|
super.visitMethodCallExpression(expression)
|
||||||
|
if (!IS_EQUAL_TO_OBJECT.test(expression)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val psiExpression = expression.argumentList.expressions[0] as? PsiLiteralExpression ?: return
|
||||||
|
|
||||||
|
if (psiExpression.value == "") {
|
||||||
|
holder.registerProblem(
|
||||||
|
expression,
|
||||||
|
INSPECTION_MESSAGE,
|
||||||
|
ProblemHighlightType.INFORMATION,
|
||||||
|
null as TextRange?,
|
||||||
|
ReplaceSimpleMethodCallQuickFix(QUICKFIX_DESCRIPTION, "isEmpty()")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package de.platon42.intellij.plugins.cajon.quickfixes
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.LocalQuickFix
|
||||||
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.JavaPsiFacade
|
||||||
|
import com.intellij.psi.PsiMethodCallExpression
|
||||||
|
|
||||||
|
class ReplaceSimpleMethodCallQuickFix(private val description: String, private val replacementMethod: String) :
|
||||||
|
LocalQuickFix {
|
||||||
|
override fun getFamilyName() = description
|
||||||
|
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
val element = descriptor.startElement
|
||||||
|
val factory = JavaPsiFacade.getElementFactory(element.project)
|
||||||
|
val methodCallExpression = element as? PsiMethodCallExpression ?: return
|
||||||
|
val oldQualifier = methodCallExpression.methodExpression.qualifierExpression ?: return
|
||||||
|
val isEmptyExpression =
|
||||||
|
factory.createExpressionFromText("a.$replacementMethod", null) as PsiMethodCallExpression
|
||||||
|
isEmptyExpression.methodExpression.qualifierExpression!!.replace(oldQualifier)
|
||||||
|
element.replace(isEmptyExpression)
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,8 @@
|
|||||||
<localInspection groupPath="Java" shortName="AssertThatBooleanIsTrueOrFalse" enabledByDefault="true"
|
<localInspection groupPath="Java" shortName="AssertThatBooleanIsTrueOrFalse" enabledByDefault="true"
|
||||||
level="WARNING"
|
level="WARNING"
|
||||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBooleanIsTrueOrFalseInspection"/>
|
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBooleanIsTrueOrFalseInspection"/>
|
||||||
|
<localInspection groupPath="Java" shortName="AssertThatStringIsEmpty" enabledByDefault="true" level="WARNING"
|
||||||
|
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatStringIsEmptyInspection"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<actions>
|
<actions>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package de.platon42.intellij.playground;
|
package de.platon42.intellij.playground;
|
||||||
|
|
||||||
|
import org.assertj.core.api.AbstractStringAssert;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -48,4 +50,10 @@ public class Playground {
|
|||||||
assertThat("").isEqualTo(Boolean.TRUE);
|
assertThat("").isEqualTo(Boolean.TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void stringIsEmpty() {
|
||||||
|
String foo = "bar";
|
||||||
|
AbstractStringAssert<?> abstractStringAssert = assertThat(foo);
|
||||||
|
abstractStringAssert.isEqualTo("");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 AssertThatStringIsEmptyInspectionTest : AbstractCajonTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestDataSubPath("inspections/StringIsEmpty")
|
||||||
|
internal fun assertThat_with_isEqualTo_emptyString_can_use_isEmpty(@MyFixture myFixture: JavaCodeInsightTestFixture) {
|
||||||
|
runTest {
|
||||||
|
myFixture.enableInspections(AssertThatStringIsEmptyInspection::class.java)
|
||||||
|
myFixture.configureByFile("StringIsEmptyBefore.java")
|
||||||
|
executeQuickFixes(myFixture, Regex("Replace is.*"), 1)
|
||||||
|
myFixture.checkResultByFile("StringIsEmptyAfter.java")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class StringIsEmpty {
|
||||||
|
|
||||||
|
private void stringIsEmpty() {
|
||||||
|
String string = "string";
|
||||||
|
|
||||||
|
assertThat(string).isEqualTo("foo");
|
||||||
|
assertThat(string).isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class StringIsEmpty {
|
||||||
|
|
||||||
|
private void stringIsEmpty() {
|
||||||
|
String string = "string";
|
||||||
|
|
||||||
|
assertThat(string).isEqualTo("foo");
|
||||||
|
assertThat(string).isEqualTo("");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user