From 4e6d53b3dca0cf546f41a62e031f173339abd147 Mon Sep 17 00:00:00 2001 From: chrisly42 Date: Thu, 11 Apr 2019 23:55:35 +0200 Subject: [PATCH] Reduced minimal supported IDEA version from 2018.2 to 2017.2. Added AssertThatGuavaOptional inspection. Prepared next release. Bumped to Kotlin 1.3.30. --- README.md | 38 +++++++----- build.gradle | 18 ++---- .../plugins/cajon/AssertJClassNames.kt | 2 + .../intellij/plugins/cajon/MethodNames.kt | 1 + .../inspections/AbstractAssertJInspection.kt | 23 +++++-- .../AssertThatGuavaOptionalInspection.kt | 61 +++++++++++++++++++ .../AssertThatJava8OptionalInspection.kt | 22 +++---- .../JUnitAssertToAssertJInspection.kt | 9 +-- ...emoveExpectedOutmostMethodCallQuickFix.kt} | 2 +- .../ReplaceJUnitAssertMethodCallQuickFix.kt | 2 +- ...placeJUnitDeltaAssertMethodCallQuickFix.kt | 2 +- src/main/resources/META-INF/plugin.xml | 4 +- .../AssertThatGuavaOptional.html | 8 +++ .../AssertThatJava8Optional.html | 2 +- .../intellij/playground/Playground.java | 6 +- .../AssertThatGuavaOptionalInspectionTest.kt | 30 +++++++++ .../AssertThatGuavaOptionalAfter.java | 36 +++++++++++ .../AssertThatGuavaOptionalBefore.java | 36 +++++++++++ 18 files changed, 248 insertions(+), 54 deletions(-) create mode 100644 src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt rename src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/{ReplaceExpectedOutmostMethodCallQuickFix.kt => RemoveExpectedOutmostMethodCallQuickFix.kt} (90%) create mode 100644 src/main/resources/inspectionDescriptions/AssertThatGuavaOptional.html create mode 100644 src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspectionTest.kt create mode 100644 src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalAfter.java create mode 100644 src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalBefore.java diff --git a/README.md b/README.md index 757036d..fc2b627 100644 --- a/README.md +++ b/README.md @@ -51,22 +51,26 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the from: assertThat(object).isNotEqualTo(null); to: assertThat(object).isNotNull(); ``` + - AssertThatBooleanIsTrueOrFalse ``` from: assertThat(booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE); to: assertThat(booleanValue).isTrue()/isFalse(); ``` + - AssertThatStringIsEmpty ``` from: assertThat(charSequence/string).isEqualTo(""); from: assertThat(charSequence/string).hasSize(0); to: assertThat(charSequence/string).isEmpty(); ``` + - AssertThatEnumerableIsEmpty ``` from: assertThat(enumerable).hasSize(0); to: assertThat(enumerable).isEmpty(); ``` + - AssertThatSize ``` from: assertThat(array.length).isEqualTo(0); @@ -174,17 +178,7 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the assertArrayEquals(expectedDoubleOrFloatArray, actualDoubleOrFloatArray, delta); assertArrayEquals(message, expectedDoubleOrFloatArray, actualDoubleOrFloatArray, delta); ``` - -## Development notice - -Cajon is written in Kotlin 1.3. - -Cajon is probably the only plugin that uses JUnit 5 Jupiter for unit testing so far (or at least the only one that I'm aware of ;) ). -The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing and I 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 -- AssertThatNegatedBooleanExpression + - AssertThatGuavaOptional ``` from: assertThat(opt.isPresent()).isEqualTo(true); @@ -200,9 +194,6 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro from: assertThat(opt.get()).isEqualTo("foo"); to: assertThat(opt).contains("foo"); - from: assertThat(opt.get()).isSameAs("foo"); - to: assertThat(opt).containsSame("foo"); - from: assertThat(opt).isEqualTo(Optional.of("foo")); from: assertThat(opt).isEqualTo(Optional.fromNullable("foo")); to: assertThat(opt).contains("foo"); @@ -214,6 +205,19 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro to: assertThat(opt).isPresent(); ``` + AssertJ for Guava needs to be available in the classpath. + +## Development notice + +Cajon is written in Kotlin 1.3. + +Cajon is probably the only plugin that uses JUnit 5 Jupiter for unit testing so far (or at least the only one that I'm aware of ;) ). +The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing and I 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 +- AssertThatNegatedBooleanExpression +- AssertThatInstanceOf - Referencing string properties inside extracting() - Extraction with property names to lambda with Java 8 ``` @@ -224,6 +228,12 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro ## Changelog +#### V0.4 (11-Apr-19) +- Reduced minimal supported IDEA version from 2018.2 to 2017.2. +- New inspection AssertThatJava8Optional that operates on Java 8 Optional objects and tries to use contains(), containsSame(), isPresent(), and isNotPresent() instead. +- New inspection AssertThatGuavaOptional that operates on Guava Optional objects and tries to use contains(), isPresent(), and isAbsent() instead. +- Added support in AssertThatBinaryExpressionIsTrueOrFalse for is(Not)EqualTo(Boolean.TRUE/FALSE). + #### V0.3 (07-Apr-19) - New inspection AssertThatBinaryExpressionIsTrueOrFalse that will find and fix common binary expressions and equals() statements (more than 150 combinations) inside assertThat(). - Merged AssertThatObjectIsNull and AssertThatObjectIsNotNull to AssertThatObjectIsNullOrNotNull. diff --git a/build.gradle b/build.gradle index fb2df70..b7d887b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java' id 'org.jetbrains.intellij' version '0.4.3' - id 'org.jetbrains.kotlin.jvm' version '1.3.21' + id 'org.jetbrains.kotlin.jvm' version '1.3.30' } group 'de.platon42' @@ -41,9 +41,12 @@ intellij { patchPluginXml { changeNotes """ -

