diff --git a/README.md b/README.md
index 7064ab0..10f3391 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ For example:
assertThat(collection.size()).isEqualTo(5);
```
-If the collection has more or less than 5 elements, the assertion will fail, but will not
+If the collection has more or less than five 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:
@@ -26,12 +26,24 @@ 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.
+Then AssertJ would tell you the _actual contents_ of the collection on failure.
## Conversion of JUnit assertions to AssertJ
The plugin also supports the conversion of the most common JUnit 4 assertions to AssertJ.
+## Lookup and refactoring of string-based extracting()
+
+AssertJ allows [extracting POJO fields/properties on iterables/arrays](http://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#extracted-properties-assertion).
+
+Using strings is not safe for refactoring (and before Java 8 Lambdas were available,
+creating extractor functions just for testing purpose was a bit too tedious).
+
+This plugin adds support for referencing these fields (so you can ctrl(/cmd)-click on the
+string to go to the definition) and also allows safe refactoring on the
+fields (refactoring a getter method without a corresponding field will not work
+correctly right now).
+
## Usage
The plugin will report inspections in your opened editor file as warnings.
@@ -103,7 +115,6 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
from: assertThat(array.length).isGreaterThanOrEqualTo(expression);
to: assertThat(array).hasSizeGreaterThanOrEqualTo(expression);
```
-
and analogously for collections...
- AssertThatBinaryExpressionIsTrueOrFalse
@@ -120,7 +131,7 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
from: assertThat(null == objActual).isFalse();
to: assertThat(objActual).isNotNull();
```
- and many, many more combinations (more than 150).
+ ...and many, many more combinations (more than 150).
- AssertThatJava8Optional
```
@@ -207,6 +218,23 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
AssertJ for Guava needs to be available in the classpath.
+### Implemented referencing
+
+ ```
+ .extracting("field")
+ .extracting("outerfield.fieldInsideObjectTypeOfOuterfield.andSoOn")
+ .extracting("property") // where the class has a getProperty() (or isProperty() for boolean) method
+ .extracting("bareMethod") // supported with AssertJ 13.12.0
+ .extracting(Extractors.byName("fieldOrPropertyOrBareMethod")
+ .extracting(Extractors.byName("fieldOrPropertyOrBareMethod.orAPathLikeAbove")
+ .extracting(Extractors.resultOf("bareMethod")
+ .extractingResultOf("bareMethod")
+ .flatExtracting("fieldOrPropertyOrBareMethod.orAPathLikeAbove")
+ .flatExtracting(Extractors.byName("fieldOrPropertyOrBareMethod.orAPathLikeAbove")
+ .flatExtracting(Extractors.resultOf("bareMethod")
+ ```
+ Works on both POJOs and ```Iterable```s/```Array```s.
+
## Development notice
Cajon is written in Kotlin 1.3.
@@ -218,7 +246,20 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro
## TODO
- AssertThatNegatedBooleanExpression
- AssertThatInstanceOf
-- Referencing string properties inside extracting()
+- AssertThatStringOps
+ ```
+ from: assertThat(string.contains(foobar)).isTrue();
+ to: assertThat(string).contains(foobar);
+ from: assertThat(string.startsWith(foobar)).isTrue();
+ to: assertThat(string).startsWith(foobar);
+ from: assertThat(string.endsWith(foobar)).isTrue();
+ to: assertThat(string).endsWith(foobar);
+ from: assertThat(string.equalsIgnoreCase(foobar)).isTrue();
+ to: assertThat(string).isEqualToIgnoringCase(foobar);
+ ```
+ Analogously with ```isFalse()```.
+
+- AssumeInsteadOfReturn
- Extraction with property names to lambda with Java 8
```
from: assertThat(object).extracting("propOne", "propNoGetter", "propTwo.innerProp")...
@@ -229,19 +270,23 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro
## Changelog
#### V0.5 (13-Apr-19)
-- Fixed incompatibility with IDEA versions < 2018.2 (affected AssertThatSizeInspection).
+- Fixed incompatibility with IDEA versions < 2018.2 (affected AssertThatSizeInspection). Minimal version is now 2017.3.
- Fixed missing Guava imports (if not already present) for AssertThatGuavaInspection. This was a major PITA to get right.
+- Added support for referencing and refactoring inside ```.extracting()``` methods with fields, properties and methods (though
+ getter renaming does not work that perfect, but I'm giving up for now as the IntelliJ SDK docs are seriously lacking).
+- Fixed an exception in batch mode if the description string was the same but for different fixes.
+ Now descriptions are different for quick fixes triggered by AssertThatJava8OptionalInspection and AssertThatGuavaOptionalInspection.
#### 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).
+- 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().
+- 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.
-- Support for hasSizeLessThan(), hasSizeLessThanOrEqualTo(), hasSizeGreaterThanOrEqualTo(), and hasSizeGreaterThan() for AssertThatSizeInspection (with AssertJ >=13.2.0).
+- Support for ```hasSizeLessThan()```, ```hasSizeLessThanOrEqualTo()```, ```hasSizeGreaterThanOrEqualTo()```, and ```hasSizeGreaterThan()``` for AssertThatSizeInspection (with AssertJ >=13.2.0).
- Really fixed highlighting for JUnit conversion. Sorry.
#### V0.2 (01-Apr-19)
diff --git a/build.gradle b/build.gradle
index 559d802..fb0cfa0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -22,9 +22,8 @@ dependencies {
testCompile "org.assertj:assertj-guava:3.2.1"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
- testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.4.0'
testImplementation "org.jetbrains.kotlin:kotlin-test"
- testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
+// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
}
compileKotlin {
@@ -41,10 +40,14 @@ intellij {
patchPluginXml {
changeNotes """
-
V0.5 (13-Apr-19)
+ V0.5 (18-Apr-19)
- - Fixed incompatibility with IDEA versions < 2018.2 (affected AssertThatSizeInspection).
+
- Fixed incompatibility with IDEA versions < 2018.2 (affected AssertThatSizeInspection). Minimal version is now 2017.3.
- Fixed missing Guava imports (if not already present) for AssertThatGuavaInspection. This was a major PITA to get right.
+
- Added support for referencing and refactoring inside .extracting() methods with fields, properties and methods (though
+ getter renaming does not work that perfect, but I'm giving up for now as the IntelliJ SDK docs are seriously lacking).
+
- Fixed an exception in batch mode if the description string was the same but for different fixes.
+ Now descriptions are different for quick fixes triggered by AssertThatJava8OptionalInspection and AssertThatGuavaOptionalInspection.
V0.4 (11-Apr-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 33ffd29..0c644b6 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/AssertJClassNames.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/AssertJClassNames.kt
@@ -25,6 +25,8 @@ class AssertJClassNames {
const val ABSTRACT_ITERABLE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractIterableAssert"
@NonNls
const val ABSTRACT_ENUMERABLE_ASSERT_CLASSNAME = "org.assertj.core.api.EnumerableAssert"
+ @NonNls
+ const val EXTRACTORS_CLASSNAME = "org.assertj.core.extractor.Extractors"
@NonNls
const val GUAVA_OPTIONAL_CLASSNAME = "com.google.common.base.Optional"
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt b/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt
index 2f69022..66ef68e 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/Helper.kt
@@ -4,7 +4,9 @@ import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiMethodCallExpression
+import com.siyeh.ig.callMatcher.CallMatcher
+val CORE_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!!
fun createAssertThat(context: PsiElement, actualExpression: PsiExpression): PsiMethodCallExpression {
return createAssertThat(context, AssertJClassNames.ASSERTIONS_CLASSNAME, actualExpression)
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 98086bb..cc77c4c 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
@@ -28,6 +28,8 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
const val MORE_CONCISE_MESSAGE_TEMPLATE = "%s() would be more concise than %s()"
const val REPLACE_DESCRIPTION_TEMPLATE = "Replace %s() with %s()"
+ const val REMOVE_EXPECTED_OUTMOST_DESCRIPTION_TEMPLATE = "Unwrap expected expression and replace %s() with %s()"
+ const val REMOVE_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE = "Unwrap actual expression and replace %s() with %s()"
val TOKEN_TO_ASSERTJ_FOR_PRIMITIVE_MAP = mapOf(
JavaTokenType.EQEQ to MethodNames.IS_EQUAL_TO,
@@ -179,14 +181,45 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
oldExpectedCallExpression: PsiMethodCallExpression,
replacementMethod: String,
quickFixSupplier: (String, String) -> LocalQuickFix
+ ) {
+ registerConciseMethod(REPLACE_DESCRIPTION_TEMPLATE, oldExpectedCallExpression, replacementMethod, quickFixSupplier, holder, expression)
+ }
+
+ private fun registerConciseMethod(
+ descriptionTemplate: String,
+ oldExpectedCallExpression: PsiMethodCallExpression,
+ replacementMethod: String,
+ quickFixSupplier: (String, String) -> LocalQuickFix,
+ holder: ProblemsHolder,
+ expression: PsiMethodCallExpression
) {
val originalMethod = getOriginalMethodName(oldExpectedCallExpression) ?: return
- val description = REPLACE_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod)
+ val description = descriptionTemplate.format(originalMethod, replacementMethod)
val message = MORE_CONCISE_MESSAGE_TEMPLATE.format(replacementMethod, originalMethod)
val quickfix = quickFixSupplier(description, replacementMethod)
holder.registerProblem(expression, message, quickfix)
}
+ protected fun registerRemoveExpectedOutmostMethod(
+ holder: ProblemsHolder,
+ expression: PsiMethodCallExpression,
+ oldExpectedCallExpression: PsiMethodCallExpression,
+ replacementMethod: String,
+ quickFixSupplier: (String, String) -> LocalQuickFix
+ ) {
+ registerConciseMethod(REMOVE_EXPECTED_OUTMOST_DESCRIPTION_TEMPLATE, oldExpectedCallExpression, replacementMethod, quickFixSupplier, holder, expression)
+ }
+
+ protected fun registerRemoveActualOutmostMethod(
+ holder: ProblemsHolder,
+ expression: PsiMethodCallExpression,
+ oldExpectedCallExpression: PsiMethodCallExpression,
+ replacementMethod: String,
+ quickFixSupplier: (String, String) -> LocalQuickFix
+ ) {
+ registerConciseMethod(REMOVE_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE, oldExpectedCallExpression, replacementMethod, quickFixSupplier, holder, expression)
+ }
+
protected fun calculateConstantParameterValue(expression: PsiMethodCallExpression, argIndex: Int): Any? {
if (argIndex >= expression.argumentList.expressions.size) return null
val valueExpression = expression.getArg(argIndex)
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
index b87263b..71308ef 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspection.kt
@@ -6,6 +6,7 @@ import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.search.GlobalSearchScope
+import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.*
@@ -34,8 +35,8 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
if (assertThatGuava) {
if (isEqualTo) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
- if (GUAVA_OPTIONAL_OF.test(innerExpectedCall) || GUAVA_OPTIONAL_FROM_NULLABLE.test(innerExpectedCall)) {
- registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::RemoveExpectedOutmostMethodCallQuickFix)
+ if (CallMatcher.anyOf(GUAVA_OPTIONAL_OF, GUAVA_OPTIONAL_FROM_NULLABLE).test(innerExpectedCall)) {
+ registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::RemoveExpectedOutmostMethodCallQuickFix)
} else if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) {
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_ABSENT)
}
@@ -60,8 +61,8 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
}
if (isEqualTo) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
- if (GUAVA_OPTIONAL_OF.test(innerExpectedCall) || GUAVA_OPTIONAL_FROM_NULLABLE.test(innerExpectedCall)) {
- registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) { desc, method ->
+ if (CallMatcher.anyOf(GUAVA_OPTIONAL_OF, GUAVA_OPTIONAL_FROM_NULLABLE).test(innerExpectedCall)) {
+ registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) { desc, method ->
QuickFixWithPostfixDelegate(
RemoveExpectedOutmostMethodCallQuickFix(desc, method),
ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
@@ -88,7 +89,7 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
replacementMethod: String,
noExpectedExpression: Boolean = false
) {
- registerReplaceMethod(holder, expression, oldExpectedCallExpression, replacementMethod) { desc, method ->
+ registerRemoveActualOutmostMethod(holder, expression, oldExpectedCallExpression, replacementMethod) { desc, method ->
QuickFixWithPostfixDelegate(
RemoveActualOutmostMethodCallQuickFix(desc, method, noExpectedExpression),
ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
@@ -96,11 +97,7 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
}
}
- private fun registerSimplifyForGuavaMethod(
- holder: ProblemsHolder,
- expression: PsiMethodCallExpression,
- replacementMethod: String
- ) {
+ private fun registerSimplifyForGuavaMethod(holder: ProblemsHolder, expression: PsiMethodCallExpression, replacementMethod: String) {
val originalMethod = getOriginalMethodName(expression) ?: return
val description = REPLACE_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod)
val message = SIMPLIFY_MESSAGE_TEMPLATE.format(originalMethod, replacementMethod)
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 d7e3ab0..28c869f 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
@@ -4,6 +4,7 @@ import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
+import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
@@ -31,8 +32,8 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
if (ASSERT_THAT_JAVA8_OPTIONAL.test(expression)) {
if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
- if (OPTIONAL_OF.test(innerExpectedCall) || OPTIONAL_OF_NULLABLE.test(innerExpectedCall)) {
- registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::RemoveExpectedOutmostMethodCallQuickFix)
+ if (CallMatcher.anyOf(OPTIONAL_OF, OPTIONAL_OF_NULLABLE).test(innerExpectedCall)) {
+ registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::RemoveExpectedOutmostMethodCallQuickFix)
} else if (OPTIONAL_EMPTY.test(innerExpectedCall)) {
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_NOT_PRESENT)
}
@@ -47,18 +48,18 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
if (OPTIONAL_GET.test(actualExpression)) {
if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) {
- registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) { desc, method ->
+ registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) { desc, method ->
RemoveActualOutmostMethodCallQuickFix(desc, method)
}
} else if (IS_SAME_AS_OBJECT.test(expectedCallExpression)) {
- registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS_SAME) { desc, method ->
+ registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS_SAME) { desc, method ->
RemoveActualOutmostMethodCallQuickFix(desc, method)
}
}
} else if (OPTIONAL_IS_PRESENT.test(actualExpression)) {
val expectedPresence = getExpectedBooleanResult(expectedCallExpression) ?: return
val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_NOT_PRESENT)
- registerReplaceMethod(holder, expression, expectedCallExpression, replacementMethod) { desc, method ->
+ registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, replacementMethod) { desc, method ->
RemoveActualOutmostMethodCallQuickFix(desc, method, 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 3ef3f17..56ea732 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
@@ -6,6 +6,7 @@ import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.siyeh.ig.callMatcher.CallMatcher
import com.siyeh.ig.callMatcher.CallMatcher.anyOf
+import com.siyeh.ig.callMatcher.CallMatcher.staticCall
import de.platon42.intellij.plugins.cajon.AssertJClassNames
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceJUnitAssertMethodCallQuickFix
@@ -19,91 +20,91 @@ class JUnitAssertToAssertJInspection : AbstractJUnitAssertInspection() {
private val MAPPINGS = listOf(
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "boolean"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes("boolean")
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "boolean"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes("boolean")
),
MethodNames.IS_TRUE, false
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "boolean"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes("boolean")
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "boolean"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes("boolean")
),
MethodNames.IS_FALSE, false
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, CommonClassNames.JAVA_LANG_OBJECT),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, CommonClassNames.JAVA_LANG_OBJECT),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)
),
MethodNames.IS_NULL, false
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, CommonClassNames.JAVA_LANG_OBJECT),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, CommonClassNames.JAVA_LANG_OBJECT),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)
),
MethodNames.IS_NOT_NULL, false
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "double", "double", "double"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes("double", "double", "double"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "float", "float", "float"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes("float", "float", "float")
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "double", "double", "double"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes("double", "double", "double"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "float", "float", "float"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes("float", "float", "float")
),
MethodNames.IS_CLOSE_TO, hasDelta = true
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(3),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(2)
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(3),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(2)
),
MethodNames.IS_EQUAL_TO
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "double", "double", "double"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes("double", "double", "double"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "float", "float", "float"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes("float", "float", "float")
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "double", "double", "double"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes("double", "double", "double"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "float", "float", "float"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes("float", "float", "float")
),
MethodNames.IS_NOT_CLOSE_TO, hasDelta = true
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(3),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(2)
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(3),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(2)
),
MethodNames.IS_NOT_EQUAL_TO
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(3),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(2)
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(3),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(2)
),
MethodNames.IS_SAME_AS
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(3),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(2)
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(3),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(2)
),
MethodNames.IS_NOT_SAME_AS
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "double[]", "double[]", "double"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes("double[]", "double[]", "double"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "float[]", "float[]", "float"),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes("float[]", "float[]", "float")
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "double[]", "double[]", "double"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes("double[]", "double[]", "double"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(CommonClassNames.JAVA_LANG_STRING, "float[]", "float[]", "float"),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes("float[]", "float[]", "float")
),
MethodNames.CONTAINS_EXACTLY, hasDelta = true
),
Mapping(
anyOf(
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(2),
- CallMatcher.staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(3)
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(2),
+ staticCall(JUNIT_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(3)
),
MethodNames.CONTAINS_EXACTLY
)
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ForGuavaPostFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ForGuavaPostFix.kt
index 05a7835..01ce9cf 100644
--- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ForGuavaPostFix.kt
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ForGuavaPostFix.kt
@@ -5,21 +5,19 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiStatement
import com.intellij.psi.util.PsiTreeUtil
-import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
class ForGuavaPostFix {
companion object {
- private val CORE_MATCHER = CallMatcher.staticCall(AssertJClassNames.ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)
val REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT: (Project, ProblemDescriptor) -> Unit = exit@
{ _, descriptor ->
val element = descriptor.startElement
val statement = PsiTreeUtil.getParentOfType(element, PsiStatement::class.java) ?: return@exit
- val methodCallExpression = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { CORE_MATCHER.test(it) } ?: return@exit
+ val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { CORE_ASSERT_THAT_MATCHER.test(it) } ?: return@exit
- val newMethodCall = createGuavaAssertThat(element, methodCallExpression.firstArg)
+ val newMethodCall = createGuavaAssertThat(element, assertThatCall.firstArg)
newMethodCall.resolveMethod()?.addAsStaticImport(element, AssertJClassNames.ASSERTIONS_CLASSNAME)
- val parentCall = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression::class.java) ?: return@exit
+ val parentCall = PsiTreeUtil.getParentOfType(assertThatCall, PsiMethodCallExpression::class.java) ?: return@exit
parentCall.replaceQualifier(newMethodCall)
parentCall.shortenAndReformat()
}
diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributor.kt b/src/main/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributor.kt
new file mode 100644
index 0000000..369c5d8
--- /dev/null
+++ b/src/main/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributor.kt
@@ -0,0 +1,162 @@
+package de.platon42.intellij.plugins.cajon.references
+
+import com.intellij.lang.jvm.JvmModifier
+import com.intellij.openapi.util.TextRange
+import com.intellij.patterns.PlatformPatterns
+import com.intellij.psi.*
+import com.intellij.psi.util.PropertyUtilBase
+import com.intellij.psi.util.PsiTreeUtil
+import com.intellij.psi.util.PsiTypesUtil
+import com.intellij.util.ProcessingContext
+import com.siyeh.ig.callMatcher.CallMatcher
+import de.platon42.intellij.plugins.cajon.AssertJClassNames
+import de.platon42.intellij.plugins.cajon.CORE_ASSERT_THAT_MATCHER
+import de.platon42.intellij.plugins.cajon.firstArg
+
+class ExtractorReferenceContributor : PsiReferenceContributor() {
+
+ companion object {
+
+ private val EXTRACTING_FROM_OBJECT = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ASSERT_CLASSNAME, "extracting")
+ private val EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extracting")
+ private val FLAT_EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "flatExtracting")
+ private val EXTRACTING_RESULT_OF_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extractingResultOf")
+
+ private val BY_NAME = CallMatcher.staticCall(AssertJClassNames.EXTRACTORS_CLASSNAME, "byName")
+ private val RESULT_OF = CallMatcher.staticCall(AssertJClassNames.EXTRACTORS_CLASSNAME, "resultOf")
+ .parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!
+
+ private val propertyOrFieldReferenceProvider = PropertyOrFieldReferenceProvider()
+ private val iterablePropertyOrFieldReferenceProvider = IterablePropertyOrFieldReferenceProvider()
+ private val iterableResultOfReferenceProvider = IterableResultOfReferenceProvider()
+
+ private fun lookupFieldOrProperty(containingClass: PsiClass, path: String, startOffset: Int): List>> {
+ val partName = path.substring(startOffset).substringBefore(".")
+ val nextOffset = startOffset + partName.length + 1
+
+ val matchedGetter = PropertyUtilBase.findPropertyGetter(containingClass, partName, false, true)
+ val fieldResult = PropertyUtilBase.findPropertyField(containingClass, partName, false)
+ val textRange = TextRange(startOffset + 1, nextOffset)
+ val matchedBareMethod = containingClass.allMethods.find { (it.name == partName) && !it.hasModifier(JvmModifier.STATIC) }
+ val targets = listOfNotNull(fieldResult, matchedGetter, matchedBareMethod)
+ if (targets.isNotEmpty()) {
+ val results = listOf(textRange to targets)
+ if (nextOffset >= path.length) {
+ return results
+ }
+ val nextClass = PsiTypesUtil.getPsiClass(matchedGetter?.returnType ?: fieldResult?.type) ?: return results
+ return listOf(results, lookupFieldOrProperty(nextClass, path, nextOffset)).flatten()
+ }
+ return emptyList()
+ }
+
+ private fun lookupMethod(containingClass: PsiClass, methodName: String): List>>? {
+ val matchedMethod = containingClass.allMethods.find { (it.name == methodName) && !it.hasModifier(JvmModifier.STATIC) } ?: return null
+ val textRange = TextRange(1, methodName.length + 1)
+ return listOf(textRange to listOf(matchedMethod))
+ }
+
+ private fun findActualType(element: PsiElement): PsiClassType? {
+ val assertThatCall = PsiTreeUtil.findChildrenOfType(element, PsiMethodCallExpression::class.java)
+ .find { CORE_ASSERT_THAT_MATCHER.test(it) } ?: return null
+ return assertThatCall.firstArg.type as? PsiClassType
+ }
+
+ private fun findAndCreateReferences(element: PsiElement, finder: (PsiLiteralExpression) -> List>>?): Array {
+ val literal = element as PsiLiteralExpression
+ val results = finder(literal)
+ if (results != null) {
+ return results.map { ExtractorReference(literal, it.first, it.second) }.toTypedArray()
+ }
+ return PsiReference.EMPTY_ARRAY
+ }
+ }
+
+ override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
+ registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiLiteralExpression::class.java), propertyOrFieldReferenceProvider)
+ registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiLiteralExpression::class.java), iterablePropertyOrFieldReferenceProvider)
+ registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiLiteralExpression::class.java), iterableResultOfReferenceProvider)
+ }
+
+ class ExtractorReference(literal: PsiLiteralExpression, range: TextRange, private val targets: List) :
+ PsiPolyVariantReferenceBase(literal, range, true) {
+
+ override fun resolve(): PsiElement? {
+ return multiResolve(false).map(ResolveResult::getElement).firstOrNull()
+ }
+
+ override fun multiResolve(incompleteCode: Boolean): Array {
+ return PsiElementResolveResult.createResults(targets)
+ }
+ }
+
+ class PropertyOrFieldReferenceProvider : PsiReferenceProvider() {
+
+ override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array {
+ return findAndCreateReferences(element, ::findReferences)
+ }
+
+ fun findReferences(element: PsiLiteralExpression): List>>? {
+ val literal = element.value as? String ?: return null
+ var methodCallExpression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression::class.java) ?: return null
+ var isResultOf = false
+ if (BY_NAME.test(methodCallExpression)) {
+ methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression::class.java) ?: return null
+ } else if (RESULT_OF.test(methodCallExpression)) {
+ methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression::class.java) ?: return null
+ isResultOf = true
+ }
+ if (!EXTRACTING_FROM_OBJECT.test(methodCallExpression)) {
+ return emptyList()
+ }
+ val containingClass = PsiTypesUtil.getPsiClass(findActualType(methodCallExpression)) ?: return null
+ return if (isResultOf) lookupMethod(containingClass, literal) else lookupFieldOrProperty(containingClass, literal, 0)
+ }
+ }
+
+ class IterablePropertyOrFieldReferenceProvider : PsiReferenceProvider() {
+
+ override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array {
+ return findAndCreateReferences(element, ::findReferences)
+ }
+
+ fun findReferences(element: PsiLiteralExpression): List>>? {
+ val literal = element.value as? String ?: return null
+ var methodCallExpression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression::class.java) ?: return null
+ var isResultOf = false
+ if (BY_NAME.test(methodCallExpression)) {
+ methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression::class.java) ?: return null
+ } else if (RESULT_OF.test(methodCallExpression)) {
+ methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression::class.java) ?: return null
+ isResultOf = true
+ }
+
+ if (!CallMatcher.anyOf(EXTRACTING_FROM_ITERABLE, FLAT_EXTRACTING_FROM_ITERABLE).test(methodCallExpression)) {
+ return null
+ }
+ val iterableType = findActualType(methodCallExpression) ?: return null
+ val innerType = iterableType.resolveGenerics().substitutor.substitute(iterableType.parameters[0])
+ val containingClass = PsiTypesUtil.getPsiClass(innerType) ?: return null
+ return if (isResultOf) lookupMethod(containingClass, literal) else lookupFieldOrProperty(containingClass, literal, 0)
+ }
+ }
+
+ class IterableResultOfReferenceProvider : PsiReferenceProvider() {
+
+ override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array {
+ return findAndCreateReferences(element, ::findReferences)
+ }
+
+ fun findReferences(element: PsiLiteralExpression): List>>? {
+ val literal = element.value as? String ?: return null
+ val methodCallExpression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression::class.java) ?: return null
+ if (!EXTRACTING_RESULT_OF_FROM_ITERABLE.test(methodCallExpression)) {
+ return null
+ }
+ val iterableType = findActualType(methodCallExpression) ?: return null
+ val innerType = iterableType.resolveGenerics().substitutor.substitute(iterableType.parameters[0])
+ val containingClass = PsiTypesUtil.getPsiClass(innerType) ?: return null
+ return lookupMethod(containingClass, literal)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index d7c90e8..0530208 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -7,10 +7,11 @@
Cajon is an IntelliJ IDEA Plugin for shortening and optimizing AssertJ assertions.
It adds inspections and quick fixes to fully make use of the AssertJ methods
to make the intention clear and concise. It can also convert JUnit 4 assertions to AssertJ.
+ It supports referencing inside extracting()-methods with strings, adding refactoring safety.
]]>
-
+
@@ -19,6 +20,7 @@
com.intellij.modules.java
+
contactList = Collections.emptyList();
+
+ assertThat(contact).extracting("name").isEqualTo("foo");
+ assertThat(contact).extracting("age", "country", "address.street", "street", "address.noMailings", "address.REALLYnoMAILINGS").containsExactly(1, "Elmst. 42");
+ assertThat(contact).extracting(Extractors.byName("name")).isEqualTo("foo");
+ assertThat(contact).extracting(Extractors.resultOf("getStreet")).isEqualTo("foo");
+ assertThat(contact).extracting(Extractors.resultOf("getStreet"), Extractors.byName("narf")).isEqualTo("foo");
+
+ assertThat(contactList).extracting("name").isEqualTo("foo");
+ assertThat(contactList).extracting("name", "moar").isEqualTo("foo");
+ assertThat(contactList).extracting("name", String.class).isEqualTo("foo");
+ assertThat(contactList).extracting(Extractors.byName("name")).isEqualTo("foo");
+ assertThat(contactList).extracting(Extractors.resultOf("getStreet"), Extractors.byName("narf")).isEqualTo("foo");
+ assertThat(contactList).extractingResultOf("getStreet").isEqualTo("foo");
+ assertThat(contactList).extractingResultOf("getStreet", String.class).isEqualTo("foo");
+ assertThat(contactList).flatExtracting("age", "address.street", "street").containsExactly(1, "Elmst. 42");
+ assertThat(contactList).flatExtracting("age").containsExactly(1, "Elmst. 42");
+ }
+
+ public class Contact {
+ private String name;
+ private Integer age;
+ private Address address;
+
+ public String getStreet() {
+ return address.getStreet();
+ }
+ }
+
+ public class Address {
+ private String street;
+ private String country;
+
+ public String getStreet() {
+ return street;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public boolean isNoMailings() {
+ return true;
+ }
+
+ public Boolean getREALLYnoMAILINGS() {
+ return true;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/test/java/de/platon42/intellij/plugins/cajon/AbstractCajonTest.kt b/src/test/java/de/platon42/intellij/plugins/cajon/AbstractCajonTest.kt
index 19c70d3..4f96228 100644
--- a/src/test/java/de/platon42/intellij/plugins/cajon/AbstractCajonTest.kt
+++ b/src/test/java/de/platon42/intellij/plugins/cajon/AbstractCajonTest.kt
@@ -20,7 +20,7 @@ import java.lang.reflect.InvocationTargetException
@AddLocalJarToModule(Assertions::class)
abstract class AbstractCajonTest {
- // See https://github.com/junit-team/junit5/issues/157
+ // See https://github.com/junit-team/junit5/issues/157, should be resolved with junit5 5.5 M2
protected fun runTest(body: () -> Unit) {
val throwables = arrayOfNulls(1)
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
index bf1522f..1b0b6c5 100644
--- a/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspectionTest.kt
+++ b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatGuavaOptionalInspectionTest.kt
@@ -9,44 +9,45 @@ 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)
+@TestDataSubPath("inspections/AssertThatGuavaOptional")
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()"), 5)
- executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isAbsent()"), 5)
- 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()"), 7)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with isPresent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with isPresent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isPresent()"), 3)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with isAbsent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isAbsent()"), 3)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with isAbsent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isTrue() with isPresent()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isFalse() with isAbsent()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with contains()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap expected expression and replace isEqualTo() with contains()"), 6)
myFixture.checkResultByFile("AssertThatGuavaOptionalAfter.java")
}
}
@Test
- @TestDataSubPath("inspections/AssertThatGuavaOptional")
internal fun adds_missing_Guava_import_any_order(@MyFixture myFixture: JavaCodeInsightTestFixture) {
runTest {
myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java)
myFixture.configureByFile("WithoutPriorGuavaImportBefore.java")
- executeQuickFixes(myFixture, Regex("Replace .* with .*"), 7)
+ executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 7)
myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java")
}
}
@Test
- @TestDataSubPath("inspections/AssertThatGuavaOptional")
internal fun adds_missing_Guava_import_isAbsent_first(@MyFixture myFixture: JavaCodeInsightTestFixture) {
runTest {
myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java)
myFixture.configureByFile("WithoutPriorGuavaImportBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isAbsent()"), 1)
- executeQuickFixes(myFixture, Regex("Replace .* with .*"), 6)
+ executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 6)
myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java")
}
}
diff --git a/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspectionTest.kt b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspectionTest.kt
index c6fd09f..f7e3d64 100644
--- a/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspectionTest.kt
+++ b/src/test/java/de/platon42/intellij/plugins/cajon/inspections/AssertThatJava8OptionalInspectionTest.kt
@@ -14,14 +14,17 @@ internal class AssertThatJava8OptionalInspectionTest : AbstractCajonTest() {
runTest {
myFixture.enableInspections(AssertThatJava8OptionalInspection::class.java)
myFixture.configureByFile("AssertThatJava8OptionalBefore.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 isNotPresent()"), 3)
- executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isNotPresent()"), 2)
- executeQuickFixes(myFixture, Regex.fromLiteral("Replace isTrue() with isPresent()"), 1)
- executeQuickFixes(myFixture, Regex.fromLiteral("Replace isFalse() with isNotPresent()"), 1)
- executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with contains()"), 3)
- executeQuickFixes(myFixture, Regex.fromLiteral("Replace isSameAs() with containsSame()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with isPresent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with isPresent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with isNotPresent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with isNotPresent()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isTrue() with isPresent()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isNotPresent()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isPresent()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isFalse() with isNotPresent()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap expected expression and replace isEqualTo() with contains()"), 2)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with contains()"), 1)
+ executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isSameAs() with containsSame()"), 1)
myFixture.checkResultByFile("AssertThatJava8OptionalAfter.java")
}
}
diff --git a/src/test/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributorTest.kt b/src/test/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributorTest.kt
new file mode 100644
index 0000000..55f8a9b
--- /dev/null
+++ b/src/test/java/de/platon42/intellij/plugins/cajon/references/ExtractorReferenceContributorTest.kt
@@ -0,0 +1,93 @@
+package de.platon42.intellij.plugins.cajon.references
+
+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.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+
+@TestDataSubPath("references")
+internal class ExtractorReferenceContributorTest : AbstractCajonTest() {
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_for_field_extracting(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference1.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).isEqualTo("private String name;")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_for_first_part_of_a_path(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference2.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).isEqualTo("protected Address address;")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_for_second_part_of_a_path_and_both_getter_and_field(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference3.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).startsWith("private String street;")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_on_a_bare_method_call(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference4.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).startsWith("public Boolean getREALLYnoMAILINGS()")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_with_only_Getter_on_second_part(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference5.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).startsWith("public boolean isNoMailings()")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_using_byName_extractor(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference6.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).isEqualTo("private String name;")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_using_resultOf_extractor(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference7.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).startsWith("public String getStreetName()")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_for_field_extraction_on_list(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference8.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).isEqualTo("private String name;")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_for_field_flat_extraction_of_path_on_list(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference9.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).startsWith("private String street;")
+ }
+ }
+
+ @Test
+ internal fun extractor_is_able_to_find_reference_for_extraction_on_result_of_method(@MyFixture myFixture: JavaCodeInsightTestFixture) {
+ runTest {
+ myFixture.configureByFiles("FindReference10.java", "Address.java", "Contact.java")
+ assertThat(myFixture.elementAtCaret.text).startsWith("public String getStreetName()")
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/Address.java b/src/test/resources/references/Address.java
new file mode 100644
index 0000000..72ed8e1
--- /dev/null
+++ b/src/test/resources/references/Address.java
@@ -0,0 +1,20 @@
+public class Address {
+ private String street;
+ private String country;
+
+ private String getStreet() {
+ return street;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public boolean isNoMailings() {
+ return true;
+ }
+
+ public Boolean getREALLYnoMAILINGS() {
+ return true;
+ }
+}
diff --git a/src/test/resources/references/Contact.java b/src/test/resources/references/Contact.java
new file mode 100644
index 0000000..27d2c10
--- /dev/null
+++ b/src/test/resources/references/Contact.java
@@ -0,0 +1,9 @@
+public class Contact {
+ private String name;
+ public Integer age;
+ protected Address address;
+ public String getStreetName()
+ {
+ return address.getStreet();
+ }
+}
diff --git a/src/test/resources/references/FindReference1.java b/src/test/resources/references/FindReference1.java
new file mode 100644
index 0000000..df05e6a
--- /dev/null
+++ b/src/test/resources/references/FindReference1.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference1 {
+
+ private void findReferences() {
+ Contact contact = new Contact();
+
+ assertThat(contact).extracting("name").isEqualTo("foo");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference10.java b/src/test/resources/references/FindReference10.java
new file mode 100644
index 0000000..b02d3b3
--- /dev/null
+++ b/src/test/resources/references/FindReference10.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference10 {
+
+ private void findReferences() {
+ List contactList = Collections.emptyList();
+
+ assertThat(contactList).extractingResultOf("getStreetName").isEqualTo("foo");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference2.java b/src/test/resources/references/FindReference2.java
new file mode 100644
index 0000000..2e15ea1
--- /dev/null
+++ b/src/test/resources/references/FindReference2.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference2 {
+
+ private void findReferences() {
+ Contact contact = new Contact();
+
+ assertThat(contact).extracting("address.street", "streetName").containsExactly(1, "Elmst. 42");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference3.java b/src/test/resources/references/FindReference3.java
new file mode 100644
index 0000000..8d04444
--- /dev/null
+++ b/src/test/resources/references/FindReference3.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference3 {
+
+ private void findReferences() {
+ Contact contact = new Contact();
+
+ assertThat(contact).extracting("address.street", "address.REALLYnoMAILINGS").containsExactly(1, "Elmst. 42");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference4.java b/src/test/resources/references/FindReference4.java
new file mode 100644
index 0000000..3db8507
--- /dev/null
+++ b/src/test/resources/references/FindReference4.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference4 {
+
+ private void findReferences() {
+ Contact contact = new Contact();
+
+ assertThat(contact).extracting("address.getREALLYnoMAILINGS", "address.country").containsExactly(1, "Elmst. 42");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference5.java b/src/test/resources/references/FindReference5.java
new file mode 100644
index 0000000..315ad9e
--- /dev/null
+++ b/src/test/resources/references/FindReference5.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference5 {
+
+ private void findReferences() {
+ Contact contact = new Contact();
+
+ assertThat(contact).extracting("address.noMailings").containsExactly(1, "Elmst. 42");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference6.java b/src/test/resources/references/FindReference6.java
new file mode 100644
index 0000000..81b8085
--- /dev/null
+++ b/src/test/resources/references/FindReference6.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference6 {
+
+ private void findReferences() {
+ Contact contact = new Contact();
+
+ assertThat(contact).extracting(Extractors.byName("name")).isEqualTo("foo");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference7.java b/src/test/resources/references/FindReference7.java
new file mode 100644
index 0000000..e982661
--- /dev/null
+++ b/src/test/resources/references/FindReference7.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference7 {
+
+ private void findReferences() {
+ Contact contact = new Contact();
+
+ assertThat(contact).extracting(Extractors.resultOf("getStreetName")).isEqualTo("foo");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference8.java b/src/test/resources/references/FindReference8.java
new file mode 100644
index 0000000..cac52dc
--- /dev/null
+++ b/src/test/resources/references/FindReference8.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference8 {
+
+ private void findReferences() {
+ List contactList = Collections.emptyList();
+
+ assertThat(contactList).extracting("name").isEqualTo("foo");
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/references/FindReference9.java b/src/test/resources/references/FindReference9.java
new file mode 100644
index 0000000..6314ae8
--- /dev/null
+++ b/src/test/resources/references/FindReference9.java
@@ -0,0 +1,15 @@
+import org.assertj.core.extractor.Extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FindReference9 {
+
+ private void findReferences() {
+ List contactList = Collections.emptyList();
+
+ assertThat(contactList).flatExtracting("age", "address.street", "streetName").containsExactly(1, "Elmst. 42");
+ }
+}
\ No newline at end of file