V0.4 (xx-Apr-19)

+

V0.4 (11-Apr-19)

V0.3 (07-Apr-19)

-

V0.2 (01-Apr-19)

- -

V0.1 (31-Mar-19)

- """ } diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/AssertJClassNames.kt b/src/main/java/de/platon42/intellij/plugins/cajon/AssertJClassNames.kt index 26b6b11..87ad08b 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/AssertJClassNames.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/AssertJClassNames.kt @@ -28,5 +28,7 @@ class AssertJClassNames { const val GUAVA_OPTIONAL_CLASSNAME = "com.google.common.base.Optional" @NonNls const val GUAVA_ASSERTIONS_CLASSNAME = "org.assertj.guava.api.Assertions" + @NonNls + const val GUAVA_OPTIONAL_ASSERT_CLASSNAME = "org.assertj.guava.api.OptionalAssert" } } \ No newline at end of file diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/MethodNames.kt b/src/main/java/de/platon42/intellij/plugins/cajon/MethodNames.kt index 6b365ed..d028092 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/MethodNames.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/MethodNames.kt @@ -72,6 +72,7 @@ class MethodNames { const val IS_PRESENT = "isPresent" @NonNls const val IS_NOT_PRESENT = "isNotPresent" + @NonNls const val IS_ABSENT = "isAbsent" } diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt index a464f15..5c9f9cf 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractAssertJInspection.kt @@ -14,18 +14,19 @@ import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_E import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_INTEGER_ASSERT_CLASSNAME import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ASSERTIONS_CLASSNAME import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.GUAVA_ASSERTIONS_CLASSNAME +import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.GUAVA_OPTIONAL_CLASSNAME import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.getArg import de.platon42.intellij.plugins.cajon.qualifierExpression import de.platon42.intellij.plugins.cajon.quickfixes.RemoveActualOutmostMethodCallQuickFix -import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceExpectedOutmostMethodCallQuickFix +import de.platon42.intellij.plugins.cajon.quickfixes.RemoveExpectedOutmostMethodCallQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() { companion object { const val SIMPLIFY_MESSAGE_TEMPLATE = "%s() can be simplified to %s()" - const val MORE_CONCISE_MESSAGE_TEMPLATE = "%s() would be more concise than %s" + const val MORE_CONCISE_MESSAGE_TEMPLATE = "%s() would be more concise than %s()" const val REPLACE_DESCRIPTION_TEMPLATE = "Replace %s() with %s()" @@ -73,7 +74,7 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() { .parameterTypes(CommonClassNames.JAVA_UTIL_OPTIONAL)!! val ASSERT_THAT_GUAVA_OPTIONAL = CallMatcher.staticCall(GUAVA_ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT) - .parameterTypes()!! + .parameterTypes(GUAVA_OPTIONAL_CLASSNAME)!! val IS_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO) .parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!! @@ -130,6 +131,18 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() { .parameterCount(1)!! val OPTIONAL_EMPTY = CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "empty") .parameterCount(0)!! + + val GUAVA_OPTIONAL_GET = CallMatcher.instanceCall(GUAVA_OPTIONAL_CLASSNAME, "get") + .parameterCount(0)!! + val GUAVA_OPTIONAL_IS_PRESENT = CallMatcher.instanceCall(GUAVA_OPTIONAL_CLASSNAME, "isPresent") + .parameterCount(0)!! + + val GUAVA_OPTIONAL_OF = CallMatcher.staticCall(GUAVA_OPTIONAL_CLASSNAME, "of") + .parameterCount(1)!! + val GUAVA_OPTIONAL_FROM_NULLABLE = CallMatcher.staticCall(GUAVA_OPTIONAL_CLASSNAME, "fromNullable") + .parameterCount(1)!! + val GUAVA_OPTIONAL_ABSENT = CallMatcher.staticCall(GUAVA_OPTIONAL_CLASSNAME, "absent") + .parameterCount(0)!! } override fun getGroupDisplayName(): String { @@ -184,12 +197,12 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() { val originalMethod = getOriginalMethodName(expectedCallExpression) ?: return val description = REPLACE_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod) val message = MORE_CONCISE_MESSAGE_TEMPLATE.format(replacementMethod, originalMethod) - val quickfix = ReplaceExpectedOutmostMethodCallQuickFix(description, replacementMethod) + val quickfix = RemoveExpectedOutmostMethodCallQuickFix(description, replacementMethod) holder.registerProblem(expression, message, quickfix) } protected fun calculateConstantParameterValue(expression: PsiMethodCallExpression, argIndex: Int): Any? { - if (argIndex >= expression.argumentList.expressionCount) return null + if (argIndex >= expression.argumentList.expressions.size) return null val valueExpression = expression.getArg(argIndex) val constantEvaluationHelper = JavaPsiFacade.getInstance(expression.project).constantEvaluationHelper val value = constantEvaluationHelper.computeConstantExpression(valueExpression) diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt new file mode 100644 index 0000000..cebdbc7 --- /dev/null +++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt @@ -0,0 +1,61 @@ +package de.platon42.intellij.plugins.cajon.inspections + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.* +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.util.PsiTreeUtil +import de.platon42.intellij.plugins.cajon.AssertJClassNames +import de.platon42.intellij.plugins.cajon.MethodNames +import de.platon42.intellij.plugins.cajon.firstArg +import de.platon42.intellij.plugins.cajon.map + +class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() { + + companion object { + private const val DISPLAY_NAME = "Asserting an Optional (Guava)" + } + + override fun getDisplayName() = DISPLAY_NAME + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { + return object : JavaElementVisitor() { + override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { + super.visitMethodCallExpression(expression) + JavaPsiFacade.getInstance(expression.project) + .findClass(AssertJClassNames.GUAVA_ASSERTIONS_CLASSNAME, GlobalSearchScope.allScope(expression.project)) ?: return + val assertThatGuava = ASSERT_THAT_GUAVA_OPTIONAL.test(expression) + if (!(ASSERT_THAT_ANY.test(expression) || assertThatGuava)) { + return + } + val statement = PsiTreeUtil.getParentOfType(expression, PsiStatement::class.java) ?: return + val expectedCallExpression = PsiTreeUtil.findChildOfType(statement, PsiMethodCallExpression::class.java) ?: return + + if (assertThatGuava) { + if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) { + val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return + if (GUAVA_OPTIONAL_OF.test(innerExpectedCall) || GUAVA_OPTIONAL_FROM_NULLABLE.test(innerExpectedCall)) { + registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) + } else if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) { + registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_ABSENT) + } + } else if (IS_NOT_EQUAL_TO_OBJECT.test(expectedCallExpression)) { + val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return + if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) { + registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_PRESENT) + } + } + } else { + val actualExpression = expression.firstArg as? PsiMethodCallExpression ?: return + + if (GUAVA_OPTIONAL_GET.test(actualExpression) && IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) { + registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) + } else if (GUAVA_OPTIONAL_IS_PRESENT.test(actualExpression)) { + val expectedPresence = getExpectedBooleanResult(expectedCallExpression) ?: return + val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_ABSENT) + registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, replacementMethod, noExpectedExpression = true) + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt index 4fe0c7a..2e28b17 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspection.kt @@ -44,21 +44,17 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() { } } else { val actualExpression = expression.firstArg as? PsiMethodCallExpression ?: return - val isGet = OPTIONAL_GET.test(actualExpression) - val isIsPresent = OPTIONAL_IS_PRESENT.test(actualExpression) - if (isGet || isIsPresent) { - if (isGet) { - if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) { - registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) - } else if (IS_SAME_AS_OBJECT.test(expectedCallExpression)) { - registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS_SAME) - } - } else { - val expectedPresence = getExpectedBooleanResult(expectedCallExpression) ?: return - val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_NOT_PRESENT) - registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, replacementMethod, noExpectedExpression = true) + if (OPTIONAL_GET.test(actualExpression)) { + if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) { + registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) + } else if (IS_SAME_AS_OBJECT.test(expectedCallExpression)) { + registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS_SAME) } + } else if (OPTIONAL_IS_PRESENT.test(actualExpression)) { + val expectedPresence = getExpectedBooleanResult(expectedCallExpression) ?: return + val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_NOT_PRESENT) + registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, replacementMethod, noExpectedExpression = true) } } } diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt index 248b17c..d9df369 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt @@ -1,12 +1,11 @@ package de.platon42.intellij.plugins.cajon.inspections import com.intellij.codeInspection.ProblemsHolder -import com.intellij.psi.CommonClassNames -import com.intellij.psi.JavaElementVisitor -import com.intellij.psi.PsiElementVisitor -import com.intellij.psi.PsiMethodCallExpression +import com.intellij.psi.* +import com.intellij.psi.search.GlobalSearchScope import com.siyeh.ig.callMatcher.CallMatcher import com.siyeh.ig.callMatcher.CallMatcher.anyOf +import de.platon42.intellij.plugins.cajon.AssertJClassNames import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceJUnitAssertMethodCallQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceJUnitDeltaAssertMethodCallQuickFix @@ -120,6 +119,8 @@ class JUnitAssertToAssertJInspection : AbstractJUnitAssertInspection() { if (!isJUnitAssertCall) { return // early exit } + JavaPsiFacade.getInstance(expression.project) + .findClass(AssertJClassNames.ASSERTIONS_CLASSNAME, GlobalSearchScope.allScope(expression.project)) ?: return for (mapping in MAPPINGS) { if (mapping.callMatcher.test(expression)) { if (mapping.hasDelta) { diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceExpectedOutmostMethodCallQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveExpectedOutmostMethodCallQuickFix.kt similarity index 90% rename from src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceExpectedOutmostMethodCallQuickFix.kt rename to src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveExpectedOutmostMethodCallQuickFix.kt index 84d5c96..e1043e7 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceExpectedOutmostMethodCallQuickFix.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/RemoveExpectedOutmostMethodCallQuickFix.kt @@ -9,7 +9,7 @@ import com.intellij.psi.util.PsiTreeUtil import de.platon42.intellij.plugins.cajon.firstArg import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall -class ReplaceExpectedOutmostMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) { +class RemoveExpectedOutmostMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val element = descriptor.startElement diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt index f5756d2..a85d8b2 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt @@ -19,7 +19,7 @@ class ReplaceJUnitAssertMethodCallQuickFix(description: String, private val noEx val element = descriptor.startElement val methodCallExpression = element as? PsiMethodCallExpression ?: return val args = methodCallExpression.argumentList - val count = args.expressionCount + val count = args.expressions.size val actualExpression = args.expressions[count - 1] ?: return val (expectedExpression, messageExpression) = if (noExpectedExpression) { val message = if (count > 1) args.expressions[0] else null diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitDeltaAssertMethodCallQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitDeltaAssertMethodCallQuickFix.kt index 244656c..b671d4a 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitDeltaAssertMethodCallQuickFix.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitDeltaAssertMethodCallQuickFix.kt @@ -17,7 +17,7 @@ class ReplaceJUnitDeltaAssertMethodCallQuickFix(description: String, private val val element = descriptor.startElement val methodCallExpression = element as? PsiMethodCallExpression ?: return val args = methodCallExpression.argumentList - val count = args.expressionCount + val count = args.expressions.size val actualExpression = args.expressions[count - 2] ?: return val messageExpression = if (count > 3) args.expressions[0] else null val expectedExpression = args.expressions[count - 3] ?: return diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index b40b14b..d7c90e8 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -10,7 +10,7 @@ ]]> - + @@ -36,6 +36,8 @@ + diff --git a/src/main/resources/inspectionDescriptions/AssertThatGuavaOptional.html b/src/main/resources/inspectionDescriptions/AssertThatGuavaOptional.html new file mode 100644 index 0000000..ac234b9 --- /dev/null +++ b/src/main/resources/inspectionDescriptions/AssertThatGuavaOptional.html @@ -0,0 +1,8 @@ + + +Looks at expected and actual expression being of Guava Optional type and whether the statement effectively tries to assert the +presence, absence or content and then replaces the statement by isPresent(), isAbsent(), or contains(). + +Requires AssertJ-Guava to be in classpath. + + \ No newline at end of file diff --git a/src/main/resources/inspectionDescriptions/AssertThatJava8Optional.html b/src/main/resources/inspectionDescriptions/AssertThatJava8Optional.html index 04c2aab..edcc1ac 100644 --- a/src/main/resources/inspectionDescriptions/AssertThatJava8Optional.html +++ b/src/main/resources/inspectionDescriptions/AssertThatJava8Optional.html @@ -1,7 +1,7 @@ Looks at expected and actual expression being of Java 8 Optional type and whether the statement effectively tries to assert the -presence, absence or content and then replaces the statement by isPresent(), isNotPresent(), contains() or containsSame(). +presence, absence or content and then replaces the statement by isPresent(), isNotPresent(), contains(), or containsSame(). \ No newline at end of file diff --git a/src/test/java/de/platon42/intellij/playground/Playground.java b/src/test/java/de/platon42/intellij/playground/Playground.java index 98c1c03..9126072 100644 --- a/src/test/java/de/platon42/intellij/playground/Playground.java +++ b/src/test/java/de/platon42/intellij/playground/Playground.java @@ -153,9 +153,10 @@ public class Playground { assertThat(opt).isEqualTo(Optional.empty()); assertThat(opt).isNotEqualTo(Optional.empty()); + assertThat(opt).isPresent(); } - private void guavaOptional() { + private void assertThatGuavaOptional() { com.google.common.base.Optional opt = com.google.common.base.Optional.absent(); assertThat(opt.isPresent()).isEqualTo(true); @@ -172,6 +173,8 @@ public class Playground { assertThat(opt.get()).isEqualTo("foo"); assertThat(opt.get()).isSameAs("foo"); + assertThat(opt.get()).isNotEqualTo("foo"); + assertThat(opt.get()).isNotSameAs("foo"); assertThat(opt).isEqualTo(com.google.common.base.Optional.of("foo")); assertThat(opt).isEqualTo(com.google.common.base.Optional.fromNullable("foo")); @@ -180,6 +183,7 @@ public class Playground { assertThat(opt).isEqualTo(com.google.common.base.Optional.absent()); assertThat(opt).isNotEqualTo(com.google.common.base.Optional.absent()); + assertThat(opt).isAbsent(); } private void junitAssertions() { diff --git a/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspectionTest.kt b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspectionTest.kt new file mode 100644 index 0000000..57756e5 --- /dev/null +++ b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspectionTest.kt @@ -0,0 +1,30 @@ +package de.platon42.intellij.plugins.cajon.inspections + +import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture +import de.platon42.intellij.jupiter.AddLocalJarToModule +import de.platon42.intellij.jupiter.MyFixture +import de.platon42.intellij.jupiter.TestDataSubPath +import de.platon42.intellij.plugins.cajon.AbstractCajonTest +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +@AddLocalJarToModule(com.google.common.base.Optional::class, org.assertj.guava.api.Assertions::class, Assertions::class) +internal class AssertThatGuavaOptionalInspectionTest : AbstractCajonTest() { + + @Test + @TestDataSubPath("inspections/AssertThatGuavaOptional") + internal fun assertThat_get_or_isPresent_for_Guava_Optional_can_be_simplified(@MyFixture myFixture: JavaCodeInsightTestFixture) { + runTest { + myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java) + myFixture.configureByFile("AssertThatGuavaOptionalBefore.java") + executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isPresent()"), 2) + executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isPresent()"), 3) + executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isAbsent()"), 3) + executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isAbsent()"), 2) + executeQuickFixes(myFixture, Regex.fromLiteral("Replace isTrue() with isPresent()"), 1) + executeQuickFixes(myFixture, Regex.fromLiteral("Replace isFalse() with isAbsent()"), 1) + executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with contains()"), 3) + myFixture.checkResultByFile("AssertThatGuavaOptionalAfter.java") + } + } +} \ No newline at end of file diff --git a/src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalAfter.java b/src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalAfter.java new file mode 100644 index 0000000..3a169b8 --- /dev/null +++ b/src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalAfter.java @@ -0,0 +1,36 @@ +import com.google.common.base.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.assertThat; + +public class AssertThatGuavaOptional { + + private void assertThatGuavaOptional() { + Optional opt = Optional.absent(); + + assertThat(opt).isPresent(); + assertThat(opt).isPresent(); + assertThat(opt).isPresent(); + assertThat(opt).isPresent(); + assertThat(opt).isPresent(); + + assertThat(opt).isAbsent(); + assertThat(opt).isAbsent(); + assertThat(opt).isAbsent(); + assertThat(opt).isAbsent(); + assertThat(opt).isAbsent(); + + assertThat(opt).contains("foo"); + assertThat(opt.get()).isSameAs("foo"); + assertThat(opt.get()).isNotEqualTo("foo"); + assertThat(opt.get()).isNotSameAs("foo"); + + assertThat(opt).contains("foo"); + assertThat(opt).contains("foo"); + assertThat(opt).isNotEqualTo(Optional.of("foo")); + assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); + + assertThat(opt).isAbsent(); + assertThat(opt).isPresent(); + } +} diff --git a/src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalBefore.java b/src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalBefore.java new file mode 100644 index 0000000..02477f9 --- /dev/null +++ b/src/test/resources/inspections/AssertThatGuavaOptional/AssertThatGuavaOptionalBefore.java @@ -0,0 +1,36 @@ +import com.google.common.base.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.assertThat; + +public class AssertThatGuavaOptional { + + private void assertThatGuavaOptional() { + Optional opt = Optional.absent(); + + assertThat(opt.isPresent()).isEqualTo(true); + assertThat(opt.isPresent()).isEqualTo(Boolean.TRUE); + assertThat(opt.isPresent()).isNotEqualTo(false); + assertThat(opt.isPresent()).isNotEqualTo(Boolean.FALSE); + assertThat(opt.isPresent()).isTrue(); + + assertThat(opt.isPresent()).isEqualTo(false); + assertThat(opt.isPresent()).isEqualTo(Boolean.FALSE); + assertThat(opt.isPresent()).isNotEqualTo(true); + assertThat(opt.isPresent()).isNotEqualTo(Boolean.TRUE); + assertThat(opt.isPresent()).isFalse(); + + assertThat(opt.get()).isEqualTo("foo"); + assertThat(opt.get()).isSameAs("foo"); + assertThat(opt.get()).isNotEqualTo("foo"); + assertThat(opt.get()).isNotSameAs("foo"); + + assertThat(opt).isEqualTo(Optional.of("foo")); + assertThat(opt).isEqualTo(Optional.fromNullable("foo")); + assertThat(opt).isNotEqualTo(Optional.of("foo")); + assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); + + assertThat(opt).isEqualTo(Optional.absent()); + assertThat(opt).isNotEqualTo(Optional.absent()); + } +}