Compare commits

..
11 Commits
Author SHA1 Message Date
chrisly42 ecb5029154 Fixed a NPE in AssumeThatInsteadOfReturn inspection quickfix for empty else branches.
Fixed missing description for AssumeThatInsteadOfReturn inspection.
Added new AssertThatCollectionOrMapExpression inspection that tries to pull out methods such as isEmpty() or contains() out of an actual assertThat() expression. Added more method calls that are considered extension points.
2019-05-06 20:17:11 +02:00
chrisly42 0e2007641c Compatibility fixes for IDEA <= 2019.1 :-/ 2019-05-05 20:06:12 +02:00
chrisly42 eab50f590b Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls. Removed oraclejdk8 from travis-ci. Added custom Jupiter DisplayNameGenerator for user friendly test names in report. Extended documentation. Removed Playground. 2019-05-05 19:02:35 +02:00
chrisly42 66f1467b23 Added coveralls. 2019-05-04 16:40:05 +02:00
chrisly42 6a36294a2b Added travis Build Status to readme. 2019-05-04 16:15:36 +02:00
chrisly42 0b79a6d7dc Added early bail-outs via simple text matchings to optimize speed of false positive detection. 2019-05-04 15:54:27 +02:00
chrisly42 6fb23ea89c Heavily reworked inspections for edge cases, such as multiple isEqualTo() calls inside a single statement. Corrected highlighting for most inspections. Lots of refactorings, tweakings. Added travis-ci file (untested). Added jacoco. 2019-05-04 15:36:04 +02:00
chrisly42 362c4210a5 Fixed isEmpty() for enumerables and strings and isNull() for object conversions to be applied only if it is the terminal method call as isEmpty() and isNull() return void. 2019-05-01 13:15:31 +02:00
chrisly42 e55acf9c74 Extended test cases for AssertThatBooleanCondition and AssertThatObjectIsNullOrNotNull. 2019-04-29 20:10:55 +02:00
chrisly42 3ece81b024 Minor fixes to descriptions. 2019-04-29 19:58:05 +02:00
chrisly42 0b2ce470db Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions. 2019-04-29 19:58:00 +02:00
102 changed files with 2049 additions and 1163 deletions
+10
View File
@@ -0,0 +1,10 @@
language: java
jdk:
- openjdk8
before_script:
- chmod +x gradlew
- chmod +x gradle/wrapper/gradle-wrapper.jar
script:
- ./gradlew clean test jacocoTestReport coveralls
+135 -9
View File
@@ -1,4 +1,4 @@
# Cajon - Concise AssertJ Optimizing Nitpicker # Cajon - Concise AssertJ Optimizing Nitpicker [![Build Status](https://travis-ci.org/chrisly42/cajon-plugin.svg?branch=master)](https://travis-ci.org/chrisly42/cajon-plugin) [![Coverage Status](https://coveralls.io/repos/github/chrisly42/cajon-plugin/badge.svg?branch=master)](https://coveralls.io/github/chrisly42/cajon-plugin?branch=master)
Cajon is an IntelliJ IDEA Plugin for shortening and optimizing [AssertJ](https://assertj.github.io/doc/) assertions. Cajon is an IntelliJ IDEA Plugin for shortening and optimizing [AssertJ](https://assertj.github.io/doc/) assertions.
@@ -73,19 +73,23 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
## Implemented inspections and quickfixes ## Implemented inspections and quickfixes
- JoinAssertThatStatements - JoinAssertThatStatements
Joins multiple ```assertThat()``` statements with same actual expression together.
``` ```
from: assertThat(expected).someCondition(); from: assertThat(expected).someCondition();
assertThat(expected).anotherCondition(); assertThat(expected).anotherCondition();
to: assertThat(expected).someCondition().anotherCondition(); to: assertThat(expected).someCondition().anotherCondition();
``` ```
Joining will work on actual expressions inside assertThat() that are Joining will work on actual expressions inside assertThat() that are equivalent expressions,
- the same variable reference except for method calls with known side-effect methods such as ```Iterator.next()``` -- please notify me about others.
- textually equal binary expressions
- the same method calls (except for known side-effect methods such as ```Iterator.next()``` -- please notify me about others)
The comments of the statements will be preserved. When using ```.extracting()``` or similar, the statements will not be merged. The comments of the statements will be preserved. When using ```.extracting()``` or similar, the statements will not be merged.
- AssertThatObjectIsNullOrNotNull - AssertThatObjectIsNullOrNotNull
Uses ```isNull()``` and ```isNotNull()``` instead.
``` ```
from: assertThat(object).isEqualTo(null); from: assertThat(object).isEqualTo(null);
to: assertThat(object).isNull(); to: assertThat(object).isNull();
@@ -95,12 +99,18 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
``` ```
- AssertThatBooleanCondition - AssertThatBooleanCondition
Uses ```isTrue()``` and ```isFalse()``` instead.
``` ```
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();
``` ```
- AssertThatInvertedBooleanCondition - AssertThatInvertedBooleanCondition
Inverts the boolean condition to make it more readable.
``` ```
from: assertThat(!booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE); from: assertThat(!booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE);
from: assertThat(!booleanValue).isTrue()/isFalse(); from: assertThat(!booleanValue).isTrue()/isFalse();
@@ -108,6 +118,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
``` ```
- AssertThatInstanceOf - AssertThatInstanceOf
Moves ```instanceof``` expressions out of ```assertThat()```.
``` ```
from: assertThat(object instanceof classname).isEqualTo(true); from: assertThat(object instanceof classname).isEqualTo(true);
from: assertThat(object instanceof classname).isTrue(); from: assertThat(object instanceof classname).isTrue();
@@ -119,13 +132,21 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
``` ```
- AssertThatStringIsEmpty - AssertThatStringIsEmpty
Uses ```isEmpty()``` for empty string assertions.
``` ```
from: assertThat(charSequence/string).isEqualTo(""); from: assertThat(charSequence/string).isEqualTo("");
from: assertThat(charSequence/string).hasSize(0); from: assertThat(charSequence/string).hasSize(0);
to: assertThat(charSequence/string).isEmpty(); to: assertThat(charSequence/string).isEmpty();
``` ```
The ```assertThat(string.length()).isEqualTo(0);``` case is handled in the AssertThatSize inspection.
- AssertThatStringExpression - AssertThatStringExpression
Moves string operations inside assertThat() out.
``` ```
from: assertThat(stringActual.isEmpty()).isTrue(); from: assertThat(stringActual.isEmpty()).isTrue();
to: assertThat(stringActual).isEmpty(); to: assertThat(stringActual).isEmpty();
@@ -148,13 +169,45 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
``` ```
Analogously with ```isFalse()```. Analogously with ```isFalse()```.
- AssertThatCollectionOrMapExpression
Moves collection and map operations inside assertThat() out.
```
from: assertThat(collection.isEmpty()).isTrue();
to: assertThat(collection).isEmpty();
from: assertThat(collection.contains("foobar")).isTrue();
to: assertThat(collection).contains("foobar");
from: assertThat(collection.containsAll(otherCollection)).isTrue();
to: assertThat(collection).containsAll(otherCollection);
from: assertThat(map.isEmpty()).isTrue();
to: assertThat(map).isEmpty();
from: assertThat(map.containsKey(key)).isTrue();
to: assertThat(map).containsKey(key);
from: assertThat(map.containsValue(value)).isTrue();
to: assertThat(map).containsValue(value);
```
Analogously with ```isFalse()``` (except for containsAll()).
- AssertThatEnumerableIsEmpty - AssertThatEnumerableIsEmpty
Uses ```isEmpty()``` for ```hasSize(0)``` iterable assertions instead.
``` ```
from: assertThat(enumerable).hasSize(0); from: assertThat(enumerable).hasSize(0);
to: assertThat(enumerable).isEmpty(); to: assertThat(enumerable).isEmpty();
``` ```
- AssertThatSize - AssertThatSize
Makes assertions on sizes of arrays, collections, strings,
or ```CharSequence```s more concise.
``` ```
from: assertThat(array.length).isEqualTo(0); from: assertThat(array.length).isEqualTo(0);
from: assertThat(array.length).isLessThanOrEqualTo(0); from: assertThat(array.length).isLessThanOrEqualTo(0);
@@ -203,6 +256,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
``` ```
- AssertThatBinaryExpression - AssertThatBinaryExpression
Splits a boolean condition represented by binary expression out of ```assertThat()```.
``` ```
from: assertThat(primActual == primExpected).isTrue(); from: assertThat(primActual == primExpected).isTrue();
to: assertThat(primActual).isEqualTo(primExpected); to: assertThat(primActual).isEqualTo(primExpected);
@@ -222,6 +278,11 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
...and many, many more combinations (more than 150). ...and many, many more combinations (more than 150).
- AssertThatJava8Optional - AssertThatJava8Optional
Examines the statement for Java 8 Optional type and whether the statement
effectively tries to assert the presence, absence or content and then
replaces the statement by better assertions.
``` ```
from: assertThat(opt.isPresent()).isEqualTo(true); from: assertThat(opt.isPresent()).isEqualTo(true);
from: assertThat(opt.isPresent()).isNotEqualTo(false); from: assertThat(opt.isPresent()).isNotEqualTo(false);
@@ -251,6 +312,11 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
``` ```
- AssertThatGuavaOptional - AssertThatGuavaOptional
Examines the statement for Google Guava Optional type and whether the statement
effectively tries to assert the presence, absence or content and then
replaces the statement by better assertions.
``` ```
from: assertThat(opt.isPresent()).isEqualTo(true); from: assertThat(opt.isPresent()).isEqualTo(true);
from: assertThat(opt.isPresent()).isNotEqualTo(false); from: assertThat(opt.isPresent()).isNotEqualTo(false);
@@ -278,7 +344,54 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
AssertJ for Guava needs to be available in the classpath. AssertJ for Guava needs to be available in the classpath.
- AssumeThatInsteadOfReturn
Tries to detect bogus uses of return statements in test methods and replaces them by ```assumeThat()``` calls.
Novices will use these to skip test execution by bailing out early on some preconditions not met.
However, this suggests that the test has actually been run and passed instead of showing the test
as being skipped.
Return statements in ```if``` statements in main test methods (must be annotated with JUnit 4 or
Jupiter @Test annotations) will be verified to have at least one ```assertThat()``` statement in the code flow.
Method calls within the same class will be examined for ```assertThat()``` statements, too.
However, at most 50 statements and down to five recursions will be tolerated before giving up.
Currently, the quickfix may lose some comments during operation. The other branch of the ```if``` statement
will be inlined (blocks with declarations will remain a code block due to variable scope).
The generated ```assumeThat()``` statement could be optimized further (similar to ```assertThat()```).
Example:
```
@Test
public void check_fuel_emission() {
if (System.getProperty("manufacturer").equals("Volkswagen")) {
return;
}
double nitroxppm = doWltpDrivingCycle();
assertThat(nitroxppm).isLessThan(500.0);
}
```
will be transformed to
```
@Test
public void check_fuel_emission() {
assumeThat(System.getProperty("manufacturer").equals("Volkswagen")).isFalse();
double nitroxppm = doWltpDrivingCycle();
assertThat(nitroxppm).isLessThan(500.0);
}
```
- JUnitAssertToAssertJ - JUnitAssertToAssertJ
Tries to convert most of the JUnit 4 assertions to AssertJ format.
Does not support Hamcrest-Matchers.
If you need that kind of conversion, you might want to check out the
[Assertions2AssertJ plugin](https://plugins.jetbrains.com/plugin/10345-assertions2assertj) by Ric Emery.
``` ```
assertTrue(condition); assertTrue(condition);
assertTrue(message, condition); assertTrue(message, condition);
@@ -334,17 +447,30 @@ The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing and
Feel free to use the code (in package de.platon42.intellij.jupiter) for your projects (with attribution). Feel free to use the code (in package de.platon42.intellij.jupiter) for your projects (with attribution).
## Planned features ## Planned features
- AssumeThatInsteadOfReturn
- Extraction with property names to lambda with Java 8 - Extraction with property names to lambda with Java 8
``` ```
from: assertThat(object).extracting("propOne", "propNoGetter", "propTwo.innerProp")... from: assertThat(object).extracting("propOne", "propNoGetter", "propTwo.innerProp")...
to: assertThat(object).extracting(type::getPropOne, it -> it.propNoGetter, it -> it.getPropTwo().getInnerProp())... to: assertThat(object).extracting(type::getPropOne, it -> it.propNoGetter, it -> it.getPropTwo().getInnerProp())...
``` ```
- Kotlin support (right now, however, with less than 100 downloads after a month, this is unlikely to happen)
## Changelog ## Changelog
#### V1.0 (06-May-19)
- First release to be considered stable enough for production use.
- Fixed a NPE in AssumeThatInsteadOfReturn inspection quickfix for empty else branches.
- Fixed missing description for AssumeThatInsteadOfReturn inspection.
- Added new AssertThatCollectionOrMapExpression inspection that tries to pull out methods such as ```isEmpty()``` or ```contains()``` out of an actual assertThat() expression.
#### V0.8 (05-May-19)
- Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
- Fixed ```isEmpty()``` for enumerables and strings and ```isNull()``` for object conversions to be applied only if it is the terminal method call as ```isEmpty()``` and ```isNull()``` return void.
- Heavily reworked inspections for edge cases, such as multiple ```isEqualTo()``` calls inside a single statement.
- Some inspections could generate bogus code for weird situations, this has been made more fool-proof.
- Corrected highlighting for many inspections.
- Fixed family names for inspections in batch mode.
- Reworded many inspection messages for better understanding.
- Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by ```assumeThat()``` calls.
#### V0.7 (28-Apr-19) #### V0.7 (28-Apr-19)
- Another fix for AssertThatGuavaOptional inspection regarding using the same family name for slightly different quick fix executions - Another fix for AssertThatGuavaOptional inspection regarding using the same family name for slightly different quick fix executions
(really, Jetbrains, this sucks for no reason). (really, Jetbrains, this sucks for no reason).
+31 -17
View File
@@ -2,10 +2,12 @@ plugins {
id 'java' id 'java'
id 'org.jetbrains.intellij' version '0.4.8' id 'org.jetbrains.intellij' version '0.4.8'
id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'org.jetbrains.kotlin.jvm' version '1.3.31'
id 'jacoco'
id 'com.github.kt3k.coveralls' version '2.8.2'
} }
group 'de.platon42' group 'de.platon42'
version '0.7' version '1.0'
repositories { repositories {
mavenCentral() mavenCentral()
@@ -40,22 +42,23 @@ intellij {
patchPluginXml { patchPluginXml {
changeNotes """ changeNotes """
<h4>V0.7 (28-Apr-19)</h4> <h4>V1.0 (06-May-19)</h4>
<ul> <ul>
<li>Another fix for AssertThatGuavaOptional inspection regarding using the same family name for slightly different quick fix executions <li>First release to be considered stable enough for production use.
(really, Jetbrains, this sucks for no reason). <li>Fixed a NPE in AssumeThatInsteadOfReturn inspection quickfix for empty else branches.
<li>Extended AssertThatSize inspection to transform hasSize() into hasSameSizeAs(), if possible. <li>Fixed missing description for AssumeThatInsteadOfReturn inspection.
<li>Implemented first version of JoinAssertThatStatements inspection that will try to merge assertThat() statements with the same <li>Added new AssertThatCollectionOrMapExpression inspection that tries to pull out methods such as isEmpty() or contains() out of an actual assertThat() expression.
actual object together, preserving comments.
</ul> </ul>
<h4>V0.6 (22-Apr-19)</h4> <h4>V0.8 (05-May-19)</h4>
<ul> <ul>
<li>New AssertThatStringExpression inspection that will move isEmpty(), equals(), equalsIgnoreCase(), contains(), <li>Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
startsWith(), and endsWith() out of actual expression. <li>Fixed isEmpty() for enumerables and strings and isNull() for object conversions to be applied only if it is the terminal method call as isEmpty() and isNull() return void.
<li>Extended AssertThatSize inspection to take strings and CharSequences into account, too. <li>Heavily reworked inspections for edge cases, such as multiple isEqualTo() calls inside a single statement.
<li>New AssertThatInvertedBooleanCondition inspection that will remove inverted boolean expressions inside assertThat(). <li>Some inspections could generate bogus code for weird situations, this has been made more fool-proof.
<li>Renamed a few inspections to better/shorter names. <li>Corrected highlighting for many inspections.
<li>New AssertThatInstanceOf inspection that moves instanceof expressions out of assertThat(). <li>Fixed family names for inspections in batch mode.
<li>Reworded many inspection messages for better understanding.
<li>Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls.
</ul> </ul>
<p>Full changelog available at <a href="https://github.com/chrisly42/cajon-plugin#changelog">Github project site</a>.</p> <p>Full changelog available at <a href="https://github.com/chrisly42/cajon-plugin#changelog">Github project site</a>.</p>
""" """
@@ -63,9 +66,20 @@ patchPluginXml {
test { test {
useJUnitPlatform() useJUnitPlatform()
// testLogging { testLogging {
// events "passed", "skipped", "failed" events "passed", "skipped", "failed"
// } }
}
jacoco {
toolVersion = '0.8.3'
}
jacocoTestReport {
reports {
xml.enabled true
csv.enabled false
}
} }
publishPlugin { publishPlugin {
@@ -7,6 +7,18 @@ class AssertJClassNames {
@NonNls @NonNls
const val ASSERTIONS_CLASSNAME = "org.assertj.core.api.Assertions" const val ASSERTIONS_CLASSNAME = "org.assertj.core.api.Assertions"
@NonNls
const val ASSUMPTIONS_CLASSNAME = "org.assertj.core.api.Assumptions"
@NonNls
const val DESCRIPTABLE_INTERFACE = "org.assertj.core.api.Descriptable"
@NonNls
const val EXTENSION_POINTS_INTERFACE = "org.assertj.core.api.ExtensionPoints"
@NonNls
const val OBJECT_ENUMERABLE_ASSERT_INTERFACE = "org.assertj.core.api.ObjectEnumerableAssert"
@NonNls
const val ASSERT_INTERFACE = "org.assertj.core.api.Assert"
@NonNls @NonNls
const val ABSTRACT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractAssert" const val ABSTRACT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractAssert"
@NonNls @NonNls
@@ -32,7 +44,5 @@ class AssertJClassNames {
const val GUAVA_OPTIONAL_CLASSNAME = "com.google.common.base.Optional" const val GUAVA_OPTIONAL_CLASSNAME = "com.google.common.base.Optional"
@NonNls @NonNls
const val GUAVA_ASSERTIONS_CLASSNAME = "org.assertj.guava.api.Assertions" const val GUAVA_ASSERTIONS_CLASSNAME = "org.assertj.guava.api.Assertions"
@NonNls
const val GUAVA_OPTIONAL_ASSERT_CLASSNAME = "org.assertj.guava.api.OptionalAssert"
} }
} }
@@ -6,6 +6,7 @@ import com.siyeh.ig.callMatcher.CallMatcher
val CORE_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!! val CORE_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!!
val GUAVA_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.GUAVA_ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!! val GUAVA_ASSERT_THAT_MATCHER = CallMatcher.staticCall(AssertJClassNames.GUAVA_ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)!!
val ALL_ASSERT_THAT_MATCHERS = CallMatcher.anyOf(CORE_ASSERT_THAT_MATCHER, GUAVA_ASSERT_THAT_MATCHER)!! val ALL_ASSERT_THAT_MATCHERS = CallMatcher.anyOf(CORE_ASSERT_THAT_MATCHER, GUAVA_ASSERT_THAT_MATCHER)!!
val EXTRACTING_FROM_OBJECT = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ASSERT_CLASSNAME, "extracting")!! val EXTRACTING_FROM_OBJECT = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ASSERT_CLASSNAME, "extracting")!!
val EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extracting")!! val EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "extracting")!!
val FLAT_EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "flatExtracting")!! val FLAT_EXTRACTING_FROM_ITERABLE = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "flatExtracting")!!
@@ -18,6 +19,31 @@ val EXTRACTING_CALL_MATCHERS = CallMatcher.anyOf(
EXTRACTING_RESULT_OF_FROM_ITERABLE EXTRACTING_RESULT_OF_FROM_ITERABLE
)!! )!!
val DESCRIBED_AS = CallMatcher.instanceCall(AssertJClassNames.DESCRIPTABLE_INTERFACE, MethodNames.DESCRIBED_AS, MethodNames.AS)!!
val WITH_REPRESENTATION_AND_SUCH = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, "withRepresentation", "withThreadDumpOnError")!!
val USING_COMPARATOR = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, "usingComparator", "usingDefaultComparator")!!
val IN_HEXADECIMAL_OR_BINARY = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ASSERT_CLASSNAME, MethodNames.IN_HEXADECIMAL, MethodNames.IN_BINARY)!!
val EXTENSION_POINTS = CallMatcher.instanceCall(
AssertJClassNames.EXTENSION_POINTS_INTERFACE,
"is", "isNot", "has", "doesNotHave",
"satisfies"
)!!
val MORE_EXTENSION_POINTS = CallMatcher.instanceCall(
AssertJClassNames.OBJECT_ENUMERABLE_ASSERT_INTERFACE,
"are", "areNot", "have", "doNotHave",
"areAtLeast", "areAtLeastOne", "areAtMost", "areExactly",
"haveAtLeastOne", "haveAtLeast", "haveAtMost", "haveExactly",
"hasOnlyOneElementSatisfying", "anyMatch", "noneMatch", "anySatisfy", "noneSatisfy"
)!!
val NOT_ACTUAL_ASSERTIONS = CallMatcher.anyOf(
ALL_ASSERT_THAT_MATCHERS,
DESCRIBED_AS,
WITH_REPRESENTATION_AND_SUCH,
USING_COMPARATOR,
IN_HEXADECIMAL_OR_BINARY
)!!
val KNOWN_METHODS_WITH_SIDE_EFFECTS = CallMatcher.anyOf( val KNOWN_METHODS_WITH_SIDE_EFFECTS = CallMatcher.anyOf(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_ITERATOR, "next") CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_ITERATOR, "next")
)!! )!!
@@ -1,51 +1,76 @@
package de.platon42.intellij.plugins.cajon package de.platon42.intellij.plugins.cajon
import com.intellij.lang.jvm.JvmModifier
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.codeStyle.JavaCodeStyleManager import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiUtil
import com.siyeh.ig.callMatcher.CallMatcher import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.inspections.AbstractAssertJInspection
val PsiMethodCallExpression.qualifierExpression: PsiExpression get() = this.methodExpression.qualifierExpression!! val PsiMethodCallExpression.qualifierExpression: PsiExpression get() = methodExpression.qualifierExpression!!
val PsiMethodCallExpression.firstArg: PsiExpression get() = this.argumentList.expressions[0]!! val PsiMethodCallExpression.firstArg: PsiExpression get() = getArg(0)
fun PsiElement.hasAssertThat(): Boolean {
val elementText = text
return elementText.startsWith("${MethodNames.ASSERT_THAT}(") || elementText.contains(".${MethodNames.ASSERT_THAT}(")
}
fun PsiMethodCallExpression.replaceQualifier(qualifier: PsiElement) { fun PsiMethodCallExpression.replaceQualifier(qualifier: PsiElement) {
this.qualifierExpression.replace(qualifier) qualifierExpression.replace(qualifier)
} }
fun PsiMethodCallExpression.replaceQualifierFromMethodCall(oldMethodCall: PsiMethodCallExpression) { fun PsiMethodCallExpression.replaceQualifierFromMethodCall(oldMethodCall: PsiMethodCallExpression) {
this.qualifierExpression.replace(oldMethodCall.qualifierExpression) qualifierExpression.replace(oldMethodCall.qualifierExpression)
} }
fun PsiElement.findOutmostMethodCall(): PsiMethodCallExpression? { fun PsiElement.findOutmostMethodCall(): PsiMethodCallExpression? {
val statement = PsiTreeUtil.getParentOfType(this, PsiStatement::class.java) ?: return null val statement = PsiTreeUtil.getParentOfType(this, PsiStatement::class.java, false) ?: return null
return PsiTreeUtil.findChildOfType(statement, PsiMethodCallExpression::class.java) return PsiTreeUtil.findChildOfType(statement, PsiMethodCallExpression::class.java)
} }
fun PsiMethodCallExpression.findFluentCallTo(matcher: CallMatcher): PsiMethodCallExpression? { fun PsiElement.findStaticMethodCall(): PsiMethodCallExpression? {
var currentMethodCall: PsiMethodCallExpression? = this var elem: PsiElement? = this
while (currentMethodCall != null) { while (elem != null) {
if (matcher.test(currentMethodCall)) { if ((elem is PsiMethodCallExpression) && (elem.resolveMethod()?.hasModifier(JvmModifier.STATIC) == true)) {
return currentMethodCall return elem
} }
currentMethodCall = PsiTreeUtil.getParentOfType(currentMethodCall, PsiMethodCallExpression::class.java, true, PsiStatement::class.java) elem = elem.firstChild
} }
return null return null
} }
fun PsiMethodCallExpression.getArg(n: Int): PsiExpression = this.argumentList.expressions[n] fun PsiElement.gatherAssertionCalls(): List<PsiMethodCallExpression> {
val assertThatMethodCall = findStaticMethodCall() ?: return emptyList()
return assertThatMethodCall.collectMethodCallsUpToStatement()
.filterNot { NOT_ACTUAL_ASSERTIONS.test(it) }
.toList()
}
fun PsiMethodCallExpression.collectMethodCallsUpToStatement(): Sequence<PsiMethodCallExpression> {
return generateSequence(this) { PsiTreeUtil.getParentOfType(it, PsiMethodCallExpression::class.java, true, PsiStatement::class.java) }
}
fun PsiMethodCallExpression.findFluentCallTo(matcher: CallMatcher): PsiMethodCallExpression? {
return collectMethodCallsUpToStatement().find { matcher.test(it) }
}
fun PsiMethodCallExpression.getArg(n: Int): PsiExpression = PsiUtil.skipParenthesizedExprDown(argumentList.expressions[n])!!
fun PsiMethodCallExpression.getArgOrNull(n: Int): PsiExpression? = argumentList.expressions.getOrNull(n)
fun <T> Boolean.map(forTrue: T, forFalse: T) = if (this) forTrue else forFalse fun <T> Boolean.map(forTrue: T, forFalse: T) = if (this) forTrue else forFalse
fun PsiMethod.addAsStaticImport(context: PsiElement, vararg allowedClashes: String) { fun PsiMethod.addAsStaticImport(context: PsiElement, vararg allowedClashes: String) {
val factory = JavaPsiFacade.getElementFactory(context.project) val factory = JavaPsiFacade.getElementFactory(context.project)
val methodName = this.name val methodName = name
val containingClass = this.containingClass ?: return val containingClass = containingClass ?: return
val importList = (context.containingFile as PsiJavaFile).importList ?: return val importList = (context.containingFile as PsiJavaFile).importList ?: return
val notImportedStatically = importList.importStaticStatements.none { val notImportedStatically = importList.importStaticStatements.none {
val targetClass = it.resolveTargetClass() ?: return@none false val targetClass = it.resolveTargetClass() ?: return@none false
((it.referenceName == methodName) && !allowedClashes.contains(targetClass.qualifiedName)) ((it.referenceName == methodName) && !allowedClashes.contains(targetClass.qualifiedName))
|| (it.isOnDemand && (targetClass == this.containingClass)) || (it.isOnDemand && (targetClass == containingClass))
} }
if (notImportedStatically) { if (notImportedStatically) {
importList.add(factory.createImportStaticStatement(containingClass, methodName)) importList.add(factory.createImportStaticStatement(containingClass, methodName))
@@ -56,4 +81,68 @@ fun PsiElement.shortenAndReformat() {
val codeStyleManager = JavaCodeStyleManager.getInstance(project) val codeStyleManager = JavaCodeStyleManager.getInstance(project)
codeStyleManager.shortenClassReferences(this) codeStyleManager.shortenClassReferences(this)
CodeStyleManager.getInstance(project).reformat(this) CodeStyleManager.getInstance(project).reformat(this)
}
fun PsiMethodCallExpression.getExpectedBooleanResult(): Boolean? {
val isTrue = AbstractAssertJInspection.IS_TRUE.test(this)
val isFalse = AbstractAssertJInspection.IS_FALSE.test(this)
if (isTrue || isFalse) {
return isTrue
} else {
val isEqualTo = AbstractAssertJInspection.IS_EQUAL_TO_BOOLEAN.test(this) || AbstractAssertJInspection.IS_EQUAL_TO_OBJECT.test(this)
val isNotEqualTo =
AbstractAssertJInspection.IS_NOT_EQUAL_TO_BOOLEAN.test(this) || AbstractAssertJInspection.IS_NOT_EQUAL_TO_OBJECT.test(this)
if (isEqualTo || isNotEqualTo) {
val constValue = calculateConstantParameterValue(0) as? Boolean ?: return null
return isNotEqualTo xor constValue
}
}
return null
}
fun PsiMethodCallExpression.calculateConstantParameterValue(argIndex: Int): Any? {
if (argIndex >= argumentList.expressions.size) return null
val valueExpression = getArg(argIndex)
val constantEvaluationHelper = JavaPsiFacade.getInstance(project).constantEvaluationHelper
val value = constantEvaluationHelper.computeConstantExpression(valueExpression)
if (value == null) {
val field = (valueExpression as? PsiReferenceExpression)?.resolve() as? PsiField
if (field?.containingClass?.qualifiedName == CommonClassNames.JAVA_LANG_BOOLEAN) {
return when (field.name) {
"TRUE" -> true
"FALSE" -> false
else -> null
}
}
}
return value
}
fun PsiExpression.getAllTheSameExpectedBooleanConstants(): Boolean? {
val assertThatMethodCall = findStaticMethodCall() ?: return null
var lockedResult: Boolean? = null
val methodsToView = generateSequence(assertThatMethodCall) { PsiTreeUtil.getParentOfType(it, PsiMethodCallExpression::class.java) }
for (methodCall in methodsToView) {
val expectedResult = methodCall.getExpectedBooleanResult()
if (expectedResult != null) {
if ((lockedResult != null) && (lockedResult != expectedResult)) {
return null
}
lockedResult = expectedResult
} else {
val isNotConstant = CallMatcher.anyOf(
EXTENSION_POINTS,
MORE_EXTENSION_POINTS,
AbstractAssertJInspection.IS_EQUAL_TO_BOOLEAN,
AbstractAssertJInspection.IS_EQUAL_TO_OBJECT,
AbstractAssertJInspection.IS_NOT_EQUAL_TO_BOOLEAN,
AbstractAssertJInspection.IS_NOT_EQUAL_TO_OBJECT
).test(methodCall)
if (isNotConstant) {
return null
}
}
}
return lockedResult
} }
@@ -4,6 +4,7 @@ import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiExpression import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.search.GlobalSearchScope
fun createAssertThat(context: PsiElement, actualExpression: PsiExpression): PsiMethodCallExpression { fun createAssertThat(context: PsiElement, actualExpression: PsiExpression): PsiMethodCallExpression {
return createAssertThat(context, AssertJClassNames.ASSERTIONS_CLASSNAME, actualExpression) return createAssertThat(context, AssertJClassNames.ASSERTIONS_CLASSNAME, actualExpression)
@@ -29,4 +30,11 @@ fun createMethodCall(context: PsiElement, fullQualifiedMethodName: String, varar
) as PsiMethodCallExpression ) as PsiMethodCallExpression
arguments.forEachIndexed { index, newArg -> expectedExpression.getArg(index).replace(newArg) } arguments.forEachIndexed { index, newArg -> expectedExpression.getArg(index).replace(newArg) }
return expectedExpression return expectedExpression
}
fun hasAssertJMethod(element: PsiElement, classname: String, methodname: String): Boolean {
val findClass =
JavaPsiFacade.getInstance(element.project).findClass(classname, GlobalSearchScope.allScope(element.project))
?: return false
return findClass.allMethods.any { it.name == methodname }
} }
@@ -11,8 +11,19 @@ class MethodNames {
@NonNls @NonNls
const val ASSERT_THAT = "assertThat" const val ASSERT_THAT = "assertThat"
@NonNls
const val ASSUME_THAT = "assumeThat"
@NonNls @NonNls
const val AS = "as" const val AS = "as"
@NonNls
const val DESCRIBED_AS = "describedAs"
@NonNls
const val IN_HEXADECIMAL = "inHexadecimal"
@NonNls
const val IN_BINARY = "inBinary"
@NonNls @NonNls
const val IS_EQUAL_TO = "isEqualTo" const val IS_EQUAL_TO = "isEqualTo"
@NonNls @NonNls
@@ -38,7 +49,7 @@ class MethodNames {
@NonNls @NonNls
const val IS_FALSE = "isFalse" const val IS_FALSE = "isFalse"
@NonNls @NonNls
const val IS_NULL = "isNull" const val IS_NULL = "isNull" // terminal, returns void
@NonNls @NonNls
const val IS_NOT_NULL = "isNotNull" const val IS_NOT_NULL = "isNotNull"
@NonNls @NonNls
@@ -51,7 +62,7 @@ class MethodNames {
const val IS_NOT_INSTANCE_OF = "isNotInstanceOf" const val IS_NOT_INSTANCE_OF = "isNotInstanceOf"
@NonNls @NonNls
const val IS_EMPTY = "isEmpty" const val IS_EMPTY = "isEmpty" // terminal, returns void
@NonNls @NonNls
const val IS_NOT_EMPTY = "isNotEmpty" const val IS_NOT_EMPTY = "isNotEmpty"
@NonNls @NonNls
@@ -73,6 +84,16 @@ class MethodNames {
@NonNls @NonNls
const val CONTAINS_EXACTLY = "containsExactly" const val CONTAINS_EXACTLY = "containsExactly"
@NonNls @NonNls
const val CONTAINS_ALL = "containsAll"
@NonNls
const val CONTAINS_KEY = "containsKey"
@NonNls
const val DOES_NOT_CONTAIN_KEY = "doesNotContainKey"
@NonNls
const val CONTAINS_VALUE = "containsValue"
@NonNls
const val DOES_NOT_CONTAIN_VALUE = "doesNotContainValue"
@NonNls
const val IS_EQUAL_TO_IC = "isEqualToIgnoringCase" const val IS_EQUAL_TO_IC = "isEqualToIgnoringCase"
@NonNls @NonNls
const val IS_NOT_EQUAL_TO_IC = "isNotEqualToIgnoringCase" const val IS_NOT_EQUAL_TO_IC = "isNotEqualToIgnoringCase"
@@ -3,6 +3,7 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool
import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.util.TextRange
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
@@ -14,10 +15,10 @@ import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_C
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_ENUMERABLE_ASSERT_CLASSNAME import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_ENUMERABLE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_INTEGER_ASSERT_CLASSNAME 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.ASSERTIONS_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ASSERT_INTERFACE
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.GUAVA_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.AssertJClassNames.Companion.GUAVA_OPTIONAL_CLASSNAME
import de.platon42.intellij.plugins.cajon.MethodNames 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.qualifierExpression
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix
@@ -28,8 +29,9 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
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()" const val REPLACE_DESCRIPTION_TEMPLATE = "Replace %s() with %s()"
const val REMOVE_EXPECTED_OUTMOST_DESCRIPTION_TEMPLATE = "Remove unwrapping of expected expression and replace %s() with %s()" const val REMOVE_EXPECTED_OUTMOST_DESCRIPTION_TEMPLATE = "Unwrap expected expression and replace %s() with %s()"
const val UNWRAP_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE = "Unwrap actual expression and replace %s() with %s()" const val MOVE_ACTUAL_EXPRESSION_DESCRIPTION_TEMPLATE = "Remove %s() of actual expression and use assertThat().%s() instead"
const val MOVING_OUT_MESSAGE_TEMPLATE = "Moving %s() expression out of assertThat() would be more concise"
val TOKEN_TO_ASSERTJ_FOR_PRIMITIVE_MAP = mapOf<IElementType, String>( val TOKEN_TO_ASSERTJ_FOR_PRIMITIVE_MAP = mapOf<IElementType, String>(
JavaTokenType.EQEQ to MethodNames.IS_EQUAL_TO, JavaTokenType.EQEQ to MethodNames.IS_EQUAL_TO,
@@ -74,21 +76,21 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
val ASSERT_THAT_JAVA8_OPTIONAL = CallMatcher.staticCall(ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT) val ASSERT_THAT_JAVA8_OPTIONAL = CallMatcher.staticCall(ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)
.parameterTypes(CommonClassNames.JAVA_UTIL_OPTIONAL)!! .parameterTypes(CommonClassNames.JAVA_UTIL_OPTIONAL)!!
val ASSERT_THAT_GUAVA_OPTIONAL = CallMatcher.staticCall(GUAVA_ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT) val GUAVA_ASSERT_THAT_ANY = CallMatcher.staticCall(GUAVA_ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)
.parameterTypes(GUAVA_OPTIONAL_CLASSNAME)!! .parameterCount(1)!!
val IS_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO) val IS_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ASSERT_INTERFACE, MethodNames.IS_EQUAL_TO)
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!! .parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val IS_NOT_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO) val IS_NOT_EQUAL_TO_OBJECT = CallMatcher.instanceCall(ASSERT_INTERFACE, MethodNames.IS_NOT_EQUAL_TO)
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!! .parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val IS_EQUAL_TO_BOOLEAN = CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO) val IS_EQUAL_TO_BOOLEAN = CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO)
.parameterTypes("boolean")!! .parameterTypes("boolean")!!
val IS_NOT_EQUAL_TO_BOOLEAN = val IS_NOT_EQUAL_TO_BOOLEAN =
CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO) CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO)
.parameterTypes("boolean")!! .parameterTypes("boolean")!!
val IS_SAME_AS_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, MethodNames.IS_SAME_AS) val IS_SAME_AS_OBJECT = CallMatcher.instanceCall(ASSERT_INTERFACE, MethodNames.IS_SAME_AS)
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!! .parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val IS_NOT_SAME_AS_OBJECT = CallMatcher.instanceCall(ABSTRACT_ASSERT_CLASSNAME, MethodNames.IS_NOT_SAME_AS) val IS_NOT_SAME_AS_OBJECT = CallMatcher.instanceCall(ASSERT_INTERFACE, MethodNames.IS_NOT_SAME_AS)
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!! .parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val HAS_SIZE = CallMatcher.instanceCall(ABSTRACT_ENUMERABLE_ASSERT_CLASSNAME, MethodNames.HAS_SIZE) val HAS_SIZE = CallMatcher.instanceCall(ABSTRACT_ENUMERABLE_ASSERT_CLASSNAME, MethodNames.HAS_SIZE)
@@ -174,7 +176,22 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
val description = REPLACE_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod) val description = REPLACE_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod)
val message = SIMPLIFY_MESSAGE_TEMPLATE.format(originalMethod, replacementMethod) val message = SIMPLIFY_MESSAGE_TEMPLATE.format(originalMethod, replacementMethod)
val quickFix = ReplaceSimpleMethodCallQuickFix(description, replacementMethod) val quickFix = ReplaceSimpleMethodCallQuickFix(description, replacementMethod)
holder.registerProblem(expression, message, quickFix) val textRange = TextRange(expression.qualifierExpression.textLength, expression.textLength)
holder.registerProblem(expression, textRange, message, quickFix)
}
protected fun registerMoveOutMethod(
holder: ProblemsHolder,
expression: PsiMethodCallExpression,
oldActualExpression: PsiMethodCallExpression,
replacementMethod: String,
quickFixSupplier: (String, String) -> LocalQuickFix
) {
val originalMethod = getOriginalMethodName(oldActualExpression) ?: return
val description = MOVE_ACTUAL_EXPRESSION_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod)
val message = MOVING_OUT_MESSAGE_TEMPLATE.format(originalMethod)
val quickfix = quickFixSupplier(description, replacementMethod)
holder.registerProblem(expression, message, quickfix)
} }
protected fun registerReplaceMethod( protected fun registerReplaceMethod(
@@ -199,7 +216,8 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
val description = descriptionTemplate.format(originalMethod, replacementMethod) val description = descriptionTemplate.format(originalMethod, replacementMethod)
val message = MORE_CONCISE_MESSAGE_TEMPLATE.format(replacementMethod, originalMethod) val message = MORE_CONCISE_MESSAGE_TEMPLATE.format(replacementMethod, originalMethod)
val quickfix = quickFixSupplier(description, replacementMethod) val quickfix = quickFixSupplier(description, replacementMethod)
holder.registerProblem(expression, message, quickfix) val textRange = TextRange(expression.qualifierExpression.textLength, expression.textLength)
holder.registerProblem(expression, textRange, message, quickfix)
} }
protected fun registerRemoveExpectedOutmostMethod( protected fun registerRemoveExpectedOutmostMethod(
@@ -211,55 +229,4 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
) { ) {
registerConciseMethod(REMOVE_EXPECTED_OUTMOST_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod, quickFixSupplier) registerConciseMethod(REMOVE_EXPECTED_OUTMOST_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod, quickFixSupplier)
} }
protected fun registerRemoveActualOutmostMethod(
holder: ProblemsHolder,
expression: PsiMethodCallExpression,
oldExpectedCallExpression: PsiMethodCallExpression,
replacementMethod: String,
quickFixSupplier: (String, String) -> LocalQuickFix
) {
registerConciseMethod(UNWRAP_ACTUAL_OUTMOST_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod, quickFixSupplier)
}
protected fun calculateConstantParameterValue(expression: PsiMethodCallExpression, argIndex: Int): Any? {
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)
if (value == null) {
val field = (valueExpression as? PsiReferenceExpression)?.resolve() as? PsiField
if (field?.containingClass?.qualifiedName == CommonClassNames.JAVA_LANG_BOOLEAN) {
return when (field.name) {
"TRUE" -> true
"FALSE" -> false
else -> null
}
}
}
return value
}
protected fun getExpectedBooleanResult(expectedCallExpression: PsiMethodCallExpression): Boolean? {
val isTrue = IS_TRUE.test(expectedCallExpression)
val isFalse = IS_FALSE.test(expectedCallExpression)
if (isTrue || isFalse) {
return isTrue
} else {
val isEqualTo = IS_EQUAL_TO_BOOLEAN.test(expectedCallExpression) || IS_EQUAL_TO_OBJECT.test(expectedCallExpression)
val isNotEqualTo = IS_NOT_EQUAL_TO_BOOLEAN.test(expectedCallExpression) || IS_NOT_EQUAL_TO_OBJECT.test(expectedCallExpression)
if (isEqualTo || isNotEqualTo) {
val constValue = calculateConstantParameterValue(expectedCallExpression, 0) as? Boolean ?: return null
return isNotEqualTo xor constValue
}
}
return null
}
protected fun hasAssertJMethod(element: PsiElement, classname: String, methodname: String): Boolean {
val findClass =
JavaPsiFacade.getInstance(element.project).findClass(classname, GlobalSearchScope.allScope(element.project))
?: return false
return findClass.allMethods.any { it.name == methodname }
}
} }
@@ -7,10 +7,6 @@ import org.jetbrains.annotations.NonNls
open class AbstractJUnitAssertInspection : AbstractBaseJavaLocalInspectionTool() { open class AbstractJUnitAssertInspection : AbstractBaseJavaLocalInspectionTool() {
companion object { companion object {
const val CONVERT_MESSAGE_TEMPLATE = "%s can be converted to AssertJ style"
const val REPLACE_DESCRIPTION_TEMPLATE = "Replace %s() with assertThat().%s()"
@NonNls @NonNls
const val JUNIT_ASSERT_CLASSNAME = "org.junit.Assert" const val JUNIT_ASSERT_CLASSNAME = "org.junit.Assert"
@@ -4,11 +4,8 @@ import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
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.MethodNames import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
import de.platon42.intellij.plugins.cajon.quickfixes.MoveActualOuterExpressionMethodCallQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.SplitBinaryExpressionMethodCallQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.SplitBinaryExpressionMethodCallQuickFix
class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() { class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
@@ -23,19 +20,23 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitMethodCallExpression(expression) super.visitExpressionStatement(statement)
if (!ASSERT_THAT_BOOLEAN.test(expression)) { if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return return
} }
val expectedCallExpression = expression.findOutmostMethodCall() ?: return val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val expectedResult = getExpectedBooleanResult(expectedCallExpression) ?: return val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
val assertThatArgument = expression.firstArg val assertThatArgument = staticMethodCall.firstArg
if (assertThatArgument is PsiMethodCallExpression && OBJECT_EQUALS.test(assertThatArgument)) { if (assertThatArgument is PsiMethodCallExpression && OBJECT_EQUALS.test(assertThatArgument)) {
val replacementMethod = expectedResult.map(MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO) val replacementMethod = expectedResult.map(MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO)
registerSplitMethod(holder, expression, "${MethodNames.EQUALS}()", replacementMethod, ::MoveActualOuterExpressionMethodCallQuickFix) registerSplitMethod(holder, expectedCallExpression, "${MethodNames.EQUALS}()", replacementMethod, ::MoveOutMethodCallExpressionQuickFix)
return return
} }
@@ -50,7 +51,7 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
return return
} else if (isLeftNull || isRightNull) { } else if (isLeftNull || isRightNull) {
val replacementMethod = expectedResult.map(MethodNames.IS_NULL, MethodNames.IS_NOT_NULL) val replacementMethod = expectedResult.map(MethodNames.IS_NULL, MethodNames.IS_NOT_NULL)
registerSplitMethod(holder, expression, "binary", replacementMethod) { desc, method -> registerSplitMethod(holder, expectedCallExpression, "binary", replacementMethod) { desc, method ->
SplitBinaryExpressionMethodCallQuickFix(desc, method, pickRightOperand = isLeftNull, noExpectedExpression = true) SplitBinaryExpressionMethodCallQuickFix(desc, method, pickRightOperand = isLeftNull, noExpectedExpression = true)
} }
return return
@@ -58,7 +59,7 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
val isPrimitive = bothTypes.all(TypeConversionUtil::isPrimitiveAndNotNull) val isPrimitive = bothTypes.all(TypeConversionUtil::isPrimitiveAndNotNull)
val isNumericType = bothTypes.all(TypeConversionUtil::isNumericType) val isNumericType = bothTypes.all(TypeConversionUtil::isNumericType)
val constantEvaluationHelper = JavaPsiFacade.getInstance(expression.project).constantEvaluationHelper val constantEvaluationHelper = JavaPsiFacade.getInstance(statement.project).constantEvaluationHelper
val swapExpectedAndActual = constantEvaluationHelper.computeConstantExpression(binaryExpression.lOperand) != null val swapExpectedAndActual = constantEvaluationHelper.computeConstantExpression(binaryExpression.lOperand) != null
val tokenType = binaryExpression.operationTokenType val tokenType = binaryExpression.operationTokenType
@@ -72,7 +73,7 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
(isPrimitive || isNumericType).map(TOKEN_TO_ASSERTJ_FOR_PRIMITIVE_MAP, TOKEN_TO_ASSERTJ_FOR_OBJECT_MAPPINGS) (isPrimitive || isNumericType).map(TOKEN_TO_ASSERTJ_FOR_PRIMITIVE_MAP, TOKEN_TO_ASSERTJ_FOR_OBJECT_MAPPINGS)
val replacementMethod = mappingToUse[tokenType] ?: return val replacementMethod = mappingToUse[tokenType] ?: return
registerSplitMethod(holder, expression, "binary", replacementMethod) { desc, method -> registerSplitMethod(holder, expectedCallExpression, "binary", replacementMethod) { desc, method ->
SplitBinaryExpressionMethodCallQuickFix(desc, method, pickRightOperand = swapExpectedAndActual) SplitBinaryExpressionMethodCallQuickFix(desc, method, pickRightOperand = swapExpectedAndActual)
} }
} }
@@ -5,10 +5,8 @@ import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.util.TypeConversionUtil import com.intellij.psi.util.TypeConversionUtil
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_BOOLEAN_ASSERT_CLASSNAME import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_BOOLEAN_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
class AssertThatBooleanConditionInspection : AbstractAssertJInspection() { class AssertThatBooleanConditionInspection : AbstractAssertJInspection() {
@@ -22,6 +20,9 @@ class AssertThatBooleanConditionInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression) super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val matchingCalls = listOf( val matchingCalls = listOf(
IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_BOOLEAN, IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_BOOLEAN,
IS_NOT_EQUAL_TO_OBJECT, IS_NOT_EQUAL_TO_BOOLEAN IS_NOT_EQUAL_TO_OBJECT, IS_NOT_EQUAL_TO_BOOLEAN
@@ -37,7 +38,7 @@ class AssertThatBooleanConditionInspection : AbstractAssertJInspection() {
if (!TypeConversionUtil.isBooleanType(expectedExpression.type)) { if (!TypeConversionUtil.isBooleanType(expectedExpression.type)) {
return return
} }
val expectedResult = calculateConstantParameterValue(expression, 0) as? Boolean ?: return val expectedResult = expression.calculateConstantParameterValue(0) as? Boolean ?: return
val flippedBooleanTest = matchingCalls.drop(2).any { it } val flippedBooleanTest = matchingCalls.drop(2).any { it }
val replacementMethod = (expectedResult xor flippedBooleanTest).map(MethodNames.IS_TRUE, MethodNames.IS_FALSE) val replacementMethod = (expectedResult xor flippedBooleanTest).map(MethodNames.IS_TRUE, MethodNames.IS_FALSE)
@@ -0,0 +1,71 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.*
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
class AssertThatCollectionOrMapExpressionInspection : AbstractAssertJInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting a collection or map specific expression"
private val MAPPINGS = listOf(
Mapping(
CallMatcher.anyOf(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "isEmpty").parameterCount(0),
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "isEmpty").parameterCount(0)
),
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "contains").parameterCount(1),
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "containsAll").parameterCount(1),
MethodNames.CONTAINS_ALL, null
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "containsKey").parameterCount(1),
MethodNames.CONTAINS_KEY, MethodNames.DOES_NOT_CONTAIN_KEY
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "containsValue").parameterCount(1),
MethodNames.CONTAINS_VALUE, MethodNames.DOES_NOT_CONTAIN_VALUE
)
)
}
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val mapping = MAPPINGS.firstOrNull { it.callMatcher.test(assertThatArgument) } ?: return
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
val replacementMethod = if (expectedResult) mapping.replacementForTrue else mapping.replacementForFalse ?: return
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod, ::MoveOutMethodCallExpressionQuickFix)
}
}
}
private class Mapping(
val callMatcher: CallMatcher,
val replacementForTrue: String,
val replacementForFalse: String?
)
}
@@ -4,7 +4,10 @@ import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiStatement
import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue
import de.platon42.intellij.plugins.cajon.hasAssertThat
class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() { class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
@@ -18,11 +21,15 @@ class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression) super.visitMethodCallExpression(expression)
if (!HAS_SIZE.test(expression)) { if (!expression.hasAssertThat()) {
return
}
val isLastExpression = expression.parent is PsiStatement
if (!(HAS_SIZE.test(expression) && isLastExpression)) {
return return
} }
val value = calculateConstantParameterValue(expression, 0) ?: return val value = expression.calculateConstantParameterValue(0) ?: return
if (value == 0) { if (value == 0) {
registerSimplifyMethod(holder, expression, MethodNames.IS_EMPTY) registerSimplifyMethod(holder, expression, MethodNames.IS_EMPTY)
} }
@@ -1,10 +1,8 @@
package de.platon42.intellij.plugins.cajon.inspections package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor import com.intellij.openapi.util.TextRange
import com.intellij.psi.JavaPsiFacade import com.intellij.psi.*
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.siyeh.ig.callMatcher.CallMatcher import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.* import de.platon42.intellij.plugins.cajon.*
@@ -15,97 +13,88 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Asserting an Optional (Guava)" private const val DISPLAY_NAME = "Asserting an Optional (Guava)"
private const val REPLACE_GUAVA_DESCRIPTION_TEMPLATE = "Replace %s() with Guava assertThat().%s()" private const val REPLACE_GUAVA_DESCRIPTION_TEMPLATE = "Replace %s() with Guava assertThat().%s()"
private const val REMOVE_EXPECTED_OUTMOST_GUAVA_DESCRIPTION_TEMPLATE = "Remove unwrapping of expected expression and replace %s() with Guava assertThat().%s()"
private const val REMOVE_ACTUAL_OUTMOST_GUAVA_DESCRIPTION_TEMPLATE = "Unwrap actual expression and replace %s() with Guava assertThat().%s()"
} }
override fun getDisplayName() = DISPLAY_NAME override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitMethodCallExpression(expression) super.visitExpressionStatement(statement)
JavaPsiFacade.getInstance(expression.project) if (!statement.hasAssertThat()) {
.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 return
} }
val expectedCallExpression = expression.findOutmostMethodCall() ?: return val staticMethodCall = statement.findStaticMethodCall() ?: return
val isEqualTo = IS_EQUAL_TO_OBJECT.test(expectedCallExpression) if (!checkPreconditions(staticMethodCall)) {
val isNotEqualTo = IS_NOT_EQUAL_TO_OBJECT.test(expectedCallExpression) return
if (assertThatGuava) { }
if (isEqualTo) { val actualExpression = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
if (CallMatcher.anyOf(GUAVA_OPTIONAL_OF, GUAVA_OPTIONAL_FROM_NULLABLE).test(innerExpectedCall)) { val outmostMethodCall = statement.findOutmostMethodCall() ?: return
registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::UnwrapExpectedStaticMethodCallQuickFix) if (GUAVA_OPTIONAL_GET.test(actualExpression)) {
} else if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) { val expectedCallExpression = staticMethodCall.gatherAssertionCalls().singleOrNull() ?: return
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_ABSENT) if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) {
} registerMoveOutMethod(holder, outmostMethodCall, actualExpression, MethodNames.CONTAINS) { desc, method ->
} else if (isNotEqualTo) { QuickFixWithPostfixDelegate(
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return RemoveActualOutmostMethodCallQuickFix(desc, method),
if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) { ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_PRESENT) )
} }
} }
} else { } else if (GUAVA_OPTIONAL_IS_PRESENT.test(actualExpression)) {
// we're not calling an assertThat() from Guava, but a core-AssertJ one! val expectedPresence = outmostMethodCall.getAllTheSameExpectedBooleanConstants() ?: return
// We need to replace that by the Guava one, if we want to apply a formally correct fix. val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_ABSENT)
val actualExpression = expression.firstArg as? PsiMethodCallExpression registerMoveOutMethod(holder, outmostMethodCall, actualExpression, replacementMethod) { desc, method ->
if (actualExpression != null) { QuickFixWithPostfixDelegate(
if (GUAVA_OPTIONAL_GET.test(actualExpression) && isEqualTo) { MoveOutMethodCallExpressionQuickFix(desc, method),
registerRemoveActualOutmostForGuavaMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
} else if (GUAVA_OPTIONAL_IS_PRESENT.test(actualExpression)) { )
val expectedPresence = getExpectedBooleanResult(expectedCallExpression) ?: return
val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_ABSENT)
registerRemoveActualOutmostForGuavaMethod(holder, expression, expectedCallExpression, replacementMethod, noExpectedExpression = true)
}
}
if (isEqualTo) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
if (CallMatcher.anyOf(GUAVA_OPTIONAL_OF, GUAVA_OPTIONAL_FROM_NULLABLE).test(innerExpectedCall)) {
registerRemoveExpectedOutmostGuavaMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS)
} else if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) {
registerSimplifyForGuavaMethod(holder, expectedCallExpression, MethodNames.IS_ABSENT)
}
} else if (isNotEqualTo) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return
if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) {
registerSimplifyForGuavaMethod(holder, expectedCallExpression, MethodNames.IS_PRESENT)
}
} }
} }
} }
}
}
private fun registerRemoveExpectedOutmostGuavaMethod( override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
holder: ProblemsHolder, super.visitMethodCallExpression(expression)
expression: PsiMethodCallExpression, if (!expression.hasAssertThat()) {
oldExpectedCallExpression: PsiMethodCallExpression, return
replacementMethod: String }
) { val staticMethodCall = expression.findStaticMethodCall() ?: return
registerConciseMethod(REMOVE_EXPECTED_OUTMOST_GUAVA_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod) { desc, method -> if (!checkPreconditions(staticMethodCall)) {
QuickFixWithPostfixDelegate( return
UnwrapExpectedStaticMethodCallQuickFix(desc, method), }
ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT // We're not calling an assertThat() from Guava, but a core-AssertJ one!
) // We need to replace that by the Guava one, if we want to apply a formally correct fix.
} if (IS_EQUAL_TO_OBJECT.test(expression)) {
} val innerExpectedCall = expression.firstArg as? PsiMethodCallExpression ?: return
if (CallMatcher.anyOf(GUAVA_OPTIONAL_OF, GUAVA_OPTIONAL_FROM_NULLABLE).test(innerExpectedCall)) {
registerRemoveExpectedOutmostMethod(holder, expression, expression, MethodNames.CONTAINS) { desc, method ->
QuickFixWithPostfixDelegate(
UnwrapExpectedStaticMethodCallQuickFix(desc, method),
ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
)
}
} else if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) {
registerSimplifyForGuavaMethod(holder, expression, MethodNames.IS_ABSENT)
}
} else if (IS_NOT_EQUAL_TO_OBJECT.test(expression)) {
val innerExpectedCall = expression.firstArg as? PsiMethodCallExpression ?: return
if (GUAVA_OPTIONAL_ABSENT.test(innerExpectedCall)) {
registerSimplifyForGuavaMethod(holder, expression, MethodNames.IS_PRESENT)
}
}
}
private fun registerRemoveActualOutmostForGuavaMethod( private fun checkPreconditions(staticMethodCall: PsiMethodCallExpression): Boolean {
holder: ProblemsHolder, val assertThatGuava = GUAVA_ASSERT_THAT_ANY.test(staticMethodCall)
expression: PsiMethodCallExpression,
oldExpectedCallExpression: PsiMethodCallExpression, if (ASSERT_THAT_ANY.test(staticMethodCall) || assertThatGuava) {
replacementMethod: String, JavaPsiFacade.getInstance(staticMethodCall.project)
noExpectedExpression: Boolean = false .findClass(AssertJClassNames.GUAVA_ASSERTIONS_CLASSNAME, GlobalSearchScope.allScope(staticMethodCall.project)) ?: return false
) { return true
registerConciseMethod(REMOVE_ACTUAL_OUTMOST_GUAVA_DESCRIPTION_TEMPLATE, holder, expression, oldExpectedCallExpression, replacementMethod) { desc, method -> }
QuickFixWithPostfixDelegate( return false
RemoveActualOutmostMethodCallQuickFix(desc, method, noExpectedExpression), }
ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
)
} }
} }
@@ -117,6 +106,7 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
ReplaceSimpleMethodCallQuickFix(description, replacementMethod), ReplaceSimpleMethodCallQuickFix(description, replacementMethod),
ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT ForGuavaPostFix.REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT
) )
holder.registerProblem(expression, message, quickFix) val textRange = TextRange(expression.qualifierExpression.textLength, expression.textLength)
holder.registerProblem(expression, textRange, message, quickFix)
} }
} }
@@ -2,21 +2,15 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor import com.intellij.psi.*
import com.intellij.psi.PsiElementVisitor import de.platon42.intellij.plugins.cajon.*
import com.intellij.psi.PsiInstanceOfExpression import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutInstanceOfExpressionQuickFix
import com.intellij.psi.PsiMethodCallExpression
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
import de.platon42.intellij.plugins.cajon.quickfixes.RemoveInstanceOfExpressionQuickFix
class AssertThatInstanceOfInspection : AbstractAssertJInspection() { class AssertThatInstanceOfInspection : AbstractAssertJInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Asserting a class instance" private const val DISPLAY_NAME = "Asserting a class instance"
private const val REPLACE_INSTANCEOF_DESCRIPTION_TEMPLATE = "Replace instanceof expression by assertThat().%s()" private const val REMOVE_INSTANCEOF_DESCRIPTION_TEMPLATE = "Remove instanceof in actual expression and use assertThat().%s() instead"
private const val MOVE_OUT_INSTANCEOF_MESSAGE = "instanceof expression could be moved out of assertThat()" private const val MOVE_OUT_INSTANCEOF_MESSAGE = "instanceof expression could be moved out of assertThat()"
} }
@@ -24,30 +18,34 @@ class AssertThatInstanceOfInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitMethodCallExpression(expression) super.visitExpressionStatement(statement)
if (!ASSERT_THAT_BOOLEAN.test(expression)) { if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return return
} }
val expectedCallExpression = expression.findOutmostMethodCall() ?: return val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val expectedResult = getExpectedBooleanResult(expectedCallExpression) ?: return val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
if (expression.firstArg is PsiInstanceOfExpression) { if (staticMethodCall.firstArg is PsiInstanceOfExpression) {
val replacementMethod = expectedResult.map(MethodNames.IS_INSTANCE_OF, MethodNames.IS_NOT_INSTANCE_OF) val replacementMethod = expectedResult.map(MethodNames.IS_INSTANCE_OF, MethodNames.IS_NOT_INSTANCE_OF)
registerRemoveInstanceOfMethod(holder, expression, replacementMethod, ::RemoveInstanceOfExpressionQuickFix) registerMoveOutInstanceOfMethod(holder, expectedCallExpression, replacementMethod, ::MoveOutInstanceOfExpressionQuickFix)
} }
} }
} }
} }
private fun registerRemoveInstanceOfMethod( private fun registerMoveOutInstanceOfMethod(
holder: ProblemsHolder, holder: ProblemsHolder,
expression: PsiMethodCallExpression, expression: PsiMethodCallExpression,
replacementMethod: String, replacementMethod: String,
quickFixSupplier: (String, String) -> LocalQuickFix quickFixSupplier: (String, String) -> LocalQuickFix
) { ) {
val description = REPLACE_INSTANCEOF_DESCRIPTION_TEMPLATE.format(replacementMethod) val description = REMOVE_INSTANCEOF_DESCRIPTION_TEMPLATE.format(replacementMethod)
val quickfix = quickFixSupplier(description, replacementMethod) val quickfix = quickFixSupplier(description, replacementMethod)
holder.registerProblem(expression, MOVE_OUT_INSTANCEOF_MESSAGE, quickfix) holder.registerProblem(expression, MOVE_OUT_INSTANCEOF_MESSAGE, quickfix)
} }
@@ -1,19 +1,14 @@
package de.platon42.intellij.plugins.cajon.inspections package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.* import com.intellij.psi.*
import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall import de.platon42.intellij.plugins.cajon.quickfixes.InvertUnaryStatementQuickFix
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
import de.platon42.intellij.plugins.cajon.quickfixes.RemoveUnaryExpressionQuickFix
class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection() { class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Asserting an inverted boolean condition" private const val DISPLAY_NAME = "Asserting an inverted boolean condition"
private const val INVERT_CONDITION_DESCRIPTION = "Invert condition in assertThat()"
private const val INVERT_CONDITION_MESSAGE = "Condition inside assertThat() could be inverted" private const val INVERT_CONDITION_MESSAGE = "Condition inside assertThat() could be inverted"
} }
@@ -23,29 +18,21 @@ class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection()
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression) super.visitMethodCallExpression(expression)
if (!ASSERT_THAT_BOOLEAN.test(expression)) { if (!expression.hasAssertThat()) {
return return
} }
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
expression.getExpectedBooleanResult() ?: return
val expectedCallExpression = expression.findOutmostMethodCall() ?: return val prefixExpression = staticMethodCall.firstArg as? PsiPrefixExpression ?: return
val expectedResult = getExpectedBooleanResult(expectedCallExpression) ?: return
val prefixExpression = expression.firstArg as? PsiPrefixExpression ?: return
if (prefixExpression.operationTokenType == JavaTokenType.EXCL) { if (prefixExpression.operationTokenType == JavaTokenType.EXCL) {
val replacementMethod = expectedResult.map(MethodNames.IS_FALSE, MethodNames.IS_TRUE) val outmostMethodCall = expression.findOutmostMethodCall() ?: return
registerInvertMethod(holder, expression, replacementMethod, ::RemoveUnaryExpressionQuickFix) holder.registerProblem(outmostMethodCall, INVERT_CONDITION_MESSAGE, InvertUnaryStatementQuickFix())
} }
} }
} }
} }
private fun registerInvertMethod(
holder: ProblemsHolder,
expression: PsiMethodCallExpression,
replacementMethod: String,
quickFixSupplier: (String, String) -> LocalQuickFix
) {
val quickfix = quickFixSupplier(INVERT_CONDITION_DESCRIPTION, replacementMethod)
holder.registerProblem(expression, INVERT_CONDITION_MESSAGE, quickfix)
}
} }
@@ -3,12 +3,11 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiExpressionStatement
import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiMethodCallExpression
import com.siyeh.ig.callMatcher.CallMatcher import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.map
import de.platon42.intellij.plugins.cajon.quickfixes.RemoveActualOutmostMethodCallQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.RemoveActualOutmostMethodCallQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.UnwrapExpectedStaticMethodCallQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.UnwrapExpectedStaticMethodCallQuickFix
@@ -22,46 +21,58 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitMethodCallExpression(expression) super.visitExpressionStatement(statement)
if (!ASSERT_THAT_ANY.test(expression)) { if (!statement.hasAssertThat()) {
return return
} }
val expectedCallExpression = expression.findOutmostMethodCall() ?: return val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_ANY.test(staticMethodCall)) {
return
}
val actualExpression = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
if (ASSERT_THAT_JAVA8_OPTIONAL.test(expression)) { val outmostMethodCall = statement.findOutmostMethodCall() ?: return
if (OPTIONAL_GET.test(actualExpression)) {
val expectedCallExpression = staticMethodCall.gatherAssertionCalls().singleOrNull() ?: return
if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) { if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return registerMoveOutMethod(holder, outmostMethodCall, actualExpression, MethodNames.CONTAINS) { desc, method ->
if (CallMatcher.anyOf(OPTIONAL_OF, OPTIONAL_OF_NULLABLE).test(innerExpectedCall)) { RemoveActualOutmostMethodCallQuickFix(desc, method)
registerRemoveExpectedOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS, ::UnwrapExpectedStaticMethodCallQuickFix)
} else if (OPTIONAL_EMPTY.test(innerExpectedCall)) {
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_NOT_PRESENT)
} }
} else if (IS_NOT_EQUAL_TO_OBJECT.test(expectedCallExpression)) { } else if (IS_SAME_AS_OBJECT.test(expectedCallExpression)) {
val innerExpectedCall = expectedCallExpression.firstArg as? PsiMethodCallExpression ?: return registerMoveOutMethod(holder, outmostMethodCall, actualExpression, MethodNames.CONTAINS_SAME) { desc, method ->
if (OPTIONAL_EMPTY.test(innerExpectedCall)) { RemoveActualOutmostMethodCallQuickFix(desc, method)
registerSimplifyMethod(holder, expectedCallExpression, MethodNames.IS_PRESENT)
} }
} }
} else { } else if (OPTIONAL_IS_PRESENT.test(actualExpression)) {
val actualExpression = expression.firstArg as? PsiMethodCallExpression ?: return val expectedPresence = outmostMethodCall.getAllTheSameExpectedBooleanConstants() ?: return
val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_NOT_PRESENT)
registerMoveOutMethod(holder, outmostMethodCall, actualExpression, replacementMethod) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method)
}
}
}
if (OPTIONAL_GET.test(actualExpression)) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
if (IS_EQUAL_TO_OBJECT.test(expectedCallExpression)) { super.visitMethodCallExpression(expression)
registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS) { desc, method -> if (!expression.hasAssertThat()) {
RemoveActualOutmostMethodCallQuickFix(desc, method) return
} }
} else if (IS_SAME_AS_OBJECT.test(expectedCallExpression)) { val staticMethodCall = expression.findStaticMethodCall() ?: return
registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, MethodNames.CONTAINS_SAME) { desc, method -> if (!ASSERT_THAT_JAVA8_OPTIONAL.test(staticMethodCall)) {
RemoveActualOutmostMethodCallQuickFix(desc, method) return
} }
} if (IS_EQUAL_TO_OBJECT.test(expression)) {
} else if (OPTIONAL_IS_PRESENT.test(actualExpression)) { val innerExpectedCall = expression.firstArg as? PsiMethodCallExpression ?: return
val expectedPresence = getExpectedBooleanResult(expectedCallExpression) ?: return if (CallMatcher.anyOf(OPTIONAL_OF, OPTIONAL_OF_NULLABLE).test(innerExpectedCall)) {
val replacementMethod = expectedPresence.map(MethodNames.IS_PRESENT, MethodNames.IS_NOT_PRESENT) registerRemoveExpectedOutmostMethod(holder, expression, expression, MethodNames.CONTAINS, ::UnwrapExpectedStaticMethodCallQuickFix)
registerRemoveActualOutmostMethod(holder, expression, expectedCallExpression, replacementMethod) { desc, method -> } else if (OPTIONAL_EMPTY.test(innerExpectedCall)) {
RemoveActualOutmostMethodCallQuickFix(desc, method, noExpectedExpression = true) registerSimplifyMethod(holder, expression, MethodNames.IS_NOT_PRESENT)
} }
} else if (IS_NOT_EQUAL_TO_OBJECT.test(expression)) {
val innerExpectedCall = expression.firstArg as? PsiMethodCallExpression ?: return
if (OPTIONAL_EMPTY.test(innerExpectedCall)) {
registerSimplifyMethod(holder, expression, MethodNames.IS_PRESENT)
} }
} }
} }
@@ -1,12 +1,10 @@
package de.platon42.intellij.plugins.cajon.inspections package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor import com.intellij.psi.*
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiType
import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.firstArg import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.hasAssertThat
import de.platon42.intellij.plugins.cajon.map import de.platon42.intellij.plugins.cajon.map
class AssertThatObjectIsNullOrNotNullInspection : AbstractAssertJInspection() { class AssertThatObjectIsNullOrNotNullInspection : AbstractAssertJInspection() {
@@ -21,9 +19,13 @@ class AssertThatObjectIsNullOrNotNullInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression) super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val isNotEqualTo = IS_NOT_EQUAL_TO_OBJECT.test(expression) val isNotEqualTo = IS_NOT_EQUAL_TO_OBJECT.test(expression)
val isEqualTo = IS_EQUAL_TO_OBJECT.test(expression) val isEqualTo = IS_EQUAL_TO_OBJECT.test(expression)
if (!(isEqualTo || isNotEqualTo)) { val isLastExpression = expression.parent is PsiStatement
if (!((isEqualTo && isLastExpression) || isNotEqualTo)) {
return return
} }
@@ -2,10 +2,10 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.cajon.* import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_ITERABLE_ASSERT_CLASSNAME import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_ITERABLE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceHasSizeMethodCallQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSizeMethodCallQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSizeMethodCallQuickFix
class AssertThatSizeInspection : AbstractAssertJInspection() { class AssertThatSizeInspection : AbstractAssertJInspection() {
@@ -13,6 +13,7 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Asserting the size of an collection, array or string" private const val DISPLAY_NAME = "Asserting the size of an collection, array or string"
private const val REMOVE_SIZE_DESCRIPTION_TEMPLATE = "Remove size determination of expected expression and replace %s() with %s()" private const val REMOVE_SIZE_DESCRIPTION_TEMPLATE = "Remove size determination of expected expression and replace %s() with %s()"
private const val REMOVE_ALL_MESSAGE = "Try to operate on the iterable itself rather than its size"
private val BONUS_EXPRESSIONS_CALL_MATCHER_MAP = listOf( private val BONUS_EXPRESSIONS_CALL_MATCHER_MAP = listOf(
IS_LESS_THAN_INT to MethodNames.HAS_SIZE_LESS_THAN, IS_LESS_THAN_INT to MethodNames.HAS_SIZE_LESS_THAN,
@@ -20,90 +21,129 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
IS_GREATER_THAN_INT to MethodNames.HAS_SIZE_GREATER_THAN, IS_GREATER_THAN_INT to MethodNames.HAS_SIZE_GREATER_THAN,
IS_GREATER_THAN_OR_EQUAL_TO_INT to MethodNames.HAS_SIZE_GREATER_THAN_OR_EQUAL_TO IS_GREATER_THAN_OR_EQUAL_TO_INT to MethodNames.HAS_SIZE_GREATER_THAN_OR_EQUAL_TO
) )
private fun isCharSequenceLength(expression: PsiExpression) = (expression is PsiMethodCallExpression) && CHAR_SEQUENCE_LENGTH.test(expression)
private fun isCollectionSize(expression: PsiExpression) = (expression is PsiMethodCallExpression) && COLLECTION_SIZE.test(expression)
private fun isArrayLength(expression: PsiExpression): Boolean {
val psiReferenceExpression = expression as? PsiReferenceExpression ?: return false
return ((psiReferenceExpression.qualifierExpression?.type is PsiArrayType)
&& ((psiReferenceExpression.resolve() as? PsiField)?.name == "length"))
}
fun getMatch(expression: PsiMethodCallExpression, isForArrayOrCollection: Boolean, isForString: Boolean): Match? {
val isLastExpression = expression.parent is PsiStatement
val constValue = expression.calculateConstantParameterValue(0)
if (IS_EQUAL_TO_INT.test(expression)) {
return if ((constValue == 0) && isLastExpression) {
Match(expression, MethodNames.IS_EMPTY, noExpectedExpression = true)
} else {
val equalToExpression = expression.firstArg
if (isForArrayOrCollection && (isCollectionSize(equalToExpression) || isArrayLength(equalToExpression)) ||
isForString && (isCollectionSize(equalToExpression) || isArrayLength(equalToExpression) || isCharSequenceLength(equalToExpression))
) {
Match(expression, MethodNames.HAS_SAME_SIZE_AS, expectedIsCollection = true)
} else {
Match(expression, MethodNames.HAS_SIZE)
}
}
} else {
val isTestForEmpty = ((IS_LESS_THAN_OR_EQUAL_TO_INT.test(expression) && (constValue == 0))
|| (IS_LESS_THAN_INT.test(expression) && (constValue == 1))
|| IS_ZERO.test(expression))
val isTestForNotEmpty = ((IS_GREATER_THAN_INT.test(expression) && (constValue == 0))
|| (IS_GREATER_THAN_OR_EQUAL_TO_INT.test(expression) && (constValue == 1))
|| IS_NOT_ZERO.test(expression))
if ((isTestForEmpty && isLastExpression) || isTestForNotEmpty) {
val replacementMethod = isTestForEmpty.map(MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY)
return Match(expression, replacementMethod, noExpectedExpression = true)
} else if (hasAssertJMethod(expression, ABSTRACT_ITERABLE_ASSERT_CLASSNAME, MethodNames.HAS_SIZE_LESS_THAN)) {
// new stuff in AssertJ 13.2.0
val replacementMethod = BONUS_EXPRESSIONS_CALL_MATCHER_MAP.find { it.first.test(expression) }?.second ?: return null
return Match(expression, replacementMethod)
}
return null
}
}
} }
override fun getDisplayName() = DISPLAY_NAME override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_INT.test(staticMethodCall)) {
return
}
val actualExpression = staticMethodCall.firstArg
val isForArrayOrCollection = isArrayLength(actualExpression) || isCollectionSize(actualExpression)
val isForString = isCharSequenceLength(actualExpression)
if (!(isForArrayOrCollection || isForString)) {
return
}
val matches = staticMethodCall.collectMethodCallsUpToStatement()
.mapNotNull { getMatch(it, isForArrayOrCollection, isForString) }
.toList()
if (matches.isNotEmpty()) {
if (matches.size == 1) {
val match = matches.single()
val expression = match.methodCall
registerReplaceMethod(
holder,
expression,
expression,
match.replacementMethod
)
{ desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method, noExpectedExpression = match.noExpectedExpression, expectedIsCollection = match.expectedIsCollection)
}
} else {
// I could try to create a quickfix for this, too, but it's probably not worth the effort
holder.registerProblem(statement, REMOVE_ALL_MESSAGE)
}
}
}
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression) super.visitMethodCallExpression(expression)
val isAssertThatWithInt = ASSERT_THAT_INT.test(expression) if (!expression.hasAssertThat()) {
return
}
val isHasSize = HAS_SIZE.test(expression) val isHasSize = HAS_SIZE.test(expression)
if (!(isAssertThatWithInt || isHasSize)) { if (!(isHasSize)) {
return return
} }
val actualExpression = expression.firstArg val actualExpression = expression.firstArg
val isForArrayOrCollection = isArrayLength(actualExpression) || isCollectionSize(actualExpression) val isForArrayOrCollection = isArrayLength(actualExpression) || isCollectionSize(actualExpression)
val isForString = isCharSequenceLength(actualExpression) val isForString = isCharSequenceLength(actualExpression)
if (isHasSize && (isForArrayOrCollection if (!(isForArrayOrCollection
|| (isForString && checkAssertedType(expression, ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME))) || (isForString && checkAssertedType(expression, ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME)))
) { ) {
val assertThatCall = PsiTreeUtil.findChildrenOfType(expression, PsiMethodCallExpression::class.java).find { CORE_ASSERT_THAT_MATCHER.test(it) } ?: return return
registerConciseMethod(
REMOVE_SIZE_DESCRIPTION_TEMPLATE,
holder,
assertThatCall,
expression,
MethodNames.HAS_SAME_SIZE_AS
) { desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method, expectedIsCollection = true, keepActualAsIs = true)
}
} else if (isForArrayOrCollection || isForString) {
val expectedCallExpression = expression.findOutmostMethodCall() ?: return
val constValue = calculateConstantParameterValue(expectedCallExpression, 0)
if (IS_EQUAL_TO_INT.test(expectedCallExpression)) {
if (constValue == 0) {
registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.IS_EMPTY) { desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method, noExpectedExpression = true)
}
} else {
val equalToExpression = expectedCallExpression.firstArg
if (isForArrayOrCollection && (isCollectionSize(equalToExpression) || isArrayLength(equalToExpression)) ||
isForString && (isCollectionSize(equalToExpression) || isArrayLength(equalToExpression) || isCharSequenceLength(equalToExpression))
) {
registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.HAS_SAME_SIZE_AS) { desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method, expectedIsCollection = true)
}
} else {
registerReplaceMethod(holder, expression, expectedCallExpression, MethodNames.HAS_SIZE) { desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method)
}
}
}
} else {
val isTestForEmpty = ((IS_LESS_THAN_OR_EQUAL_TO_INT.test(expectedCallExpression) && (constValue == 0))
|| (IS_LESS_THAN_INT.test(expectedCallExpression) && (constValue == 1))
|| IS_ZERO.test(expectedCallExpression))
val isTestForNotEmpty = ((IS_GREATER_THAN_INT.test(expectedCallExpression) && (constValue == 0))
|| (IS_GREATER_THAN_OR_EQUAL_TO_INT.test(expectedCallExpression) && (constValue == 1))
|| IS_NOT_ZERO.test(expectedCallExpression))
if (isTestForEmpty || isTestForNotEmpty) {
val replacementMethod = isTestForEmpty.map(MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY)
registerReplaceMethod(holder, expression, expectedCallExpression, replacementMethod) { desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method, noExpectedExpression = true)
}
} else if (hasAssertJMethod(expression, ABSTRACT_ITERABLE_ASSERT_CLASSNAME, MethodNames.HAS_SIZE_LESS_THAN)) {
// new stuff in AssertJ 13.2.0
val matchedMethod = BONUS_EXPRESSIONS_CALL_MATCHER_MAP.find { it.first.test(expectedCallExpression) }?.second ?: return
registerReplaceMethod(holder, expression, expectedCallExpression, matchedMethod) { desc, method ->
ReplaceSizeMethodCallQuickFix(desc, method)
}
}
}
} }
} registerConciseMethod(
REMOVE_SIZE_DESCRIPTION_TEMPLATE,
private fun isCharSequenceLength(expression: PsiExpression) = (expression is PsiMethodCallExpression) && CHAR_SEQUENCE_LENGTH.test(expression) holder,
expression,
private fun isCollectionSize(expression: PsiExpression) = (expression is PsiMethodCallExpression) && COLLECTION_SIZE.test(expression) expression,
MethodNames.HAS_SAME_SIZE_AS,
private fun isArrayLength(expression: PsiExpression): Boolean { ::ReplaceHasSizeMethodCallQuickFix
val psiReferenceExpression = expression as? PsiReferenceExpression ?: return false )
return ((psiReferenceExpression.qualifierExpression?.type is PsiArrayType)
&& ((psiReferenceExpression.resolve() as? PsiField)?.name == "length"))
} }
} }
} }
class Match(
val methodCall: PsiMethodCallExpression,
val replacementMethod: String,
val noExpectedExpression: Boolean = false,
val expectedIsCollection: Boolean = false
)
} }
@@ -1,51 +1,42 @@
package de.platon42.intellij.plugins.cajon.inspections package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.CommonClassNames import com.intellij.psi.*
import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import com.siyeh.ig.callMatcher.CallMatcher import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.quickfixes.MoveActualOuterExpressionMethodCallQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.RemoveActualOutmostMethodCallQuickFix
class AssertThatStringExpressionInspection : AbstractAssertJInspection() { class AssertThatStringExpressionInspection : AbstractAssertJInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Asserting a string specific expression" private const val DISPLAY_NAME = "Asserting a string specific expression"
private const val MOVE_EXPECTED_EXPRESSION_DESCRIPTION_TEMPLATE = "Remove %s() of expected expression and use assertThat().%s() instead"
private const val MOVING_OUT_MESSAGE_TEMPLATE = "Moving %s() expression out of assertThat() would be more concise"
private val MAPPINGS = listOf( private val MAPPINGS = listOf(
Mapping( Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "isEmpty").parameterCount(0)!!, CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "isEmpty").parameterCount(0),
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY, hasExpected = false MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY
), ),
Mapping( Mapping(
CallMatcher.anyOf( CallMatcher.anyOf(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equals").parameterCount(1)!!, CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equals").parameterCount(1),
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contentEquals").parameterCount(1)!! CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contentEquals").parameterCount(1)
), ),
MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO
), ),
Mapping( Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equalsIgnoreCase").parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!, CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equalsIgnoreCase").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
MethodNames.IS_EQUAL_TO_IC, MethodNames.IS_NOT_EQUAL_TO_IC MethodNames.IS_EQUAL_TO_IC, MethodNames.IS_NOT_EQUAL_TO_IC
), ),
Mapping( Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contains").parameterCount(1)!!, CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contains").parameterCount(1),
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN
), ),
Mapping( Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "startsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!, CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "startsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
MethodNames.STARTS_WITH, MethodNames.DOES_NOT_START_WITH MethodNames.STARTS_WITH, MethodNames.DOES_NOT_START_WITH
), ),
Mapping( Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "endsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!, CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "endsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
MethodNames.ENDS_WITH, MethodNames.DOES_NOT_END_WITH MethodNames.ENDS_WITH, MethodNames.DOES_NOT_END_WITH
) )
) )
@@ -55,48 +46,30 @@ class AssertThatStringExpressionInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitMethodCallExpression(expression) super.visitExpressionStatement(statement)
if (!ASSERT_THAT_BOOLEAN.test(expression)) { if (!statement.hasAssertThat()) {
return return
} }
val assertThatArgument = expression.firstArg as? PsiMethodCallExpression ?: return val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val mapping = MAPPINGS.firstOrNull { it.callMatcher.test(assertThatArgument) } ?: return val mapping = MAPPINGS.firstOrNull { it.callMatcher.test(assertThatArgument) } ?: return
val expectedCallExpression = expression.findOutmostMethodCall() ?: return val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val expectedResult = getExpectedBooleanResult(expectedCallExpression) ?: return val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
val replacementMethod = if (expectedResult) mapping.replacementForTrue else mapping.replacementForFalse val replacementMethod = if (expectedResult) mapping.replacementForTrue else mapping.replacementForFalse
if (mapping.hasExpected) { registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod, ::MoveOutMethodCallExpressionQuickFix)
registerMoveOutMethod(holder, expression, assertThatArgument, replacementMethod, ::MoveActualOuterExpressionMethodCallQuickFix)
} else {
registerMoveOutMethod(holder, expression, assertThatArgument, replacementMethod) { desc, method ->
RemoveActualOutmostMethodCallQuickFix(desc, method, noExpectedExpression = true)
}
}
} }
} }
} }
private fun registerMoveOutMethod(
holder: ProblemsHolder,
expression: PsiMethodCallExpression,
oldActualExpression: PsiMethodCallExpression,
replacementMethod: String,
quickFixSupplier: (String, String) -> LocalQuickFix
) {
val originalMethod = getOriginalMethodName(oldActualExpression) ?: return
val description = MOVE_EXPECTED_EXPRESSION_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod)
val message = MOVING_OUT_MESSAGE_TEMPLATE.format(originalMethod)
val quickfix = quickFixSupplier(description, replacementMethod)
holder.registerProblem(expression, message, quickfix)
}
private class Mapping( private class Mapping(
val callMatcher: CallMatcher, val callMatcher: CallMatcher,
val replacementForTrue: String, val replacementForTrue: String,
val replacementForFalse: String, val replacementForFalse: String
val hasExpected: Boolean = true
) )
} }
@@ -4,8 +4,11 @@ import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiStatement
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.MethodNames import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue
import de.platon42.intellij.plugins.cajon.hasAssertThat
class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() { class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
@@ -19,9 +22,13 @@ class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression) super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
val isEqual = IS_EQUAL_TO_OBJECT.test(expression) val isEqual = IS_EQUAL_TO_OBJECT.test(expression)
val hasSize = HAS_SIZE.test(expression) val hasSize = HAS_SIZE.test(expression)
if (!(isEqual || hasSize)) { val isLastExpression = expression.parent is PsiStatement
if (!((isEqual || hasSize) && isLastExpression)) {
return return
} }
@@ -29,7 +36,7 @@ class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
return return
} }
val value = calculateConstantParameterValue(expression, 0) ?: return val value = expression.calculateConstantParameterValue(0) ?: return
if ((isEqual && (value == "")) || (hasSize && (value == 0))) { if ((isEqual && (value == "")) || (hasSize && (value == 0))) {
registerSimplifyMethod(holder, expression, MethodNames.IS_EMPTY) registerSimplifyMethod(holder, expression, MethodNames.IS_EMPTY)
} }
@@ -0,0 +1,148 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.*
import de.platon42.intellij.plugins.cajon.hasAssertThat
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceIfByAssumeThatQuickFix
class AssumeThatInsteadOfReturnInspection : AbstractAssertJInspection() {
companion object {
private const val DISPLAY_NAME = "Replace conditional test exits by assumeThat() statements with same actual expression"
private const val REPLACE_RETURN_BY_ASSUME_THAT_DESCRIPTION = "Conditional return should probably be an assumeThat() statement instead"
private const val MAX_RECURSION_DEPTH = 5
private const val MAX_STATEMENTS_COUNT = 50
private val TEST_ANNOTATIONS = setOf(
"org.junit.Test",
"org.junit.jupiter.api.Test",
"org.junit.jupiter.api.TestTemplate",
"org.junit.jupiter.api.params.ParameterizedTest"
)
private fun hasEmptyReturn(statement: PsiStatement): Boolean {
return when (statement) {
is PsiBlockStatement -> {
val psiReturnStatement = (statement.firstChild as? PsiCodeBlock)?.statements?.singleOrNull() as? PsiReturnStatement
(psiReturnStatement != null) && (psiReturnStatement.returnValue == null)
}
is PsiReturnStatement -> statement.returnValue == null
else -> false
}
}
private fun registerProblem(holder: ProblemsHolder, isOnTheFly: Boolean, statement: PsiStatement, removeElse: Boolean) {
val problemDescriptor = holder.manager.createProblemDescriptor(
statement,
statement,
REPLACE_RETURN_BY_ASSUME_THAT_DESCRIPTION,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
isOnTheFly,
ReplaceIfByAssumeThatQuickFix(removeElse)
)
holder.registerProblem(problemDescriptor)
}
}
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitMethod(method: PsiMethod) {
super.visitMethod(method)
// Note: replace with if(TEST_ANNOTATIONS.none(method::hasAnnotation)) for IDEA >= 2018.2
val annotations = method.annotations.mapNotNull { it.qualifiedName }
if (annotations.none(TEST_ANNOTATIONS::contains)) {
return
}
val containingClass = method.containingClass ?: return
val visitor: PsiElementVisitor = TestMethodVisitor(holder, isOnTheFly, containingClass)
method.accept(visitor)
}
}
}
class TestMethodVisitor(
private val holder: ProblemsHolder,
private val isOnTheFly: Boolean,
private val containingClass: PsiClass
) : JavaRecursiveElementWalkingVisitor() {
private var contSearch = true
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
if (contSearch) {
val methodCallExpression = statement.expression as? PsiMethodCallExpression
if (methodCallExpression != null) {
if (methodCallExpression.hasAssertThat()) {
contSearch = false
} else {
val method = methodCallExpression.resolveMethod()
if (method?.containingClass == containingClass) {
val recursionVisitor = CheckForAssertThatCallsVisitor(containingClass, 1)
method.accept(recursionVisitor)
if (recursionVisitor.aborted || recursionVisitor.foundAssertThat) {
contSearch = false
}
}
}
}
}
if (contSearch) {
super.visitExpressionStatement(statement)
}
}
override fun visitIfStatement(statement: PsiIfStatement) {
if (contSearch) {
checkBranch(statement, statement.thenBranch, false)
checkBranch(statement, statement.elseBranch, true)
}
}
private fun checkBranch(statement: PsiIfStatement, branch: PsiStatement?, removeElse: Boolean) {
if (branch != null) {
if (hasEmptyReturn(branch)) {
registerProblem(holder, isOnTheFly, statement, removeElse)
} else {
branch.accept(TestMethodVisitor(holder, isOnTheFly, containingClass))
}
}
}
}
class CheckForAssertThatCallsVisitor(private val containingClass: PsiClass, private var depth: Int) : JavaRecursiveElementWalkingVisitor() {
var foundAssertThat = false
private var statementCount = 0
var aborted = false
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
if (foundAssertThat || aborted) {
return
}
if (++statementCount > MAX_STATEMENTS_COUNT) {
aborted = true
return
}
super.visitExpressionStatement(statement)
val methodCallExpression = statement.expression as? PsiMethodCallExpression
if (methodCallExpression != null) {
foundAssertThat = methodCallExpression.hasAssertThat()
val method = methodCallExpression.resolveMethod()
if (method?.containingClass == containingClass) {
if (depth < MAX_RECURSION_DEPTH) {
val recursionVisitor = CheckForAssertThatCallsVisitor(containingClass, depth + 1)
method.accept(recursionVisitor)
foundAssertThat = recursionVisitor.foundAssertThat
statementCount += recursionVisitor.statementCount
aborted = recursionVisitor.aborted
} else {
aborted = true
}
}
}
}
}
}
@@ -16,6 +16,8 @@ class JUnitAssertToAssertJInspection : AbstractJUnitAssertInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Convert JUnit assertions to AssertJ" private const val DISPLAY_NAME = "Convert JUnit assertions to AssertJ"
private const val CONVERT_MESSAGE_TEMPLATE = "%s can be converted to AssertJ style"
private const val CONVERT_DESCRIPTION_TEMPLATE = "Convert %s() to assertThat().%s()"
private val MAPPINGS = listOf( private val MAPPINGS = listOf(
Mapping( Mapping(
@@ -142,7 +144,7 @@ class JUnitAssertToAssertJInspection : AbstractJUnitAssertInspection() {
quickFixSupplier: (String, String) -> LocalQuickFix quickFixSupplier: (String, String) -> LocalQuickFix
) { ) {
val originalMethod = getOriginalMethodName(expression) ?: return val originalMethod = getOriginalMethodName(expression) ?: return
val description = REPLACE_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod) val description = CONVERT_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod)
val message = CONVERT_MESSAGE_TEMPLATE.format(originalMethod) val message = CONVERT_MESSAGE_TEMPLATE.format(originalMethod)
val quickfix = quickFixSupplier(description, replacementMethod) val quickfix = quickFixSupplier(description, replacementMethod)
holder.registerProblem(expression, message, quickfix) holder.registerProblem(expression, message, quickfix)
@@ -4,13 +4,14 @@ import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.siyeh.ig.psiutils.EquivalenceChecker
import de.platon42.intellij.plugins.cajon.* import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.JoinStatementsQuickFix import de.platon42.intellij.plugins.cajon.quickfixes.JoinStatementsQuickFix
class JoinAssertThatStatementsInspection : AbstractAssertJInspection() { class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
companion object { companion object {
private const val DISPLAY_NAME = "Joining multiple assertThat() statements with same actual expression" private const val DISPLAY_NAME = "Join multiple assertThat() statements with same actual expression"
private const val CAN_BE_JOINED_DESCRIPTION = "Multiple assertThat() statements can be joined together" private const val CAN_BE_JOINED_DESCRIPTION = "Multiple assertThat() statements can be joined together"
} }
@@ -18,14 +19,15 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitCodeBlock(block: PsiCodeBlock?) { override fun visitCodeBlock(block: PsiCodeBlock) {
super.visitCodeBlock(block) super.visitCodeBlock(block)
val statements = block?.statements ?: return
var lastActualExpression: PsiExpression? = null var lastActualExpression: PsiExpression? = null
var sameCount = 0 var sameCount = 0
var firstStatement: PsiStatement? = null var firstStatement: PsiStatement? = null
var lastStatement: PsiStatement? = null var lastStatement: PsiStatement? = null
for (statement in statements) { // Note: replace with TrackingEquivalenceChecker() for IDEA >= 2019.1
val equivalenceChecker = EquivalenceChecker.getCanonicalPsiEquivalence()!!
for (statement in block.statements) {
val assertThatCall = isLegitAssertThatCall(statement) val assertThatCall = isLegitAssertThatCall(statement)
var reset = true var reset = true
var actualExpression: PsiExpression? = null var actualExpression: PsiExpression? = null
@@ -34,11 +36,14 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
actualExpression = assertThatCall.firstArg actualExpression = assertThatCall.firstArg
if (!reset) { if (!reset) {
val isSame = when (actualExpression) { val isSame = when (actualExpression) {
is PsiReferenceExpression -> (actualExpression.qualifierExpression == (lastActualExpression as? PsiReferenceExpression)?.qualifierExpression) is PsiMethodCallExpression -> equivalenceChecker.expressionsAreEquivalent(actualExpression, lastActualExpression)
is PsiMethodCallExpression -> (actualExpression.text == (lastActualExpression as? PsiMethodCallExpression)?.text) // Note: replace with PsiTreeUtil.findChildrenOfAnyType(strict = false) for IDEA >= 2018.1
&& !KNOWN_METHODS_WITH_SIDE_EFFECTS.test(actualExpression) && !KNOWN_METHODS_WITH_SIDE_EFFECTS.test(actualExpression)
is PsiPolyadicExpression -> (actualExpression.text == (lastActualExpression as? PsiPolyadicExpression)?.text) && PsiTreeUtil.findChildrenOfAnyType(
else -> false actualExpression,
PsiMethodCallExpression::class.java
).none { KNOWN_METHODS_WITH_SIDE_EFFECTS.test(it) }
else -> equivalenceChecker.expressionsAreEquivalent(actualExpression, lastActualExpression)
} }
if (isSame) { if (isSame) {
sameCount++ sameCount++
@@ -50,7 +55,7 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
} }
if (reset) { if (reset) {
if (sameCount > 1) { if (sameCount > 1) {
registerProblem(firstStatement, lastStatement) registerProblem(holder, isOnTheFly, firstStatement!!, lastStatement!!)
} }
firstStatement = statement firstStatement = statement
lastStatement = null lastStatement = null
@@ -59,24 +64,15 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
} }
} }
if (sameCount > 1) { if (sameCount > 1) {
registerProblem(firstStatement, lastStatement) registerProblem(holder, isOnTheFly, firstStatement!!, lastStatement!!)
} }
} }
private fun registerProblem(firstStatement: PsiStatement?, lastStatement: PsiStatement?) {
val problemDescriptor = holder.manager.createProblemDescriptor(
firstStatement!!,
lastStatement!!,
CAN_BE_JOINED_DESCRIPTION,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
isOnTheFly,
JoinStatementsQuickFix()
)
holder.registerProblem(problemDescriptor)
}
private fun isLegitAssertThatCall(statement: PsiStatement?): PsiMethodCallExpression? { private fun isLegitAssertThatCall(statement: PsiStatement?): PsiMethodCallExpression? {
if ((statement is PsiExpressionStatement) && (statement.expression is PsiMethodCallExpression)) { if ((statement is PsiExpressionStatement) && (statement.expression is PsiMethodCallExpression)) {
if (!statement.hasAssertThat()) {
return null
}
val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) } val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) }
return assertThatCall?.takeIf { it.findFluentCallTo(EXTRACTING_CALL_MATCHERS) == null } return assertThatCall?.takeIf { it.findFluentCallTo(EXTRACTING_CALL_MATCHERS) == null }
} }
@@ -84,4 +80,16 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
} }
} }
} }
private fun registerProblem(holder: ProblemsHolder, isOnTheFly: Boolean, firstStatement: PsiStatement, lastStatement: PsiStatement) {
val problemDescriptor = holder.manager.createProblemDescriptor(
firstStatement,
lastStatement,
CAN_BE_JOINED_DESCRIPTION,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
isOnTheFly,
JoinStatementsQuickFix()
)
holder.registerProblem(problemDescriptor)
}
} }
@@ -4,6 +4,7 @@ import com.intellij.codeInspection.LocalQuickFix
abstract class AbstractCommonQuickFix(private val description: String) : LocalQuickFix { abstract class AbstractCommonQuickFix(private val description: String) : LocalQuickFix {
override fun getFamilyName() = description override fun getName() = description
override fun getFamilyName() = description
} }
@@ -8,12 +8,13 @@ import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.cajon.* import de.platon42.intellij.plugins.cajon.*
class ForGuavaPostFix { class ForGuavaPostFix {
companion object { companion object {
val REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT: (Project, ProblemDescriptor) -> Unit = exit@ val REPLACE_BY_GUAVA_ASSERT_THAT_AND_STATIC_IMPORT: (Project, ProblemDescriptor) -> Unit = exit@
{ _, descriptor -> { _, descriptor ->
val element = descriptor.startElement val element = descriptor.startElement
val statement = PsiTreeUtil.getParentOfType(element, PsiStatement::class.java) ?: return@exit val statement = PsiTreeUtil.getParentOfType(element, PsiStatement::class.java) ?: return@exit
val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { CORE_ASSERT_THAT_MATCHER.test(it) } ?: return@exit val assertThatCall = statement.findStaticMethodCall() ?: return@exit
val newMethodCall = createGuavaAssertThat(element, assertThatCall.firstArg) val newMethodCall = createGuavaAssertThat(element, assertThatCall.firstArg)
newMethodCall.resolveMethod()?.addAsStaticImport(element, AssertJClassNames.ASSERTIONS_CLASSNAME) newMethodCall.resolveMethod()?.addAsStaticImport(element, AssertJClassNames.ASSERTIONS_CLASSNAME)
@@ -0,0 +1,37 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiUnaryExpression
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiUtil
import de.platon42.intellij.plugins.cajon.*
class InvertUnaryStatementQuickFix : AbstractCommonQuickFix(INVERT_CONDITION_DESCRIPTION) {
companion object {
private const val INVERT_CONDITION_DESCRIPTION = "Invert condition in assertThat()"
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val outmostCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
val assertThatMethodCall = outmostCallExpression.findStaticMethodCall() ?: return
val assertExpression = assertThatMethodCall.firstArg as? PsiUnaryExpression ?: return
val operand = PsiUtil.skipParenthesizedExprDown(assertExpression.operand) ?: return
assertExpression.replace(operand)
var methodCall: PsiMethodCallExpression? = assertThatMethodCall
while (methodCall != null) {
val expectedResult = methodCall.getExpectedBooleanResult()
val nextMethodCall = PsiTreeUtil.getParentOfType(methodCall, PsiMethodCallExpression::class.java)
if (expectedResult != null) {
val replacementMethod = expectedResult.map(MethodNames.IS_FALSE, MethodNames.IS_TRUE)
val expectedExpression = createExpectedMethodCall(methodCall, replacementMethod)
expectedExpression.replaceQualifierFromMethodCall(methodCall)
methodCall.replace(expectedExpression)
}
methodCall = nextMethodCall
}
}
}
@@ -3,11 +3,12 @@ package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.cajon.ALL_ASSERT_THAT_MATCHERS import de.platon42.intellij.plugins.cajon.findStaticMethodCall
import de.platon42.intellij.plugins.cajon.shortenAndReformat
class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) { class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
companion object { companion object {
private const val JOIN_STATEMENTS_MESSAGE = "Join assertThat() statements" private const val JOIN_STATEMENTS_MESSAGE = "Join assertThat() statements"
} }
@@ -18,22 +19,20 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
do { do {
val commentsToKeep = ArrayList<PsiComment>() val commentsToKeep = ArrayList<PsiComment>()
val stuffToDelete = ArrayList<PsiElement>() val stuffToDelete = ArrayList<PsiElement>()
var previousStatement = lastStatement.prevSibling ?: throw IllegalStateException("Internal error") var previousStatement = lastStatement.prevSibling!!
while (previousStatement !is PsiExpressionStatement) { while (previousStatement !is PsiExpressionStatement) {
if (previousStatement is PsiComment) { if (previousStatement is PsiComment) {
commentsToKeep.add(previousStatement.copy() as PsiComment) commentsToKeep.add(previousStatement.copy() as PsiComment)
} }
stuffToDelete.add(previousStatement) stuffToDelete.add(previousStatement)
previousStatement = previousStatement.prevSibling ?: throw IllegalStateException("Internal error") previousStatement = previousStatement.prevSibling!!
} }
stuffToDelete.forEach { if (it.isValid) it.delete() } stuffToDelete.forEach { if (it.isValid) it.delete() }
val statementComments = PsiTreeUtil.getChildrenOfAnyType(previousStatement, PsiComment::class.java) val statementComments = PsiTreeUtil.getChildrenOfAnyType(previousStatement, PsiComment::class.java)
commentsToKeep.addAll(statementComments) commentsToKeep.addAll(statementComments)
val assertThatCallOfCursorStatement = val assertThatCallOfCursorStatement = lastStatement.findStaticMethodCall()!!
PsiTreeUtil.findChildrenOfType(lastStatement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) }
?: throw IllegalStateException("Internal error")
val lastElementBeforeConcat = assertThatCallOfCursorStatement.parent val lastElementBeforeConcat = assertThatCallOfCursorStatement.parent
commentsToKeep.forEach { commentsToKeep.forEach {
@@ -49,6 +48,6 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
previousStatement.delete() previousStatement.delete()
} while (previousStatement !== firstStatement) } while (previousStatement !== firstStatement)
val codeBlock = PsiTreeUtil.getParentOfType(lastStatement, PsiCodeBlock::class.java) ?: return val codeBlock = PsiTreeUtil.getParentOfType(lastStatement, PsiCodeBlock::class.java) ?: return
CodeStyleManager.getInstance(project).reformat(codeBlock) codeBlock.shortenAndReformat()
} }
} }
@@ -1,22 +0,0 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMethodCallExpression
import de.platon42.intellij.plugins.cajon.*
class MoveActualOuterExpressionMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return
val assertExpression = methodCallExpression.firstArg as? PsiMethodCallExpression ?: return
val assertExpressionArg = assertExpression.firstArg.copy()
assertExpression.replace(assertExpression.qualifierExpression)
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
val expectedExpression = createExpectedMethodCall(element, replacementMethod, assertExpressionArg)
expectedExpression.replaceQualifierFromMethodCall(oldExpectedExpression)
oldExpectedExpression.replace(expectedExpression)
}
}
@@ -0,0 +1,44 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiInstanceOfExpression
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.util.PsiUtil
import de.platon42.intellij.plugins.cajon.*
class MoveOutInstanceOfExpressionQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
companion object {
private const val REMOVE_INSTANCEOF_DESCRIPTION = "Move instanceof in actual expressions out of assertThat()"
}
override fun getFamilyName(): String {
return REMOVE_INSTANCEOF_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val outmostCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
val assertThatMethodCall = outmostCallExpression.findStaticMethodCall() ?: return
val assertExpression = assertThatMethodCall.firstArg as? PsiInstanceOfExpression ?: return
val expectedClass = assertExpression.checkType ?: return
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
.filter { it.getExpectedBooleanResult() != null }
.toList()
val factory = JavaPsiFacade.getElementFactory(project)
val classObjectAccess = factory.createExpressionFromText("${expectedClass.type.canonicalText}.class", null)
val operand = PsiUtil.deparenthesizeExpression(assertExpression.operand) ?: return
assertExpression.replace(operand)
methodsToFix
.forEach {
val expectedExpression = createExpectedMethodCall(it, replacementMethod, classObjectAccess)
expectedExpression.replaceQualifierFromMethodCall(it)
it.replace(expectedExpression)
}
}
}
@@ -0,0 +1,37 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMethodCallExpression
import de.platon42.intellij.plugins.cajon.*
class MoveOutMethodCallExpressionQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
companion object {
private const val REMOVE_ACTUAL_EXPRESSION_DESCRIPTION = "Move method calls in actual expressions out of assertThat()"
}
override fun getFamilyName(): String {
return REMOVE_ACTUAL_EXPRESSION_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val outmostCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
val assertThatMethodCall = outmostCallExpression.findStaticMethodCall() ?: return
val assertExpression = assertThatMethodCall.firstArg as? PsiMethodCallExpression ?: return
val assertExpressionArg = assertExpression.getArgOrNull(0)?.copy()
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
.filter { it.getExpectedBooleanResult() != null }
.toList()
assertExpression.replace(assertExpression.qualifierExpression)
methodsToFix
.forEach {
val expectedExpression = createExpectedMethodCall(it, replacementMethod, *listOfNotNull(assertExpressionArg).toTypedArray())
expectedExpression.replaceQualifierFromMethodCall(it)
it.replace(expectedExpression)
}
}
}
@@ -9,6 +9,10 @@ class QuickFixWithPostfixDelegate(
private val postfix: (Project, ProblemDescriptor) -> Unit private val postfix: (Project, ProblemDescriptor) -> Unit
) : LocalQuickFix by mainFix { ) : LocalQuickFix by mainFix {
override fun getName(): String {
return mainFix.name
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
mainFix.applyFix(project, descriptor) mainFix.applyFix(project, descriptor)
postfix(project, descriptor) postfix(project, descriptor)
@@ -11,16 +11,29 @@ class RemoveActualOutmostMethodCallQuickFix(
private val noExpectedExpression: Boolean = false private val noExpectedExpression: Boolean = false
) : AbstractCommonQuickFix(description) { ) : AbstractCommonQuickFix(description) {
companion object {
private const val REMOVE_ACTUAL_EXPRESSION_DESCRIPTION = "Remove method calls in actual expressions and use better assertion"
}
override fun getFamilyName(): String {
return REMOVE_ACTUAL_EXPRESSION_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement val outmostCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
val methodCallExpression = element as? PsiMethodCallExpression ?: return val assertThatMethodCall = outmostCallExpression.findStaticMethodCall() ?: return
val assertExpression = methodCallExpression.firstArg as? PsiMethodCallExpression ?: return val assertExpression = assertThatMethodCall.firstArg as? PsiMethodCallExpression ?: return
val methodsToFix = assertThatMethodCall.gatherAssertionCalls()
assertExpression.replace(assertExpression.qualifierExpression) assertExpression.replace(assertExpression.qualifierExpression)
val oldExpectedExpression = element.findOutmostMethodCall() ?: return methodsToFix
val args = if (noExpectedExpression) emptyArray() else oldExpectedExpression.argumentList.expressions .forEach {
val expectedExpression = createExpectedMethodCall(element, replacementMethod, *args) val args = if (noExpectedExpression) emptyArray() else it.argumentList.expressions
expectedExpression.replaceQualifierFromMethodCall(oldExpectedExpression) val expectedExpression = createExpectedMethodCall(it, replacementMethod, *args)
oldExpectedExpression.replace(expectedExpression) expectedExpression.replaceQualifierFromMethodCall(it)
it.replace(expectedExpression)
}
} }
} }
@@ -1,32 +0,0 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiInstanceOfExpression
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.util.PsiUtil
import de.platon42.intellij.plugins.cajon.createExpectedMethodCall
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class RemoveInstanceOfExpressionQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return
val assertExpression = methodCallExpression.firstArg as? PsiInstanceOfExpression ?: return
val expectedClass = assertExpression.checkType ?: return
val factory = JavaPsiFacade.getElementFactory(project)
val classObjectAccess = factory.createExpressionFromText("${expectedClass.type.canonicalText}.class", null)
val operand = PsiUtil.deparenthesizeExpression(assertExpression.operand) ?: return
assertExpression.replace(operand)
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
val expectedExpression = createExpectedMethodCall(element, replacementMethod, classObjectAccess)
expectedExpression.replaceQualifierFromMethodCall(oldExpectedExpression)
oldExpectedExpression.replace(expectedExpression)
}
}
@@ -1,27 +0,0 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiUnaryExpression
import com.intellij.psi.util.PsiUtil
import de.platon42.intellij.plugins.cajon.createExpectedMethodCall
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class RemoveUnaryExpressionQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return
val assertExpression = methodCallExpression.firstArg as? PsiUnaryExpression ?: return
val operand = PsiUtil.skipParenthesizedExprDown(assertExpression.operand) ?: return
assertExpression.replace(operand)
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
val expectedExpression = createExpectedMethodCall(element, replacementMethod)
expectedExpression.replaceQualifierFromMethodCall(oldExpectedExpression)
oldExpectedExpression.replace(expectedExpression)
}
}
@@ -0,0 +1,35 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiReferenceExpression
import de.platon42.intellij.plugins.cajon.createExpectedMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.qualifierExpression
import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class ReplaceHasSizeMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val methodCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
replaceCollectionSizeOrArrayLength(methodCallExpression.firstArg)
val expectedExpression = createExpectedMethodCall(methodCallExpression, replacementMethod, methodCallExpression.firstArg)
expectedExpression.replaceQualifierFromMethodCall(methodCallExpression)
methodCallExpression.replace(expectedExpression)
}
private fun replaceCollectionSizeOrArrayLength(assertExpression: PsiExpression) {
assertExpression.replace(
when (assertExpression) {
is PsiReferenceExpression -> assertExpression.qualifierExpression!!
is PsiMethodCallExpression -> assertExpression.qualifierExpression
else -> return
}
)
}
}
@@ -0,0 +1,51 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiBlockStatement
import com.intellij.psi.PsiDeclarationStatement
import com.intellij.psi.PsiIfStatement
import de.platon42.intellij.plugins.cajon.*
class ReplaceIfByAssumeThatQuickFix(private val removeElse: Boolean) : AbstractCommonQuickFix(REPLACE_IF_MESSAGE) {
companion object {
private const val REPLACE_IF_MESSAGE = "Replace if statement by assumeTrue()"
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val ifStatement = descriptor.startElement as PsiIfStatement
val condition = ifStatement.condition ?: return
val factory = JavaPsiFacade.getElementFactory(ifStatement.project)
val assumptionExpression = if (removeElse) MethodNames.IS_TRUE else MethodNames.IS_FALSE
val assumeThatStatement = factory.createStatementFromText(
"${AssertJClassNames.ASSUMPTIONS_CLASSNAME}.${MethodNames.ASSUME_THAT}(true).$assumptionExpression();",
ifStatement
)
val assumeThatMethodCall = assumeThatStatement.findStaticMethodCall() ?: return
assumeThatMethodCall.firstArg.replace(condition)
assumeThatMethodCall.resolveMethod()?.addAsStaticImport(ifStatement)
val branchToKeep = (if (removeElse) ifStatement.thenBranch else ifStatement.elseBranch)?.copy()
val parentBlock = ifStatement.parent
if (branchToKeep != null) {
val anchorElement = ifStatement.nextSibling
if (branchToKeep is PsiBlockStatement) {
val codeBlock = branchToKeep.codeBlock
if (codeBlock.statements.isNotEmpty()) {
val hasDeclarations = codeBlock.statements.any { it is PsiDeclarationStatement }
if (hasDeclarations) {
parentBlock.addAfter(branchToKeep, anchorElement)
} else {
parentBlock.addRangeAfter(codeBlock.firstBodyElement, codeBlock.lastBodyElement, anchorElement)
}
}
} else {
parentBlock.addAfter(branchToKeep, anchorElement)
}
}
ifStatement.replace(assumeThatStatement).shortenAndReformat()
}
}
@@ -10,6 +10,14 @@ import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.GUAVA_ASSE
class ReplaceJUnitAssertMethodCallQuickFix(description: String, private val replacementMethod: String, private val noExpectedExpression: Boolean) : class ReplaceJUnitAssertMethodCallQuickFix(description: String, private val replacementMethod: String, private val noExpectedExpression: Boolean) :
AbstractCommonQuickFix(description) { AbstractCommonQuickFix(description) {
companion object {
private const val CONVERT_DESCRIPTION = "Convert JUnit assertions to assertJ"
}
override fun getFamilyName(): String {
return CONVERT_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return val methodCallExpression = element as? PsiMethodCallExpression ?: return
@@ -8,6 +8,14 @@ import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.GUAVA_ASSE
class ReplaceJUnitDeltaAssertMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) { class ReplaceJUnitDeltaAssertMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
companion object {
private const val CONVERT_DESCRIPTION = "Convert JUnit assertions to assertJ"
}
override fun getFamilyName(): String {
return CONVERT_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return val methodCallExpression = element as? PsiMethodCallExpression ?: return
@@ -8,6 +8,14 @@ import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class ReplaceSimpleMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) { class ReplaceSimpleMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
companion object {
private const val REPLACE_DESCRIPTION = "Replace methods by better ones"
}
override fun getFamilyName(): String {
return REPLACE_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement val element = descriptor.startElement
val methodCallExpression = element as? PsiMethodCallExpression ?: return val methodCallExpression = element as? PsiMethodCallExpression ?: return
@@ -11,28 +11,32 @@ class ReplaceSizeMethodCallQuickFix(
description: String, description: String,
private val replacementMethod: String, private val replacementMethod: String,
private val noExpectedExpression: Boolean = false, private val noExpectedExpression: Boolean = false,
private val expectedIsCollection: Boolean = false, private val expectedIsCollection: Boolean = false
private val keepActualAsIs: Boolean = false
) : AbstractCommonQuickFix(description) { ) : AbstractCommonQuickFix(description) {
companion object {
private const val REPLACE_DESCRIPTION = "Replace methods by better ones"
}
override fun getFamilyName(): String {
return REPLACE_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement val outmostCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
val methodCallExpression = element as? PsiMethodCallExpression ?: return val assertThatMethodCall = outmostCallExpression.findStaticMethodCall() ?: return
if (!keepActualAsIs) { val assertExpression = assertThatMethodCall.firstArg
val assertExpression = methodCallExpression.firstArg replaceCollectionSizeOrArrayLength(assertExpression)
replaceCollectionSizeOrArrayLength(assertExpression)
}
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
if (expectedIsCollection) { if (expectedIsCollection) {
replaceCollectionSizeOrArrayLength(oldExpectedExpression.firstArg) replaceCollectionSizeOrArrayLength(outmostCallExpression.firstArg)
} }
val args = if (noExpectedExpression) emptyArray() else arrayOf(oldExpectedExpression.firstArg) val args = if (noExpectedExpression) emptyArray() else arrayOf(outmostCallExpression.firstArg)
val expectedExpression = createExpectedMethodCall(element, replacementMethod, *args) val expectedExpression = createExpectedMethodCall(outmostCallExpression, replacementMethod, *args)
expectedExpression.replaceQualifierFromMethodCall(oldExpectedExpression) expectedExpression.replaceQualifierFromMethodCall(outmostCallExpression)
oldExpectedExpression.replace(expectedExpression) outmostCallExpression.replace(expectedExpression)
} }
private fun replaceCollectionSizeOrArrayLength(assertExpression: PsiExpression) { private fun replaceCollectionSizeOrArrayLength(assertExpression: PsiExpression) {
@@ -4,10 +4,7 @@ import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiBinaryExpression import com.intellij.psi.PsiBinaryExpression
import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiMethodCallExpression
import de.platon42.intellij.plugins.cajon.createExpectedMethodCall import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.findOutmostMethodCall
import de.platon42.intellij.plugins.cajon.firstArg
import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class SplitBinaryExpressionMethodCallQuickFix( class SplitBinaryExpressionMethodCallQuickFix(
description: String, description: String,
@@ -16,17 +13,33 @@ class SplitBinaryExpressionMethodCallQuickFix(
private val noExpectedExpression: Boolean = false private val noExpectedExpression: Boolean = false
) : AbstractCommonQuickFix(description) { ) : AbstractCommonQuickFix(description) {
companion object {
private const val SPLIT_EXPRESSION_DESCRIPTION = "Split binary expressions out of assertThat()"
}
override fun getFamilyName(): String {
return SPLIT_EXPRESSION_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement val outmostCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
val methodCallExpression = element as? PsiMethodCallExpression ?: return val assertThatMethodCall = outmostCallExpression.findStaticMethodCall() ?: return
val binaryExpression = methodCallExpression.firstArg as? PsiBinaryExpression ?: return
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
.filter { it.getExpectedBooleanResult() != null }
.toList()
val binaryExpression = assertThatMethodCall.firstArg as? PsiBinaryExpression ?: return
val expectedArgument = (if (pickRightOperand) binaryExpression.lOperand else binaryExpression.rOperand)?.copy() ?: return val expectedArgument = (if (pickRightOperand) binaryExpression.lOperand else binaryExpression.rOperand)?.copy() ?: return
binaryExpression.replace(if (pickRightOperand) binaryExpression.rOperand!! else binaryExpression.lOperand) binaryExpression.replace(if (pickRightOperand) binaryExpression.rOperand!! else binaryExpression.lOperand)
val oldExpectedExpression = element.findOutmostMethodCall() ?: return
val args = if (noExpectedExpression) emptyArray() else arrayOf(expectedArgument) val args = if (noExpectedExpression) emptyArray() else arrayOf(expectedArgument)
val expectedExpression = createExpectedMethodCall(element, replacementMethod, *args)
expectedExpression.replaceQualifierFromMethodCall(oldExpectedExpression) methodsToFix
oldExpectedExpression.replace(expectedExpression) .forEach {
val expectedExpression = createExpectedMethodCall(it, replacementMethod, *args)
expectedExpression.replaceQualifierFromMethodCall(it)
it.replace(expectedExpression)
}
} }
} }
@@ -10,6 +10,14 @@ import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class UnwrapExpectedStaticMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) { class UnwrapExpectedStaticMethodCallQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
companion object {
private const val REMOVE_EXPECTED_OUTMOST_DESCRIPTION = "Unwrap expected expressions and use better assertion"
}
override fun getFamilyName(): String {
return REMOVE_EXPECTED_OUTMOST_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.startElement val element = descriptor.startElement
val oldExpectedExpression = element.findOutmostMethodCall() ?: return val oldExpectedExpression = element.findOutmostMethodCall() ?: return
@@ -50,9 +50,8 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
} }
private fun findActualType(element: PsiElement): PsiClassType? { private fun findActualType(element: PsiElement): PsiClassType? {
val assertThatCall = PsiTreeUtil.findChildrenOfType(element, PsiMethodCallExpression::class.java) val assertThatCall = element.findStaticMethodCall()
.find { CORE_ASSERT_THAT_MATCHER.test(it) } ?: return null return assertThatCall?.firstArg?.type as? PsiClassType
return assertThatCall.firstArg.type as? PsiClassType
} }
private fun findAndCreateReferences(element: PsiElement, finder: (PsiLiteralExpression) -> List<Pair<TextRange, List<PsiElement>>>?): Array<PsiReference> { private fun findAndCreateReferences(element: PsiElement, finder: (PsiLiteralExpression) -> List<Pair<TextRange, List<PsiElement>>>?): Array<PsiReference> {
+4
View File
@@ -42,9 +42,13 @@
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBinaryExpressionInspection"/> implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBinaryExpressionInspection"/>
<localInspection groupPath="Java" shortName="AssertThatStringExpression" enabledByDefault="true" level="WARNING" <localInspection groupPath="Java" shortName="AssertThatStringExpression" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatStringExpressionInspection"/> implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatStringExpressionInspection"/>
<localInspection groupPath="Java" shortName="AssertThatCollectionOrMapExpression" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatCollectionOrMapExpressionInspection"/>
<localInspection groupPath="Java" shortName="JoinAssertThatStatements" enabledByDefault="true" level="WARNING" <localInspection groupPath="Java" shortName="JoinAssertThatStatements" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.JoinAssertThatStatementsInspection"/> implementationClass="de.platon42.intellij.plugins.cajon.inspections.JoinAssertThatStatementsInspection"/>
<localInspection groupPath="Java" shortName="AssumeThatInsteadOfReturn" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssumeThatInsteadOfReturnInspection"/>
<localInspection groupPath="Java" shortName="AssertThatJava8Optional" enabledByDefault="true" level="WARNING" <localInspection groupPath="Java" shortName="AssertThatJava8Optional" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatJava8OptionalInspection"/> implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatJava8OptionalInspection"/>
@@ -2,6 +2,6 @@
<body> <body>
Turns assertThat(condition).isEqualTo(true/false) into assertThat(condition).isTrue()/isFalse(). Turns assertThat(condition).isEqualTo(true/false) into assertThat(condition).isTrue()/isFalse().
<!-- tooltip end --> <!-- tooltip end -->
Also works with constant expressions and Boolean.TRUE/FALSE. <br>Also works with constant expressions and Boolean.TRUE/FALSE.
</body> </body>
</html> </html>
@@ -0,0 +1,8 @@
<html>
<body>
Turns assertThat(collectionOrMap.someMethod(arg)).isTrue/isFalse() into assertThat(collectionOrMap).someMethod(arg).
<!-- tooltip end -->
<br>someMethod() can be isEmpty(), contains(), and containsAll() for collections and
isEmpty(), containsKey(), and containsValue() for maps.
</body>
</html>
@@ -3,6 +3,6 @@
Looks at expected and actual expression being of Guava Optional type and whether the statement effectively tries to assert the 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(). presence, absence or content and then replaces the statement by isPresent(), isAbsent(), or contains().
<!-- tooltip end --> <!-- tooltip end -->
Requires AssertJ-Guava to be in classpath. <br>Requires AssertJ-Guava to be in classpath.
</body> </body>
</html> </html>
@@ -2,6 +2,6 @@
<body> <body>
Turns assertThat(object instanceof classname).isEqualTo(true/false) into assertThat(object).is(Not)InstanceOf(classname.class). Turns assertThat(object instanceof classname).isEqualTo(true/false) into assertThat(object).is(Not)InstanceOf(classname.class).
<!-- tooltip end --> <!-- tooltip end -->
Also works with constant expressions and Boolean.TRUE/FALSE. <br>Also works with constant expressions and Boolean.TRUE/FALSE.
</body> </body>
</html> </html>
@@ -2,6 +2,6 @@
<body> <body>
Turns assertThat(!condition).isEqualTo(true/false) into assertThat(condition).isFalse()/isTrue(). Turns assertThat(!condition).isEqualTo(true/false) into assertThat(condition).isFalse()/isTrue().
<!-- tooltip end --> <!-- tooltip end -->
Also works with constant expressions and Boolean.TRUE/FALSE. <br>Also works with constant expressions and Boolean.TRUE/FALSE.
</body> </body>
</html> </html>
@@ -2,6 +2,6 @@
<body> <body>
Makes assertions on sizes of arrays, collections, strings, or CharSequences more concise by replacing them with isEmpty(), isNotEmpty(), hasSize(), or hasSameSizeAs(). Makes assertions on sizes of arrays, collections, strings, or CharSequences more concise by replacing them with isEmpty(), isNotEmpty(), hasSize(), or hasSameSizeAs().
<!-- tooltip end --> <!-- tooltip end -->
Several more conversions are available with AssertJ 13.2.0 or later. <br>Several more conversions are available with AssertJ 13.2.0 or later.
</body> </body>
</html> </html>
@@ -2,6 +2,6 @@
<body> <body>
Turns assertThat(string.someMethod(arg)).isTrue/isFalse() into assertThat(string).someMethod(arg). Turns assertThat(string.someMethod(arg)).isTrue/isFalse() into assertThat(string).someMethod(arg).
<!-- tooltip end --> <!-- tooltip end -->
<br>someMethod() can be equals(), equalsIgnoreCase(), contentEquals(), contains(), startsWith(), and endsWith(). <br>someMethod() can be isEmpty(), equals(), equalsIgnoreCase(), contentEquals(), contains(), startsWith(), and endsWith().
</body> </body>
</html> </html>
@@ -0,0 +1,18 @@
<html>
<body>
Tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls.
<!-- tooltip end -->
<br>
Novices will use these to skip test execution by bailing out early on some preconditions not met.
However, this suggests that the test has actually been run and passed instead of showing the test
as being skipped.
<p>Return statements in if statements in main test methods
(must be annotated with JUnit 4 or Jupiter @Test annotations)
will be verified to have at least one assertThat() statement in the code flow.
Method calls within the same class will be examined for assertThat() statements, too.
However, at most 50 statements and down to five recursions will be tolerated before giving up.
</p>
<p>Currently, the quickfix may lose some comments during operation. The other branch of the if statement
will be inlined (blocks with declarations will remain a code block due to variable scope).</p>
</body>
</html>
@@ -1,10 +1,11 @@
<html> <html>
<body> <body>
Tries to convert most of the JUnit 4 assertions to AssertJ-Format. Tries to convert most of the JUnit 4 assertions to AssertJ format.
<!-- tooltip end --> <!-- tooltip end -->
<br>Works for assertTrue(), assertFalse(), assertNull(), assertNotNull(), assertEquals(), assertNotEquals(), assertSame() assertNotSame(), assertArrayEquals(). <br>Works for assertTrue(), assertFalse(), assertNull(), assertNotNull(), assertEquals(), assertNotEquals(), assertSame() assertNotSame(), assertArrayEquals().
Copes with variants with message and without, handles special versions for double and float types (including arrays). Copes with variants with message and without, handles special versions for double and float types (including arrays).
<p></p> <p>
Does not support Hamcrest-Matchers. If you need that kind of conversion, you might want to check out the Assertions2AssertJ plugin by Ric Emery. Does not support Hamcrest-Matchers. If you need that kind of conversion, you might want to check out the Assertions2AssertJ plugin by Ric Emery.
</p>
</body> </body>
</html> </html>
@@ -0,0 +1,7 @@
<html>
<body>
Joins consecutive assertThat() statements with the same actual expression together.
<!-- tooltip end -->
<br>Retains comments during operation. If the AssertThat()-Statement contains .extracting() methods, they will not be joined.
</body>
</html>
@@ -1,448 +0,0 @@
package de.platon42.intellij.playground;
import org.assertj.core.api.ListAssert;
import org.assertj.core.data.Offset;
import org.assertj.core.extractor.Extractors;
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.Offset.offset;
import static org.assertj.guava.api.Assertions.assertThat;
import static org.junit.Assert.*;
public class Playground {
private void sizeOfList() {
assertThat("string").as("foo").hasSize(0);
assertThat(new StringBuilder()).as("bar").hasSize(0);
ListAssert<String> etc = assertThat(new ArrayList<String>()).as("etc");
etc.hasSize(0);
assertThat(new Long[1]).as("etc").hasSize(0);
assertThat("string").as("foo").isEmpty();
assertThat(new StringBuilder()).as("bar").isEmpty();
assertThat(new ArrayList<Long>()).as("etc").isEmpty();
assertThat(new Long[1]).as("etc").isEmpty();
assertThat(new ArrayList<>().size()).isEqualTo(1);
assertThat(new ArrayList<String>().size()).isEqualTo(1);
assertThat(new ArrayList<String>().size()).isGreaterThanOrEqualTo(1);
assertThat(new ArrayList<String>().size()).isZero();
assertThat(new ArrayList<String>()).hasSizeGreaterThan(1);
assertThat(new ArrayList<String>()).hasSameSizeAs(new ArrayList<>());
assertThat(new Long[1]).as("etc").hasSameSizeAs(new Long[2]);
assertThat(new Long[1]).as("etc").hasSameSizeAs(new Long[2]);
}
private void joinStatements() {
List<String> list = new ArrayList<>();
assertThat(list).as("foo").hasSize(2);
assertThat(list).as("bar").contains("barbar"); // comment to keep
assertThat(list).as("etc").contains("etcetc");
// moar!
assertThat(list).doesNotContain("foobar");
assertThat("narf").isNotEqualTo("puit");
assertThat(list).as("bar").contains("barbar");
assertThat(list).as("foo").hasSize(2);
assertThat(list).as("evil").extracting(String::length).contains(2);
assertThat(list).as("bar").contains("barbar");
assertThat("narf").isNotEqualTo("puit");
assertThat(list).as("foo").hasSize(2);
if (true) {
assertThat(list).doesNotContain("narf");
assertThat(list).as("bar").contains("barbar");
}
assertThat(list.get(0)).isNotEmpty();
assertThat(list.get(0)).hasSize(3);
assertThat(list.get(0)).isEqualTo("bar");
assertThat(list.get(0) + "foo").isEqualTo("bar");
assertThat(list.get(0) + "foo").doesNotStartWith("foo");
Iterator<String> iterator = list.iterator();
assertThat(iterator.next()).isEqualTo("foo");
assertThat(iterator.next()).isEqualTo("bar");
}
private void sizeOfArray() {
assertThat(new String[1].length).isLessThanOrEqualTo(1);
assertThat(new String[1]).hasSameSizeAs(new Object());
assertThat("").isEqualTo(null);
assertThat(true).isTrue();
assertThat(true).isEqualTo(true);
assertThat(Boolean.TRUE).isEqualTo(Boolean.FALSE);
assertThat(Boolean.TRUE).isEqualTo(true);
}
private void booleanIsTrueOrFalse() {
boolean primitive = false;
Boolean object = java.lang.Boolean.TRUE;
assertThat(primitive).isEqualTo(Boolean.TRUE);
assertThat(primitive).isEqualTo(Boolean.FALSE);
assertThat(object).isEqualTo(Boolean.TRUE);
assertThat(object).isEqualTo(Boolean.FALSE);
assertThat(primitive).isEqualTo(true);
assertThat(primitive).isEqualTo(false);
assertThat(object).isEqualTo(true);
assertThat(object).isEqualTo(false);
assertThat(primitive).isNotEqualTo(Boolean.TRUE);
assertThat(primitive).isNotEqualTo(Boolean.FALSE);
assertThat(object).isNotEqualTo(Boolean.TRUE);
assertThat(object).isNotEqualTo(Boolean.FALSE);
assertThat(primitive).isNotEqualTo(true);
assertThat(primitive).isNotEqualTo(false);
assertThat(object).isNotEqualTo(true);
assertThat(object).isNotEqualTo(false);
assertThat(primitive).as("nah").isEqualTo(true && !true);
assertThat(object).isEqualTo(Boolean.TRUE && !Boolean.TRUE);
assertThat("").isEqualTo(Boolean.TRUE);
}
private void binaryExpression() {
int primExp = 42;
int primAct = 1337;
Double numberObjExp = 42.0;
Double numberObjAct = 1337.0;
String stringExp = "foo";
String stringAct = "bar";
assertThat(primAct == primExp).isTrue();
assertThat(primAct == 1).isTrue();
assertThat(primAct == primExp).isEqualTo(false);
assertThat(primAct != primExp).isEqualTo(true);
assertThat(1 != primAct).isTrue();
assertThat(primAct != primExp).isNotEqualTo(true);
assertThat(primAct > primExp).isNotEqualTo(false);
assertThat(primAct > primExp).isFalse();
assertThat(primAct > 1).isFalse();
assertThat(primAct >= 1).isTrue();
assertThat(primAct >= primExp).isEqualTo(false);
assertThat(1 <= primAct).isFalse();
assertThat(1 > primAct).isTrue();
assertThat(primAct < primExp).isNotEqualTo(true);
assertThat(primAct <= primExp).isNotEqualTo(false);
assertThat(primAct <= primExp).isFalse();
assertThat(primAct <= 1).isFalse();
assertThat(numberObjAct == 1).isTrue();
assertThat(numberObjAct == numberObjExp).isEqualTo(false);
assertThat(numberObjAct != numberObjExp).isEqualTo(true);
assertThat(1 != numberObjAct).isTrue();
assertThat(numberObjAct != numberObjExp).isNotEqualTo(true);
assertThat(numberObjAct > numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct > 1).isFalse();
assertThat(numberObjAct >= numberObjExp).isTrue();
assertThat(numberObjAct >= numberObjExp).isEqualTo(false);
assertThat(1 <= numberObjAct).isFalse();
assertThat(numberObjAct < numberObjExp).isEqualTo(true);
assertThat(numberObjAct < numberObjExp).isNotEqualTo(true);
assertThat(numberObjAct <= numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct <= 1).isFalse();
assertThat(numberObjAct.equals(numberObjExp)).isFalse();
assertThat(stringAct == stringExp).isNotEqualTo(false);
assertThat(stringAct.equals(stringExp)).isEqualTo(true);
assertThat(stringAct != stringExp).isFalse();
assertThat(stringAct == null).isNotEqualTo(true);
assertThat(null == stringAct).isEqualTo(false);
assertThat(null == null).isTrue();
assertThat(!false).isTrue();
}
private void stringStuff() {
String foo = "bar";
assertThat(foo).isEqualTo("");
assertThat(foo).hasSize(0);
assertThat(foo.contains("foobar")).isTrue();
assertThat(foo).contains("foobar");
assertThat(foo.startsWith("foobar")).isTrue();
assertThat(foo).startsWith("foobar");
assertThat(foo.endsWith("foobar")).isTrue();
assertThat(foo).endsWith("foobar");
assertThat(foo.equalsIgnoreCase("foo")).isTrue();
assertThat(foo).isEqualToIgnoringCase("foo");
assertThat(foo.contains("foobar")).isFalse();
assertThat(foo).doesNotContain("foobar");
assertThat(foo.startsWith("foobar")).isFalse();
assertThat(foo).doesNotStartWith("foobar");
assertThat(foo.endsWith("foobar")).isFalse();
assertThat(foo).doesNotEndWith("foobar");
assertThat(foo.equalsIgnoreCase("foo")).isFalse();
assertThat(foo).isNotEqualToIgnoringCase("foo");
ArrayList<String> list = new ArrayList<>();
long[] otherArray = new long[4];
String string = "string";
assertThat(string.length()).isEqualTo(0);
assertThat(string.length()).isZero();
assertThat(string.length()).isNotZero();
assertThat(string.length()).as("hi").isGreaterThan(0);
assertThat(string.length()).isGreaterThanOrEqualTo(1);
assertThat(string.length()).isLessThan(1);
assertThat(string.length()).isLessThanOrEqualTo(0);
assertThat(string.length()).isEqualTo(list.size());
assertThat(string.length()).isEqualTo(otherArray.length);
assertThat(string.length()).isEqualTo(1);
assertThat(string.length()).isGreaterThan(otherArray.length - 1);
assertThat(string.length()).isGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(string.length()).isLessThan(otherArray.length - 3);
assertThat(string.length()).isLessThanOrEqualTo(1 - otherArray.length);
StringBuilder stringBuilder = new StringBuilder();
assertThat(stringBuilder.length()).isEqualTo(0);
assertThat(stringBuilder.length()).isZero();
assertThat(stringBuilder.length()).isNotZero();
assertThat(stringBuilder.length()).as("hi").isGreaterThan(0);
assertThat(stringBuilder.length()).isGreaterThanOrEqualTo(1);
assertThat(stringBuilder.length()).isLessThan(1);
assertThat(stringBuilder.length()).isLessThanOrEqualTo(0);
assertThat(stringBuilder.length()).isEqualTo(list.size());
assertThat(stringBuilder.length()).isEqualTo(otherArray.length);
assertThat(stringBuilder.length()).isEqualTo(1);
assertThat(stringBuilder.length()).isGreaterThan(otherArray.length - 1);
assertThat(stringBuilder.length()).isGreaterThanOrEqualTo(otherArray.length + 1);
assertThat(stringBuilder.length()).isLessThan(otherArray.length - 3);
assertThat(stringBuilder.length()).isLessThanOrEqualTo(1 - otherArray.length);
}
private void java8Optional() {
Optional<String> opt = Optional.empty();
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).isEqualTo(Optional.of("foo"));
assertThat(opt).isEqualTo(Optional.ofNullable("foo"));
assertThat(opt).isNotEqualTo(Optional.of("foo"));
assertThat(opt).isNotEqualTo(Optional.ofNullable("foo"));
assertThat(opt).isEqualTo(Optional.empty());
assertThat(opt).isNotEqualTo(Optional.empty());
assertThat(opt).isPresent();
}
private void assertThatGuavaOptional() {
com.google.common.base.Optional<String> opt = com.google.common.base.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(com.google.common.base.Optional.of("foo"));
assertThat(opt).isEqualTo(com.google.common.base.Optional.fromNullable("foo"));
assertThat(opt).isNotEqualTo(com.google.common.base.Optional.of("foo"));
assertThat(opt).isNotEqualTo(com.google.common.base.Optional.fromNullable("foo"));
assertThat(opt).isEqualTo(com.google.common.base.Optional.absent());
assertThat(opt).isNotEqualTo(com.google.common.base.Optional.absent());
assertThat(opt).isAbsent();
}
private void assertThatInstance() {
String foo = "foo";
assertThat(foo instanceof String).isTrue();
assertThat(foo).isInstanceOf(String.class);
assertThat(foo).isNotInstanceOf(String.class);
}
private void junitAssertions() {
assertFalse(!(new int[3].length == new ArrayList<Integer>().size()));
assertThat(!(new int[3].length == new ArrayList<Integer>().size())).isFalse();
assertThat((new int[3].length == new ArrayList<Integer>().size())).isTrue();
assertThat(new int[3].length).isEqualTo(new ArrayList<Integer>().size());
assertThat(new int[3]).hasSameSizeAs(new ArrayList<Integer>());
assertTrue(true);
assertTrue("message", true);
assertFalse(true);
assertFalse("message", true);
assertEquals(1L, 2L);
assertEquals("message", 1L, 2L);
assertNotEquals(1L, 2L);
assertNotEquals("message", 1L, 2L);
assertEquals(4.0, 4.4, 3.3);
assertThat(3.0).isCloseTo(4.0, Offset.offset(2.3));
assertThat(new int[1]).isEqualTo(new int[2]);
String foo = "foo";
String bar = "bar";
assertTrue(foo == "foo");
assertTrue("oh no!", foo == "foo");
assertFalse(foo == "bar");
assertFalse("boom!", foo == "bar");
assertNull(foo);
assertNull("oh no!", foo);
assertNotNull(foo);
assertNotNull("oh no!", foo);
assertEquals(bar, foo);
assertEquals("equals", bar, foo);
assertNotEquals(bar, foo);
assertNotEquals("equals", bar, foo);
assertSame(bar, foo);
assertSame("same", bar, foo);
assertNotSame(bar, foo);
assertNotSame("same", bar, foo);
assertEquals(1.0, 2.0, 0.1);
assertEquals("equals", 1.0, 2.0, 0.1);
assertEquals(1.0f, 2.0f, 0.1f);
assertEquals("equals", 1.0f, 2.0f, 0.1f);
assertNotEquals(1.0, 2.0);
assertNotEquals(1.0, 2.0, 0.1);
assertNotEquals("equals", 1.0, 2.0);
assertNotEquals("equals", 1.0, 2.0, 0.1);
assertNotEquals(1.0f, 2.0f);
assertNotEquals(1.0f, 2.0f, 0.1f);
assertNotEquals("equals", 1.0f, 2.0f);
assertNotEquals("equals", 1.0f, 2.0f, 0.1f);
assertArrayEquals(new int[2], new int[1]);
assertArrayEquals("array equals", new int[2], new int[1]);
assertArrayEquals(new double[2], new double[1], 1.0);
assertArrayEquals("array equals", new double[2], new double[1], 1.0);
assertArrayEquals(new float[2], new float[1], 1.0f);
assertArrayEquals("array equals", new float[2], new float[1], 1.0f);
assertThat(foo == "foo").isTrue();
assertThat(foo == "foo").as("oh no!").isTrue();
assertThat(foo == "bar").isFalse();
assertThat(foo == "bar").as("boom!").isFalse();
assertThat(foo).isNull();
assertThat(foo).as("oh no!").isNull();
assertThat(foo).isNotNull();
assertThat(foo).as("oh no!").isNotNull();
assertThat(foo).isEqualTo(bar);
assertThat(foo).as("equals").isEqualTo(bar);
assertThat(foo).isNotEqualTo(bar);
assertThat(foo).as("equals").isNotEqualTo(bar);
assertThat(foo).isSameAs(bar);
assertThat(foo).as("same").isSameAs(bar);
assertThat(foo).isNotSameAs(bar);
assertThat(foo).as("same").isNotSameAs(bar);
assertThat(2.0).isEqualTo(1.0);
assertThat(2.0).isCloseTo(1.0, offset(0.1));
assertThat(2.0).as("equals").isEqualTo(1.0);
assertThat(2.0).as("equals").isCloseTo(1.0, offset(0.1));
assertThat(2.0f).isEqualTo(1.0f);
assertThat(2.0f).isCloseTo(1.0f, offset(0.1f));
assertThat(2.0f).as("equals").isEqualTo(1.0f);
assertThat(2.0f).as("equals").isCloseTo(1.0f, offset(0.1f));
assertThat(2.0).isNotEqualTo(1.0);
assertThat(2.0).isNotCloseTo(1.0, offset(0.1));
assertThat(2.0).as("equals").isNotEqualTo(1.0);
assertThat(2.0).as("equals").isNotCloseTo(1.0, offset(0.1));
assertThat(2.0f).isNotEqualTo(1.0f);
assertThat(2.0f).isNotCloseTo(1.0f, offset(0.1f));
assertThat(2.0f).as("equals").isNotEqualTo(1.0f);
assertThat(2.0f).as("equals").isNotCloseTo(1.0f, offset(0.1f));
assertThat(new int[1]).isEqualTo(new int[2]);
assertThat(new int[1]).as("array equals").isEqualTo(new int[2]);
assertThat(new double[1]).containsExactly(new double[2], offset(1.0));
assertThat(new double[1]).as("array equals").containsExactly(new double[2], offset(1.0));
assertThat(new float[1]).containsExactly(new float[2], offset(1.0f));
assertThat(new float[1]).as("array equals").containsExactly(new float[2], offset(1.0f));
assertThat(new Object()).extracting("toString");
assertThat(new Object()).extracting(Object::toString, Object::hashCode);
}
private void findReferences() {
Contact contact = new Contact();
List<Contact> 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;
}
}
}
@@ -11,13 +11,17 @@ import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestJdk import de.platon42.intellij.jupiter.TestJdk
import org.assertj.core.api.Assertions import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.DisplayNameGeneration
import org.junit.jupiter.api.DisplayNameGenerator
import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.ExtendWith
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
@ExtendWith(LightCodeInsightExtension::class) @ExtendWith(LightCodeInsightExtension::class)
@TestDataPath("src/test/resources") @TestDataPath("src/test/resources")
@TestJdk(LanguageLevel.JDK_1_8, annotations = true, useInternal = true) @TestJdk(LanguageLevel.JDK_1_8, annotations = true, useInternal = true)
@AddLocalJarToModule(Assertions::class) @AddLocalJarToModule(Assertions::class)
@DisplayNameGeneration(AbstractCajonTest.CutOffFixtureDisplayNameGenerator::class)
abstract class AbstractCajonTest { abstract class AbstractCajonTest {
// See https://github.com/junit-team/junit5/issues/157, should be resolved with junit5 5.5 M2 // See https://github.com/junit-team/junit5/issues/157, should be resolved with junit5 5.5 M2
@@ -60,8 +64,15 @@ abstract class AbstractCajonTest {
} }
protected fun executeQuickFixes(myFixture: JavaCodeInsightTestFixture, regex: Regex, expectedFixes: Int) { protected fun executeQuickFixes(myFixture: JavaCodeInsightTestFixture, regex: Regex, expectedFixes: Int) {
val quickfixes = myFixture.getAllQuickFixes().filter { it.familyName.matches(regex) } val quickfixes = myFixture.getAllQuickFixes().filter { it.text.matches(regex) }
assertThat(quickfixes).`as`("Fixes matched by $regex: ${myFixture.getAllQuickFixes().map { it.familyName }}").hasSize(expectedFixes) assertThat(quickfixes).`as`("Fixes matched by $regex: ${myFixture.getAllQuickFixes().map { it.text }}").hasSize(expectedFixes)
quickfixes.forEach(myFixture::launchAction) quickfixes.forEach(myFixture::launchAction)
} }
class CutOffFixtureDisplayNameGenerator : DisplayNameGenerator.ReplaceUnderscores() {
override fun generateDisplayNameForMethod(testClass: Class<*>?, testMethod: Method?): String {
val nameForMethod = super.generateDisplayNameForMethod(testClass, testMethod)
return nameForMethod.substringBefore("$")
}
}
} }
@@ -14,8 +14,8 @@ internal class AssertThatBinaryExpressionInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatBinaryExpressionInspection::class.java) myFixture.enableInspections(AssertThatBinaryExpressionInspection::class.java)
myFixture.configureByFile("BinaryExpressionBefore.java") myFixture.configureByFile("BinaryExpressionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Split binary expression out of assertThat()"), 148) executeQuickFixes(myFixture, Regex.fromLiteral("Split binary expression out of assertThat()"), 149)
executeQuickFixes(myFixture, Regex.fromLiteral("Split equals() expression out of assertThat()"), 12) executeQuickFixes(myFixture, Regex.fromLiteral("Split equals() expression out of assertThat()"), 13)
myFixture.checkResultByFile("BinaryExpressionAfter.java") myFixture.checkResultByFile("BinaryExpressionAfter.java")
} }
} }
@@ -14,7 +14,7 @@ internal class AssertThatBooleanConditionInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatBooleanConditionInspection::class.java) myFixture.enableInspections(AssertThatBooleanConditionInspection::class.java)
myFixture.configureByFile("BooleanConditionBefore.java") myFixture.configureByFile("BooleanConditionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isTrue()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isTrue()"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isFalse()"), 5) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isFalse()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isTrue()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isTrue()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isFalse()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isFalse()"), 4)
@@ -0,0 +1,29 @@
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 AssertThatCollectionOrMapExpressionInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/CollectionMapExpression")
internal fun assertThat_with_certain_Collection_and_Map_methods(@MyFixture myFixture: JavaCodeInsightTestFixture) {
runTest {
myFixture.enableInspections(AssertThatCollectionOrMapExpressionInspection::class.java)
myFixture.configureByFile("CollectionMapExpressionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of actual expression and use assertThat().isEmpty() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().contains() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsAll() of actual expression and use assertThat().containsAll() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsKey() of actual expression and use assertThat().containsKey() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsValue() of actual expression and use assertThat().containsValue() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of actual expression and use assertThat().isNotEmpty() instead"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().doesNotContain() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsKey() of actual expression and use assertThat().doesNotContainKey() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove containsValue() of actual expression and use assertThat().doesNotContainValue() instead"), 2)
myFixture.checkResultByFile("CollectionMapExpressionAfter.java")
}
}
}
@@ -14,7 +14,7 @@ internal class AssertThatEnumerableIsEmptyInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatEnumerableIsEmptyInspection::class.java) myFixture.enableInspections(AssertThatEnumerableIsEmptyInspection::class.java)
myFixture.configureByFile("EnumerableIsEmptyBefore.java") myFixture.configureByFile("EnumerableIsEmptyBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSize() with isEmpty()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSize() with isEmpty()"), 5)
myFixture.checkResultByFile("EnumerableIsEmptyAfter.java") myFixture.checkResultByFile("EnumerableIsEmptyAfter.java")
} }
} }
@@ -17,19 +17,12 @@ internal class AssertThatGuavaOptionalInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java) myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java)
myFixture.configureByFile("GuavaOptionalBefore.java") myFixture.configureByFile("GuavaOptionalBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with Guava assertThat().isPresent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove isPresent() of actual expression and use assertThat().isPresent() instead"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with Guava assertThat().isPresent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove isPresent() of actual expression and use assertThat().isAbsent() instead"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isPresent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().contains() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with Guava assertThat().isPresent()"), 1) executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap expected expression and replace isEqualTo() with contains()"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with Guava assertThat().isAbsent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with Guava assertThat().isAbsent()"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isAbsent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with Guava assertThat().isPresent()"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with Guava assertThat().isAbsent()"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with Guava assertThat().isAbsent()"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isTrue() with Guava assertThat().isPresent()"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isFalse() with Guava assertThat().isAbsent()"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with Guava assertThat().contains()"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove unwrapping of expected expression and replace isEqualTo() with contains()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove unwrapping of expected expression and replace isEqualTo() with Guava assertThat().contains()"), 2)
myFixture.checkResultByFile("GuavaOptionalAfter.java") myFixture.checkResultByFile("GuavaOptionalAfter.java")
} }
} }
@@ -39,7 +32,8 @@ internal class AssertThatGuavaOptionalInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java) myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java)
myFixture.configureByFile("WithoutPriorGuavaImportBefore.java") myFixture.configureByFile("WithoutPriorGuavaImportBefore.java")
executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 7) executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 4)
executeQuickFixes(myFixture, Regex("Remove .*"), 3)
myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java") myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java")
} }
} }
@@ -50,7 +44,8 @@ internal class AssertThatGuavaOptionalInspectionTest : AbstractCajonTest() {
myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java) myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java)
myFixture.configureByFile("WithoutPriorGuavaImportBefore.java") myFixture.configureByFile("WithoutPriorGuavaImportBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with Guava assertThat().isAbsent()"), 1) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with Guava assertThat().isAbsent()"), 1)
executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 6) executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 3)
executeQuickFixes(myFixture, Regex("Remove .*"), 3)
myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java") myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java")
} }
} }
@@ -14,8 +14,8 @@ internal class AssertThatInstanceOfInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatInstanceOfInspection::class.java) myFixture.enableInspections(AssertThatInstanceOfInspection::class.java)
myFixture.configureByFile("InstanceOfBefore.java") myFixture.configureByFile("InstanceOfBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace instanceof expression by assertThat().isInstanceOf()"), 5) executeQuickFixes(myFixture, Regex.fromLiteral("Remove instanceof in actual expression and use assertThat().isInstanceOf() instead"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace instanceof expression by assertThat().isNotInstanceOf()"), 6) executeQuickFixes(myFixture, Regex.fromLiteral("Remove instanceof in actual expression and use assertThat().isNotInstanceOf() instead"), 6)
myFixture.checkResultByFile("InstanceOfAfter.java") myFixture.checkResultByFile("InstanceOfAfter.java")
} }
} }
@@ -14,7 +14,7 @@ internal class AssertThatInvertedBooleanConditionInspectionTest : AbstractCajonT
runTest { runTest {
myFixture.enableInspections(AssertThatInvertedBooleanConditionInspection::class.java) myFixture.enableInspections(AssertThatInvertedBooleanConditionInspection::class.java)
myFixture.configureByFile("InvertedBooleanConditionBefore.java") myFixture.configureByFile("InvertedBooleanConditionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Invert condition in assertThat()"), 21) executeQuickFixes(myFixture, Regex.fromLiteral("Invert condition in assertThat()"), 25)
myFixture.checkResultByFile("InvertedBooleanConditionAfter.java") myFixture.checkResultByFile("InvertedBooleanConditionAfter.java")
} }
} }
@@ -14,17 +14,13 @@ internal class AssertThatJava8OptionalInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatJava8OptionalInspection::class.java) myFixture.enableInspections(AssertThatJava8OptionalInspection::class.java)
myFixture.configureByFile("Java8OptionalBefore.java") myFixture.configureByFile("Java8OptionalBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with isPresent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove isPresent() of actual expression and use assertThat().isPresent() instead"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with isPresent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove isPresent() of actual expression and use assertThat().isNotPresent() instead"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isEqualTo() with isNotPresent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().contains() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Unwrap actual expression and replace isNotEqualTo() with isNotPresent()"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsSame() instead"), 1)
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 isEqualTo() with isNotPresent()"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isPresent()"), 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("Remove unwrapping of 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("Java8OptionalAfter.java") myFixture.checkResultByFile("Java8OptionalAfter.java")
} }
} }
@@ -14,8 +14,8 @@ internal class AssertThatObjectIsNullOrNotNullInspectionTest : AbstractCajonTest
runTest { runTest {
myFixture.enableInspections(AssertThatObjectIsNullOrNotNullInspection::class.java) myFixture.enableInspections(AssertThatObjectIsNullOrNotNullInspection::class.java)
myFixture.configureByFile("ObjectIsNullOrNotNullBefore.java") myFixture.configureByFile("ObjectIsNullOrNotNullBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isNull()"), 3) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isNull()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isNotNull()"), 3) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isNotNull()"), 5)
myFixture.checkResultByFile("ObjectIsNullOrNotNullAfter.java") myFixture.checkResultByFile("ObjectIsNullOrNotNullAfter.java")
} }
} }
@@ -4,6 +4,8 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import de.platon42.intellij.jupiter.MyFixture import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataSubPath import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.cajon.AbstractCajonTest import de.platon42.intellij.plugins.cajon.AbstractCajonTest
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.extrakting
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
internal class AssertThatSizeInspectionTest : AbstractCajonTest() { internal class AssertThatSizeInspectionTest : AbstractCajonTest() {
@@ -14,6 +16,8 @@ internal class AssertThatSizeInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatSizeInspection::class.java) myFixture.enableInspections(AssertThatSizeInspection::class.java)
myFixture.configureByFile("SizeBefore.java") myFixture.configureByFile("SizeBefore.java")
assertThat(myFixture.doHighlighting()).extrakting { it.description }.containsOnlyOnce("Try to operate on the iterable itself rather than its size")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isEmpty()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isEmpty()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isZero() with isEmpty()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isZero() with isEmpty()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotZero() with isNotEmpty()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotZero() with isNotEmpty()"), 4)
@@ -27,7 +31,7 @@ internal class AssertThatSizeInspectionTest : AbstractCajonTest() {
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isGreaterThanOrEqualTo() with hasSizeGreaterThanOrEqualTo()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isGreaterThanOrEqualTo() with hasSizeGreaterThanOrEqualTo()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThan() with hasSizeLessThan()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThan() with hasSizeLessThan()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThanOrEqualTo() with hasSizeLessThanOrEqualTo()"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThanOrEqualTo() with hasSizeLessThanOrEqualTo()"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove size determination of expected expression and replace hasSize() with hasSameSizeAs()"), 12) executeQuickFixes(myFixture, Regex.fromLiteral("Remove size determination of expected expression and replace hasSize() with hasSameSizeAs()"), 14)
myFixture.checkResultByFile("SizeAfter.java") myFixture.checkResultByFile("SizeAfter.java")
} }
} }
@@ -14,20 +14,20 @@ internal class AssertThatStringExpressionInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatStringExpressionInspection::class.java) myFixture.enableInspections(AssertThatStringExpressionInspection::class.java)
myFixture.configureByFile("StringExpressionBefore.java") myFixture.configureByFile("StringExpressionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of expected expression and use assertThat().isEmpty() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of actual expression and use assertThat().isEmpty() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove equals() of expected expression and use assertThat().isEqualTo() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove equals() of actual expression and use assertThat().isEqualTo() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove equalsIgnoreCase() of expected expression and use assertThat().isEqualToIgnoringCase() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove equalsIgnoreCase() of actual expression and use assertThat().isEqualToIgnoringCase() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contentEquals() of expected expression and use assertThat().isEqualTo() instead"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Remove contentEquals() of actual expression and use assertThat().isEqualTo() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of expected expression and use assertThat().contains() instead"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().contains() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove startsWith() of expected expression and use assertThat().startsWith() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove startsWith() of actual expression and use assertThat().startsWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove endsWith() of expected expression and use assertThat().endsWith() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove endsWith() of actual expression and use assertThat().endsWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of expected expression and use assertThat().isNotEmpty() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of actual expression and use assertThat().isNotEmpty() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove equals() of expected expression and use assertThat().isNotEqualTo() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove equals() of actual expression and use assertThat().isNotEqualTo() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove equalsIgnoreCase() of expected expression and use assertThat().isNotEqualToIgnoringCase() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove equalsIgnoreCase() of actual expression and use assertThat().isNotEqualToIgnoringCase() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contentEquals() of expected expression and use assertThat().isNotEqualTo() instead"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Remove contentEquals() of actual expression and use assertThat().isNotEqualTo() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of expected expression and use assertThat().doesNotContain() instead"), 4) executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().doesNotContain() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove startsWith() of expected expression and use assertThat().doesNotStartWith() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove startsWith() of actual expression and use assertThat().doesNotStartWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove endsWith() of expected expression and use assertThat().doesNotEndWith() instead"), 2) executeQuickFixes(myFixture, Regex.fromLiteral("Remove endsWith() of actual expression and use assertThat().doesNotEndWith() instead"), 3)
myFixture.checkResultByFile("StringExpressionAfter.java") myFixture.checkResultByFile("StringExpressionAfter.java")
} }
} }
@@ -4,6 +4,8 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import de.platon42.intellij.jupiter.MyFixture import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataSubPath import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.cajon.AbstractCajonTest import de.platon42.intellij.plugins.cajon.AbstractCajonTest
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.extrakting
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
internal class AssertThatStringIsEmptyInspectionTest : AbstractCajonTest() { internal class AssertThatStringIsEmptyInspectionTest : AbstractCajonTest() {
@@ -14,8 +16,13 @@ internal class AssertThatStringIsEmptyInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(AssertThatStringIsEmptyInspection::class.java) myFixture.enableInspections(AssertThatStringIsEmptyInspection::class.java)
myFixture.configureByFile("StringIsEmptyBefore.java") myFixture.configureByFile("StringIsEmptyBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isEmpty()"), 2) val highlights = myFixture.doHighlighting()
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSize() with isEmpty()"), 2) .asSequence()
.filter { it.description?.contains(" can be simplified to") ?: false }
.toList()
assertThat(highlights).hasSize(6).extrakting { it.text }.doesNotContain("assertThat")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isEmpty()"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSize() with isEmpty()"), 3)
myFixture.checkResultByFile("StringIsEmptyAfter.java") myFixture.checkResultByFile("StringIsEmptyAfter.java")
} }
} }
@@ -0,0 +1,24 @@
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(Assertions::class, Test::class, org.junit.Test::class)
internal class AssumeThatInsteadOfReturnInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/AssumeThat")
internal fun conditional_returns_can_be_replaced_by_assumeThat(@MyFixture myFixture: JavaCodeInsightTestFixture) {
runTest {
myFixture.enableInspections(AssumeThatInsteadOfReturnInspection::class.java)
myFixture.configureByFile("AssumeThatBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace if statement by assumeTrue()"), 5)
myFixture.checkResultByFile("AssumeThatAfter.java")
}
}
}
@@ -18,7 +18,7 @@ internal class JUnitAssertToAssertJInspectionTest : AbstractCajonTest() {
runTest { runTest {
myFixture.enableInspections(JUnitAssertToAssertJInspection::class.java) myFixture.enableInspections(JUnitAssertToAssertJInspection::class.java)
myFixture.configureByFile("JUnitAssertToAssertJInspectionBefore.java") myFixture.configureByFile("JUnitAssertToAssertJInspectionBefore.java")
executeQuickFixes(myFixture, Regex("Replace .*"), 38) executeQuickFixes(myFixture, Regex("Convert assert.*\\(\\) to assertThat\\(\\).*"), 38)
myFixture.checkResultByFile("JUnitAssertToAssertJInspectionAfter.java") myFixture.checkResultByFile("JUnitAssertToAssertJInspectionAfter.java")
} }
} }
@@ -10,11 +10,11 @@ internal class JoinAssertThatStatementsInspectionTest : AbstractCajonTest() {
@Test @Test
@TestDataSubPath("inspections/JoinStatements") @TestDataSubPath("inspections/JoinStatements")
internal fun assertThat_size_of_array_or_collection_can_be_simplified(@MyFixture myFixture: JavaCodeInsightTestFixture) { internal fun assertThat_statements_can_be_joined_together(@MyFixture myFixture: JavaCodeInsightTestFixture) {
runTest { runTest {
myFixture.enableInspections(JoinAssertThatStatementsInspection::class.java) myFixture.enableInspections(JoinAssertThatStatementsInspection::class.java)
myFixture.configureByFile("JoinStatementsBefore.java") myFixture.configureByFile("JoinStatementsBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Join assertThat() statements"), 6) executeQuickFixes(myFixture, Regex.fromLiteral("Join assertThat() statements"), 5)
myFixture.checkResultByFile("JoinStatementsAfter.java") myFixture.checkResultByFile("JoinStatementsAfter.java")
} }
} }
@@ -0,0 +1,19 @@
package org.assertj.core.api
import org.assertj.core.groups.FieldsOrPropertiesExtractor
import java.util.*
// Workaround for ambiguous method signature of .extracting() see https://github.com/joel-costigliola/assertj-core/issues/1499
fun <SELF : AbstractIterableAssert<SELF, ACTUAL, ELEMENT, ELEMENT_ASSERT>,
ACTUAL : Iterable<ELEMENT>,
ELEMENT,
ELEMENT_ASSERT : AbstractAssert<ELEMENT_ASSERT, ELEMENT>,
V>
AbstractIterableAssert<SELF, ACTUAL, ELEMENT, ELEMENT_ASSERT>.extrakting(extractor: (ELEMENT) -> V): AbstractListAssert<*, List<V>, V, ObjectAssert<V>> {
val values = FieldsOrPropertiesExtractor.extract(actual, extractor)
if (actual is SortedSet<*>) {
usingDefaultElementComparator()
}
@Suppress("UNCHECKED_CAST")
return newListAssertInstance(values).withAssertionState(myself) as AbstractListAssert<*, List<V>, V, ObjectAssert<V>>
}
@@ -0,0 +1,158 @@
import org.junit.Test;
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
public class AssumeThat {
@Test
public void junit4_return_very_early() {
assumeThat(new Random().nextBoolean()).isFalse();
System.out.println("sweet!"); // single else statement
String foobar = System.getProperty("foobar");
assertThat(foobar).isNotEmpty();
}
@Test
public void junit4_return_in_else_branch_with_declaration_in_code_block_and_lots_of_comments() {
// primary comments
assumeThat(new Random().nextBoolean()).isTrue();
{
// Block start comment will be retained
String anotherString = "narf"; // This one is likely to be kept
assertThat(foobar).isNotEmpty();
assertThat(foobar).isEqualTo(anotherString);
// Block end comment is also going to be retained
} /* weird places */
// well, well, let's do some checks
String foobar = System.getProperty("foobar");
assertThat(foobar).isNotEmpty();
}
@org.junit.jupiter.api.Test
public void junit5_return_after_call_without_else_branch() {
String foobar = System.getProperty("car_manufacturer");
assumeThat(foobar.equals("Volkswagen")).isFalse();
assertThat(foobar).isNotEmpty();
}
@org.junit.jupiter.api.Test
public void junit5_return_with_empty_else_block() {
String foobar = System.getProperty("car_manufacturer");
assumeThat(foobar.equals("Volkswagen")).isFalse();
assertThat(foobar).isNotEmpty();
}
@org.junit.jupiter.api.TestTemplate
public void junit5_return_inside_recursion_with_comments() {
String foobar = System.getProperty("car_manufacturer");
if (foobar != null) {
assumeThat(!foobar.equals("Volkswagen")).isTrue();
// I doubted this comment will be retained -- but surprise!
assertThat(foobar).isNotEmpty();
// we might keep this one alright.
foobar = "narf";
// And the final one? Again what learned.
}
assertThat(foobar).startsWith("another ecology rapist");
if(foobar.length() == 0)
{
return;
}
assertThat(foobar).endsWith("!!!");
}
@Test
public void junit4_return_after_assertion() {
String foobar = System.getProperty("car_manufacturer");
assertThat(foobar).isNotNull();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_return_after_assertions_in_subroutine() {
String foobar = System.getProperty("car_manufacturer");
assertStuff(foobar);
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_return_after_assertions_in_deep_subroutine() {
String foobar = System.getProperty("car_manufacturer");
firstMethod();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_return_after_assertions_in_deep_subroutine_with_recursion() {
String foobar = System.getProperty("car_manufacturer");
firstMethodWithPotentialRecursion();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_no_harm_with_infinite_recursion() {
String foobar = System.getProperty("car_manufacturer");
infiniteRecursion();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
private void assertStuff(String foobar) {
if (new Random().nextBoolean()) {
assertThat(foobar).isNotEmpty();
} else {
assertThat(foobar).isNull();
}
}
private void firstMethod() {
if (new Random().nextBoolean()) {
assertStuff("narf");
}
}
private void firstMethodWithPotentialRecursion() {
if (new Random().nextBoolean()) {
assertStuff("narf");
} else {
infiniteRecursion();
}
}
private void infiniteRecursion() {
secondaryRecursion();
secondaryRecursion();
}
private void secondaryRecursion() {
infiniteRecursion();
infiniteRecursion();
}
}
@@ -0,0 +1,163 @@
import org.junit.Test;
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
public class AssumeThat {
@Test
public void junit4_return_very_early() {
if (new Random().nextBoolean()) {
return;
} else System.out.println("sweet!"); // single else statement
String foobar = System.getProperty("foobar");
assertThat(foobar).isNotEmpty();
}
@Test
public void junit4_return_in_else_branch_with_declaration_in_code_block_and_lots_of_comments() {
// primary comments
if (new Random().nextBoolean()) /* strange place for a comment */ {
// Block start comment will be retained
String anotherString = "narf"; // This one is likely to be kept
assertThat(foobar).isNotEmpty();
assertThat(foobar).isEqualTo(anotherString);
// Block end comment is also going to be retained
} /* weird places */ else /* more weird places */ { // this one is lost
return; // Would be sweet to keep this comment, too.
} // another comment lost
// well, well, let's do some checks
String foobar = System.getProperty("foobar");
assertThat(foobar).isNotEmpty();
}
@org.junit.jupiter.api.Test
public void junit5_return_after_call_without_else_branch() {
String foobar = System.getProperty("car_manufacturer");
if (foobar.equals("Volkswagen")) return; // no need for Volkswagen to perform tests
assertThat(foobar).isNotEmpty();
}
@org.junit.jupiter.api.Test
public void junit5_return_with_empty_else_block() {
String foobar = System.getProperty("car_manufacturer");
if (foobar.equals("Volkswagen")) return; else {}
assertThat(foobar).isNotEmpty();
}
@org.junit.jupiter.api.TestTemplate
public void junit5_return_inside_recursion_with_comments() {
String foobar = System.getProperty("car_manufacturer");
if (foobar != null) {
if (!foobar.equals("Volkswagen")) {
// I doubted this comment will be retained -- but surprise!
assertThat(foobar).isNotEmpty();
// we might keep this one alright.
foobar = "narf";
// And the final one? Again what learned.
} else {
// ooops, how did that happen?
return;
}
}
assertThat(foobar).startsWith("another ecology rapist");
if(foobar.length() == 0)
{
return;
}
assertThat(foobar).endsWith("!!!");
}
@Test
public void junit4_return_after_assertion() {
String foobar = System.getProperty("car_manufacturer");
assertThat(foobar).isNotNull();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_return_after_assertions_in_subroutine() {
String foobar = System.getProperty("car_manufacturer");
assertStuff(foobar);
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_return_after_assertions_in_deep_subroutine() {
String foobar = System.getProperty("car_manufacturer");
firstMethod();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_return_after_assertions_in_deep_subroutine_with_recursion() {
String foobar = System.getProperty("car_manufacturer");
firstMethodWithPotentialRecursion();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
@Test
public void junit4_no_harm_with_infinite_recursion() {
String foobar = System.getProperty("car_manufacturer");
infiniteRecursion();
if (!foobar.equals("Volkswagen")) {
assertThat(foobar).isNotEmpty();
} else {
return;
}
assertThat(foobar).startsWith("another ecology rapist");
}
private void assertStuff(String foobar) {
if (new Random().nextBoolean()) {
assertThat(foobar).isNotEmpty();
} else {
assertThat(foobar).isNull();
}
}
private void firstMethod() {
if (new Random().nextBoolean()) {
assertStuff("narf");
}
}
private void firstMethodWithPotentialRecursion() {
if (new Random().nextBoolean()) {
assertStuff("narf");
} else {
infiniteRecursion();
}
}
private void infiniteRecursion() {
secondaryRecursion();
secondaryRecursion();
}
private void secondaryRecursion() {
infiniteRecursion();
infiniteRecursion();
}
}
@@ -10,7 +10,7 @@ public class BinaryExpression {
String stringExp = "foo"; String stringExp = "foo";
String stringAct = "bar"; String stringAct = "bar";
assertThat(primAct).isEqualTo(primExp); assertThat(primAct).as("doh!").isEqualTo(primExp);
assertThat(primAct).isEqualTo(primExp); assertThat(primAct).isEqualTo(primExp);
assertThat(primAct).isEqualTo(primExp); assertThat(primAct).isEqualTo(primExp);
assertThat(primAct).isEqualTo(primExp); assertThat(primAct).isEqualTo(primExp);
@@ -25,7 +25,7 @@ public class BinaryExpression {
assertThat(primAct).isNotEqualTo(1); assertThat(primAct).isNotEqualTo(1);
assertThat(primAct).isNotEqualTo(1); assertThat(primAct).isNotEqualTo(1);
assertThat(primAct).isNotEqualTo(primExp); assertThat(primAct).as("doh!").isNotEqualTo(primExp);
assertThat(primAct).isNotEqualTo(primExp); assertThat(primAct).isNotEqualTo(primExp);
assertThat(primAct).isNotEqualTo(primExp); assertThat(primAct).isNotEqualTo(primExp);
assertThat(primAct).isNotEqualTo(1); assertThat(primAct).isNotEqualTo(1);
@@ -36,7 +36,7 @@ public class BinaryExpression {
assertThat(primAct).isEqualTo(1); assertThat(primAct).isEqualTo(1);
assertThat(primAct).isEqualTo(1); assertThat(primAct).isEqualTo(1);
assertThat(primAct).isGreaterThan(primExp); assertThat(primAct).as("doh!").isGreaterThan(primExp);
assertThat(primAct).isGreaterThan(primExp); assertThat(primAct).isGreaterThan(primExp);
assertThat(primAct).isGreaterThan(primExp); assertThat(primAct).isGreaterThan(primExp);
assertThat(primAct).isGreaterThan(1); assertThat(primAct).isGreaterThan(1);
@@ -47,7 +47,7 @@ public class BinaryExpression {
assertThat(primAct).isLessThanOrEqualTo(1); assertThat(primAct).isLessThanOrEqualTo(1);
assertThat(primAct).isLessThanOrEqualTo(1); assertThat(primAct).isLessThanOrEqualTo(1);
assertThat(primAct).isGreaterThanOrEqualTo(primExp); assertThat(primAct).as("doh!").isGreaterThanOrEqualTo(primExp);
assertThat(primAct).isGreaterThanOrEqualTo(primExp); assertThat(primAct).isGreaterThanOrEqualTo(primExp);
assertThat(primAct).isGreaterThanOrEqualTo(primExp); assertThat(primAct).isGreaterThanOrEqualTo(primExp);
assertThat(primAct).isGreaterThanOrEqualTo(1); assertThat(primAct).isGreaterThanOrEqualTo(1);
@@ -58,7 +58,7 @@ public class BinaryExpression {
assertThat(primAct).isLessThan(1); assertThat(primAct).isLessThan(1);
assertThat(primAct).isLessThan(1); assertThat(primAct).isLessThan(1);
assertThat(primAct).isLessThan(primExp); assertThat(primAct).as("doh!").isLessThan(primExp);
assertThat(primAct).isLessThan(primExp); assertThat(primAct).isLessThan(primExp);
assertThat(primAct).isLessThan(primExp); assertThat(primAct).isLessThan(primExp);
assertThat(primAct).isLessThan(1); assertThat(primAct).isLessThan(1);
@@ -69,7 +69,7 @@ public class BinaryExpression {
assertThat(primAct).isGreaterThanOrEqualTo(1); assertThat(primAct).isGreaterThanOrEqualTo(1);
assertThat(primAct).isGreaterThanOrEqualTo(1); assertThat(primAct).isGreaterThanOrEqualTo(1);
assertThat(primAct).isLessThanOrEqualTo(primExp); assertThat(primAct).as("doh!").isLessThanOrEqualTo(primExp);
assertThat(primAct).isLessThanOrEqualTo(primExp); assertThat(primAct).isLessThanOrEqualTo(primExp);
assertThat(primAct).isLessThanOrEqualTo(primExp); assertThat(primAct).isLessThanOrEqualTo(primExp);
assertThat(primAct).isLessThanOrEqualTo(1); assertThat(primAct).isLessThanOrEqualTo(1);
@@ -80,7 +80,7 @@ public class BinaryExpression {
assertThat(primAct).isGreaterThan(1); assertThat(primAct).isGreaterThan(1);
assertThat(primAct).isGreaterThan(1); assertThat(primAct).isGreaterThan(1);
assertThat(numberObjAct).isEqualTo(numberObjExp); assertThat(numberObjAct).as("doh!").isEqualTo(numberObjExp);
assertThat(numberObjAct).isEqualTo(numberObjExp); assertThat(numberObjAct).isEqualTo(numberObjExp);
assertThat(numberObjAct).isEqualTo(numberObjExp); assertThat(numberObjAct).isEqualTo(numberObjExp);
assertThat(numberObjAct).isEqualTo(1); assertThat(numberObjAct).isEqualTo(1);
@@ -91,7 +91,7 @@ public class BinaryExpression {
assertThat(numberObjAct).isNotEqualTo(1); assertThat(numberObjAct).isNotEqualTo(1);
assertThat(numberObjAct).isNotEqualTo(1); assertThat(numberObjAct).isNotEqualTo(1);
assertThat(numberObjAct).isNotEqualTo(numberObjExp); assertThat(numberObjAct).as("doh!").isNotEqualTo(numberObjExp);
assertThat(numberObjAct).isNotEqualTo(numberObjExp); assertThat(numberObjAct).isNotEqualTo(numberObjExp);
assertThat(numberObjAct).isNotEqualTo(numberObjExp); assertThat(numberObjAct).isNotEqualTo(numberObjExp);
assertThat(numberObjAct).isNotEqualTo(1); assertThat(numberObjAct).isNotEqualTo(1);
@@ -102,7 +102,7 @@ public class BinaryExpression {
assertThat(numberObjAct).isEqualTo(1); assertThat(numberObjAct).isEqualTo(1);
assertThat(numberObjAct).isEqualTo(1); assertThat(numberObjAct).isEqualTo(1);
assertThat(numberObjAct).isGreaterThan(numberObjExp); assertThat(numberObjAct).as("doh!").isGreaterThan(numberObjExp);
assertThat(numberObjAct).isGreaterThan(numberObjExp); assertThat(numberObjAct).isGreaterThan(numberObjExp);
assertThat(numberObjAct).isGreaterThan(numberObjExp); assertThat(numberObjAct).isGreaterThan(numberObjExp);
assertThat(numberObjAct).isGreaterThan(1); assertThat(numberObjAct).isGreaterThan(1);
@@ -113,7 +113,7 @@ public class BinaryExpression {
assertThat(numberObjAct).isLessThanOrEqualTo(1); assertThat(numberObjAct).isLessThanOrEqualTo(1);
assertThat(numberObjAct).isLessThanOrEqualTo(1); assertThat(numberObjAct).isLessThanOrEqualTo(1);
assertThat(numberObjAct).isGreaterThanOrEqualTo(numberObjExp); assertThat(numberObjAct).as("doh!").isGreaterThanOrEqualTo(numberObjExp);
assertThat(numberObjAct).isGreaterThanOrEqualTo(numberObjExp); assertThat(numberObjAct).isGreaterThanOrEqualTo(numberObjExp);
assertThat(numberObjAct).isGreaterThanOrEqualTo(numberObjExp); assertThat(numberObjAct).isGreaterThanOrEqualTo(numberObjExp);
assertThat(numberObjAct).isGreaterThanOrEqualTo(1); assertThat(numberObjAct).isGreaterThanOrEqualTo(1);
@@ -124,7 +124,7 @@ public class BinaryExpression {
assertThat(numberObjAct).isLessThan(1); assertThat(numberObjAct).isLessThan(1);
assertThat(numberObjAct).isLessThan(1); assertThat(numberObjAct).isLessThan(1);
assertThat(numberObjAct).isLessThan(numberObjExp); assertThat(numberObjAct).as("doh!").isLessThan(numberObjExp);
assertThat(numberObjAct).isLessThan(numberObjExp); assertThat(numberObjAct).isLessThan(numberObjExp);
assertThat(numberObjAct).isLessThan(numberObjExp); assertThat(numberObjAct).isLessThan(numberObjExp);
assertThat(numberObjAct).isLessThan(1); assertThat(numberObjAct).isLessThan(1);
@@ -135,7 +135,7 @@ public class BinaryExpression {
assertThat(numberObjAct).isGreaterThanOrEqualTo(1); assertThat(numberObjAct).isGreaterThanOrEqualTo(1);
assertThat(numberObjAct).isGreaterThanOrEqualTo(1); assertThat(numberObjAct).isGreaterThanOrEqualTo(1);
assertThat(numberObjAct).isLessThanOrEqualTo(numberObjExp); assertThat(numberObjAct).as("doh!").isLessThanOrEqualTo(numberObjExp);
assertThat(numberObjAct).isLessThanOrEqualTo(numberObjExp); assertThat(numberObjAct).isLessThanOrEqualTo(numberObjExp);
assertThat(numberObjAct).isLessThanOrEqualTo(numberObjExp); assertThat(numberObjAct).isLessThanOrEqualTo(numberObjExp);
assertThat(numberObjAct).isLessThanOrEqualTo(1); assertThat(numberObjAct).isLessThanOrEqualTo(1);
@@ -146,42 +146,42 @@ public class BinaryExpression {
assertThat(numberObjAct).isGreaterThan(1); assertThat(numberObjAct).isGreaterThan(1);
assertThat(numberObjAct).isGreaterThan(1); assertThat(numberObjAct).isGreaterThan(1);
assertThat(numberObjAct).isEqualTo(numberObjExp); assertThat(numberObjAct).as("doh!").isEqualTo(numberObjExp);
assertThat(numberObjAct).isEqualTo(numberObjExp); assertThat(numberObjAct).isEqualTo(numberObjExp);
assertThat(numberObjAct).isEqualTo(numberObjExp); assertThat(numberObjAct).isEqualTo(numberObjExp);
assertThat(numberObjAct).isNotEqualTo(numberObjExp); assertThat(numberObjAct).isNotEqualTo(numberObjExp);
assertThat(numberObjAct).isNotEqualTo(numberObjExp); assertThat(numberObjAct).isNotEqualTo(numberObjExp);
assertThat(numberObjAct).isNotEqualTo(numberObjExp); assertThat(numberObjAct).isNotEqualTo(numberObjExp);
assertThat(stringAct).isSameAs(stringExp); assertThat(stringAct).as("doh!").isSameAs(stringExp);
assertThat(stringAct).isSameAs(stringExp); assertThat(stringAct).isSameAs(stringExp);
assertThat(stringAct).isSameAs(stringExp); assertThat(stringAct).isSameAs(stringExp);
assertThat(stringAct).isNotSameAs(stringExp); assertThat(stringAct).isNotSameAs(stringExp);
assertThat(stringAct).isNotSameAs(stringExp); assertThat(stringAct).isNotSameAs(stringExp);
assertThat(stringAct).isNotSameAs(stringExp); assertThat(stringAct).isNotSameAs(stringExp);
assertThat(stringAct).isEqualTo(stringExp); assertThat(stringAct).as("doh!").isEqualTo(stringExp);
assertThat(stringAct).isEqualTo(stringExp); assertThat(stringAct).isEqualTo(stringExp);
assertThat(stringAct).isEqualTo(stringExp); assertThat(stringAct).isEqualTo(stringExp);
assertThat(stringAct).isNotEqualTo(stringExp); assertThat(stringAct).isNotEqualTo(stringExp);
assertThat(stringAct).isNotEqualTo(stringExp); assertThat(stringAct).isNotEqualTo(stringExp);
assertThat(stringAct).isNotEqualTo(stringExp); assertThat(stringAct).isNotEqualTo(stringExp);
assertThat(stringAct).isNotSameAs(stringExp); assertThat(stringAct).as("doh!").isNotSameAs(stringExp);
assertThat(stringAct).isNotSameAs(stringExp); assertThat(stringAct).isNotSameAs(stringExp);
assertThat(stringAct).isNotSameAs(stringExp); assertThat(stringAct).isNotSameAs(stringExp);
assertThat(stringAct).isSameAs(stringExp); assertThat(stringAct).isSameAs(stringExp);
assertThat(stringAct).isSameAs(stringExp); assertThat(stringAct).isSameAs(stringExp);
assertThat(stringAct).isSameAs(stringExp); assertThat(stringAct).isSameAs(stringExp);
assertThat(stringAct).isNull(); assertThat(stringAct).as("doh!").isNull();
assertThat(stringAct).isNull(); assertThat(stringAct).isNull();
assertThat(stringAct).isNull(); assertThat(stringAct).isNull();
assertThat(stringAct).isNotNull(); assertThat(stringAct).isNotNull();
assertThat(stringAct).isNotNull(); assertThat(stringAct).isNotNull();
assertThat(stringAct).isNotNull(); assertThat(stringAct).isNotNull();
assertThat(stringAct).isNull(); assertThat(stringAct).as("doh!").isNull();
assertThat(stringAct).isNull(); assertThat(stringAct).isNull();
assertThat(stringAct).isNull(); assertThat(stringAct).isNull();
assertThat(stringAct).isNotNull(); assertThat(stringAct).isNotNull();
@@ -190,5 +190,10 @@ public class BinaryExpression {
assertThat(null == null).isTrue(); assertThat(null == null).isTrue();
assertThat(!false).isTrue(); assertThat(!false).isTrue();
assertThat(primAct).as("doh!").isEqualTo(primExp).isEqualTo(primExp);
assertThat(primAct == primExp).isFalse().as("doh!").isEqualTo(true);
assertThat(numberObjAct).as("doh!").isEqualTo(numberObjExp).isEqualTo(numberObjExp);
} }
} }
@@ -10,7 +10,7 @@ public class BinaryExpression {
String stringExp = "foo"; String stringExp = "foo";
String stringAct = "bar"; String stringAct = "bar";
assertThat(primAct == primExp).isTrue(); assertThat(primAct == primExp).as("doh!").isTrue();
assertThat(primAct == primExp).isEqualTo(true); assertThat(primAct == primExp).isEqualTo(true);
assertThat(primAct == primExp).isEqualTo(Boolean.TRUE); assertThat(primAct == primExp).isEqualTo(Boolean.TRUE);
assertThat(primAct == primExp).isNotEqualTo(false); assertThat(primAct == primExp).isNotEqualTo(false);
@@ -25,7 +25,7 @@ public class BinaryExpression {
assertThat(primAct == 1).isFalse(); assertThat(primAct == 1).isFalse();
assertThat(1 == primAct).isFalse(); assertThat(1 == primAct).isFalse();
assertThat(primAct != primExp).isTrue(); assertThat(primAct != primExp).as("doh!").isTrue();
assertThat(primAct != primExp).isEqualTo(true); assertThat(primAct != primExp).isEqualTo(true);
assertThat(primAct != primExp).isNotEqualTo(false); assertThat(primAct != primExp).isNotEqualTo(false);
assertThat(primAct != 1).isTrue(); assertThat(primAct != 1).isTrue();
@@ -36,7 +36,7 @@ public class BinaryExpression {
assertThat(primAct != 1).isFalse(); assertThat(primAct != 1).isFalse();
assertThat(1 != primAct).isFalse(); assertThat(1 != primAct).isFalse();
assertThat(primAct > primExp).isTrue(); assertThat(primAct > primExp).as("doh!").isTrue();
assertThat(primAct > primExp).isEqualTo(true); assertThat(primAct > primExp).isEqualTo(true);
assertThat(primAct > primExp).isNotEqualTo(false); assertThat(primAct > primExp).isNotEqualTo(false);
assertThat(primAct > 1).isTrue(); assertThat(primAct > 1).isTrue();
@@ -47,7 +47,7 @@ public class BinaryExpression {
assertThat(primAct > 1).isFalse(); assertThat(primAct > 1).isFalse();
assertThat(1 < primAct).isFalse(); assertThat(1 < primAct).isFalse();
assertThat(primAct >= primExp).isTrue(); assertThat(primAct >= primExp).as("doh!").isTrue();
assertThat(primAct >= primExp).isEqualTo(true); assertThat(primAct >= primExp).isEqualTo(true);
assertThat(primAct >= primExp).isNotEqualTo(false); assertThat(primAct >= primExp).isNotEqualTo(false);
assertThat(primAct >= 1).isTrue(); assertThat(primAct >= 1).isTrue();
@@ -58,7 +58,7 @@ public class BinaryExpression {
assertThat(primAct >= 1).isFalse(); assertThat(primAct >= 1).isFalse();
assertThat(1 <= primAct).isFalse(); assertThat(1 <= primAct).isFalse();
assertThat(primAct < primExp).isTrue(); assertThat(primAct < primExp).as("doh!").isTrue();
assertThat(primAct < primExp).isEqualTo(true); assertThat(primAct < primExp).isEqualTo(true);
assertThat(primAct < primExp).isNotEqualTo(false); assertThat(primAct < primExp).isNotEqualTo(false);
assertThat(primAct < 1).isTrue(); assertThat(primAct < 1).isTrue();
@@ -69,7 +69,7 @@ public class BinaryExpression {
assertThat(primAct < 1).isFalse(); assertThat(primAct < 1).isFalse();
assertThat(1 > primAct).isFalse(); assertThat(1 > primAct).isFalse();
assertThat(primAct <= primExp).isTrue(); assertThat(primAct <= primExp).as("doh!").isTrue();
assertThat(primAct <= primExp).isEqualTo(true); assertThat(primAct <= primExp).isEqualTo(true);
assertThat(primAct <= primExp).isNotEqualTo(false); assertThat(primAct <= primExp).isNotEqualTo(false);
assertThat(primAct <= 1).isTrue(); assertThat(primAct <= 1).isTrue();
@@ -80,7 +80,7 @@ public class BinaryExpression {
assertThat(primAct <= 1).isFalse(); assertThat(primAct <= 1).isFalse();
assertThat(1 >= primAct).isFalse(); assertThat(1 >= primAct).isFalse();
assertThat(numberObjAct == numberObjExp).isTrue(); assertThat(numberObjAct == numberObjExp).as("doh!").isTrue();
assertThat(numberObjAct == numberObjExp).isEqualTo(true); assertThat(numberObjAct == numberObjExp).isEqualTo(true);
assertThat(numberObjAct == numberObjExp).isNotEqualTo(false); assertThat(numberObjAct == numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct == 1).isTrue(); assertThat(numberObjAct == 1).isTrue();
@@ -91,7 +91,7 @@ public class BinaryExpression {
assertThat(numberObjAct == 1).isFalse(); assertThat(numberObjAct == 1).isFalse();
assertThat(1 == numberObjAct).isFalse(); assertThat(1 == numberObjAct).isFalse();
assertThat(numberObjAct != numberObjExp).isTrue(); assertThat(numberObjAct != numberObjExp).as("doh!").isTrue();
assertThat(numberObjAct != numberObjExp).isEqualTo(true); assertThat(numberObjAct != numberObjExp).isEqualTo(true);
assertThat(numberObjAct != numberObjExp).isNotEqualTo(false); assertThat(numberObjAct != numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct != 1).isTrue(); assertThat(numberObjAct != 1).isTrue();
@@ -102,7 +102,7 @@ public class BinaryExpression {
assertThat(numberObjAct != 1).isFalse(); assertThat(numberObjAct != 1).isFalse();
assertThat(1 != numberObjAct).isFalse(); assertThat(1 != numberObjAct).isFalse();
assertThat(numberObjAct > numberObjExp).isTrue(); assertThat(numberObjAct > numberObjExp).as("doh!").isTrue();
assertThat(numberObjAct > numberObjExp).isEqualTo(true); assertThat(numberObjAct > numberObjExp).isEqualTo(true);
assertThat(numberObjAct > numberObjExp).isNotEqualTo(false); assertThat(numberObjAct > numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct > 1).isTrue(); assertThat(numberObjAct > 1).isTrue();
@@ -113,7 +113,7 @@ public class BinaryExpression {
assertThat(numberObjAct > 1).isFalse(); assertThat(numberObjAct > 1).isFalse();
assertThat(1 < numberObjAct).isFalse(); assertThat(1 < numberObjAct).isFalse();
assertThat(numberObjAct >= numberObjExp).isTrue(); assertThat(numberObjAct >= numberObjExp).as("doh!").isTrue();
assertThat(numberObjAct >= numberObjExp).isEqualTo(true); assertThat(numberObjAct >= numberObjExp).isEqualTo(true);
assertThat(numberObjAct >= numberObjExp).isNotEqualTo(false); assertThat(numberObjAct >= numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct >= 1).isTrue(); assertThat(numberObjAct >= 1).isTrue();
@@ -124,7 +124,7 @@ public class BinaryExpression {
assertThat(numberObjAct >= 1).isFalse(); assertThat(numberObjAct >= 1).isFalse();
assertThat(1 <= numberObjAct).isFalse(); assertThat(1 <= numberObjAct).isFalse();
assertThat(numberObjAct < numberObjExp).isTrue(); assertThat(numberObjAct < numberObjExp).as("doh!").isTrue();
assertThat(numberObjAct < numberObjExp).isEqualTo(true); assertThat(numberObjAct < numberObjExp).isEqualTo(true);
assertThat(numberObjAct < numberObjExp).isNotEqualTo(false); assertThat(numberObjAct < numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct < 1).isTrue(); assertThat(numberObjAct < 1).isTrue();
@@ -135,7 +135,7 @@ public class BinaryExpression {
assertThat(numberObjAct < 1).isFalse(); assertThat(numberObjAct < 1).isFalse();
assertThat(1 > numberObjAct).isFalse(); assertThat(1 > numberObjAct).isFalse();
assertThat(numberObjAct <= numberObjExp).isTrue(); assertThat(numberObjAct <= numberObjExp).as("doh!").isTrue();
assertThat(numberObjAct <= numberObjExp).isEqualTo(true); assertThat(numberObjAct <= numberObjExp).isEqualTo(true);
assertThat(numberObjAct <= numberObjExp).isNotEqualTo(false); assertThat(numberObjAct <= numberObjExp).isNotEqualTo(false);
assertThat(numberObjAct <= 1).isTrue(); assertThat(numberObjAct <= 1).isTrue();
@@ -146,42 +146,42 @@ public class BinaryExpression {
assertThat(numberObjAct <= 1).isFalse(); assertThat(numberObjAct <= 1).isFalse();
assertThat(1 >= numberObjAct).isFalse(); assertThat(1 >= numberObjAct).isFalse();
assertThat(numberObjAct.equals(numberObjExp)).isTrue(); assertThat(numberObjAct.equals(numberObjExp)).as("doh!").isTrue();
assertThat(numberObjAct.equals(numberObjExp)).isEqualTo(true); assertThat(numberObjAct.equals(numberObjExp)).isEqualTo(true);
assertThat(numberObjAct.equals(numberObjExp)).isNotEqualTo(false); assertThat(numberObjAct.equals(numberObjExp)).isNotEqualTo(false);
assertThat(numberObjAct.equals(numberObjExp)).isFalse(); assertThat(numberObjAct.equals(numberObjExp)).isFalse();
assertThat(numberObjAct.equals(numberObjExp)).isEqualTo(false); assertThat(numberObjAct.equals(numberObjExp)).isEqualTo(false);
assertThat(numberObjAct.equals(numberObjExp)).isNotEqualTo(true); assertThat(numberObjAct.equals(numberObjExp)).isNotEqualTo(true);
assertThat(stringAct == stringExp).isTrue(); assertThat(stringAct == stringExp).as("doh!").isTrue();
assertThat(stringAct == stringExp).isEqualTo(true); assertThat(stringAct == stringExp).isEqualTo(true);
assertThat(stringAct == stringExp).isNotEqualTo(false); assertThat(stringAct == stringExp).isNotEqualTo(false);
assertThat(stringAct == stringExp).isFalse(); assertThat(stringAct == stringExp).isFalse();
assertThat(stringAct == stringExp).isEqualTo(false); assertThat(stringAct == stringExp).isEqualTo(false);
assertThat(stringAct == stringExp).isNotEqualTo(true); assertThat(stringAct == stringExp).isNotEqualTo(true);
assertThat(stringAct.equals(stringExp)).isTrue(); assertThat(stringAct.equals(stringExp)).as("doh!").isTrue();
assertThat(stringAct.equals(stringExp)).isEqualTo(true); assertThat(stringAct.equals(stringExp)).isEqualTo(true);
assertThat(stringAct.equals(stringExp)).isNotEqualTo(false); assertThat(stringAct.equals(stringExp)).isNotEqualTo(false);
assertThat(stringAct.equals(stringExp)).isFalse(); assertThat(stringAct.equals(stringExp)).isFalse();
assertThat(stringAct.equals(stringExp)).isEqualTo(false); assertThat(stringAct.equals(stringExp)).isEqualTo(false);
assertThat(stringAct.equals(stringExp)).isNotEqualTo(true); assertThat(stringAct.equals(stringExp)).isNotEqualTo(true);
assertThat(stringAct != stringExp).isTrue(); assertThat(stringAct != stringExp).as("doh!").isTrue();
assertThat(stringAct != stringExp).isEqualTo(true); assertThat(stringAct != stringExp).isEqualTo(true);
assertThat(stringAct != stringExp).isNotEqualTo(false); assertThat(stringAct != stringExp).isNotEqualTo(false);
assertThat(stringAct != stringExp).isFalse(); assertThat(stringAct != stringExp).isFalse();
assertThat(stringAct != stringExp).isEqualTo(false); assertThat(stringAct != stringExp).isEqualTo(false);
assertThat(stringAct != stringExp).isNotEqualTo(true); assertThat(stringAct != stringExp).isNotEqualTo(true);
assertThat(stringAct == null).isTrue(); assertThat(stringAct == null).as("doh!").isTrue();
assertThat(stringAct == null).isEqualTo(true); assertThat(stringAct == null).isEqualTo(true);
assertThat(stringAct == null).isNotEqualTo(false); assertThat(stringAct == null).isNotEqualTo(false);
assertThat(stringAct == null).isFalse(); assertThat(stringAct == null).isFalse();
assertThat(stringAct == null).isEqualTo(false); assertThat(stringAct == null).isEqualTo(false);
assertThat(stringAct == null).isNotEqualTo(true); assertThat(stringAct == null).isNotEqualTo(true);
assertThat(null == stringAct).isTrue(); assertThat(null == stringAct).as("doh!").isTrue();
assertThat(null == stringAct).isEqualTo(true); assertThat(null == stringAct).isEqualTo(true);
assertThat(null == stringAct).isNotEqualTo(false); assertThat(null == stringAct).isNotEqualTo(false);
assertThat(null == stringAct).isFalse(); assertThat(null == stringAct).isFalse();
@@ -190,5 +190,10 @@ public class BinaryExpression {
assertThat(null == null).isTrue(); assertThat(null == null).isTrue();
assertThat(!false).isTrue(); assertThat(!false).isTrue();
assertThat(primAct == primExp).as("doh!").isTrue().isEqualTo(true);
assertThat(primAct == primExp).isFalse().as("doh!").isEqualTo(true);
assertThat(numberObjAct.equals(numberObjExp)).as("doh!").isTrue().isEqualTo(true);
} }
} }
@@ -6,7 +6,7 @@ public class BooleanCondition {
boolean primitive = false; boolean primitive = false;
Boolean object = Boolean.TRUE; Boolean object = Boolean.TRUE;
assertThat(primitive).isTrue(); assertThat(primitive).as("foo").isTrue();
assertThat(primitive).isFalse(); assertThat(primitive).isFalse();
assertThat(object).isTrue(); assertThat(object).isTrue();
assertThat(object).isFalse(); assertThat(object).isFalse();
@@ -15,7 +15,7 @@ public class BooleanCondition {
assertThat(object).isTrue(); assertThat(object).isTrue();
assertThat(object).isFalse(); assertThat(object).isFalse();
assertThat(primitive).isFalse(); assertThat(primitive).as("foo").isFalse();
assertThat(primitive).isTrue(); assertThat(primitive).isTrue();
assertThat(object).isFalse(); assertThat(object).isFalse();
assertThat(object).isTrue(); assertThat(object).isTrue();
@@ -28,5 +28,7 @@ public class BooleanCondition {
assertThat(object).isEqualTo(Boolean.TRUE && !Boolean.TRUE); assertThat(object).isEqualTo(Boolean.TRUE && !Boolean.TRUE);
assertThat("").isEqualTo(Boolean.TRUE); assertThat("").isEqualTo(Boolean.TRUE);
assertThat(primitive).isTrue().as("foo").isTrue().as("bar").isTrue().isFalse();
} }
} }
@@ -6,7 +6,7 @@ public class BooleanCondition {
boolean primitive = false; boolean primitive = false;
Boolean object = Boolean.TRUE; Boolean object = Boolean.TRUE;
assertThat(primitive).isEqualTo(Boolean.TRUE); assertThat(primitive).as("foo").isEqualTo(Boolean.TRUE);
assertThat(primitive).isEqualTo(Boolean.FALSE); assertThat(primitive).isEqualTo(Boolean.FALSE);
assertThat(object).isEqualTo(Boolean.TRUE); assertThat(object).isEqualTo(Boolean.TRUE);
assertThat(object).isEqualTo(Boolean.FALSE); assertThat(object).isEqualTo(Boolean.FALSE);
@@ -15,7 +15,7 @@ public class BooleanCondition {
assertThat(object).isEqualTo(true); assertThat(object).isEqualTo(true);
assertThat(object).isEqualTo(false); assertThat(object).isEqualTo(false);
assertThat(primitive).isNotEqualTo(Boolean.TRUE); assertThat(primitive).as("foo").isNotEqualTo(Boolean.TRUE);
assertThat(primitive).isNotEqualTo(Boolean.FALSE); assertThat(primitive).isNotEqualTo(Boolean.FALSE);
assertThat(object).isNotEqualTo(Boolean.TRUE); assertThat(object).isNotEqualTo(Boolean.TRUE);
assertThat(object).isNotEqualTo(Boolean.FALSE); assertThat(object).isNotEqualTo(Boolean.FALSE);
@@ -28,5 +28,7 @@ public class BooleanCondition {
assertThat(object).isEqualTo(Boolean.TRUE && !Boolean.TRUE); assertThat(object).isEqualTo(Boolean.TRUE && !Boolean.TRUE);
assertThat("").isEqualTo(Boolean.TRUE); assertThat("").isEqualTo(Boolean.TRUE);
assertThat(primitive).isEqualTo(Boolean.TRUE).as("foo").isEqualTo(true).as("bar").isTrue().isFalse();
} }
} }
@@ -0,0 +1,44 @@
import static org.assertj.core.api.Assertions.assertThat;
import java.util.*;
public class CollectionMapExpression {
private void collectionMapExpression() {
List<String> stringList = new ArrayList<>();
List<String> anotherList = new ArrayList<>();
Map<String, Integer> keyValueMap = new HashMap<>();
assertThat(stringList).as("foo").isEmpty();
assertThat(stringList).isEmpty();
assertThat(stringList).contains("foo");
assertThat(stringList).contains("foo");
assertThat(stringList).containsAll(anotherList);
assertThat(stringList).containsAll(anotherList);
assertThat(stringList).as("foo").isNotEmpty();
assertThat(stringList).isNotEmpty();
assertThat(stringList).doesNotContain("foo");
assertThat(stringList).doesNotContain("foo");
assertThat(stringList.containsAll(anotherList)).isEqualTo(false);
assertThat(stringList.containsAll(anotherList)).isFalse();
assertThat(keyValueMap).as("foo").isEmpty();
assertThat(keyValueMap).isEmpty();
assertThat(keyValueMap).containsKey("foo");
assertThat(keyValueMap).containsKey("foo");
assertThat(keyValueMap).containsValue(2);
assertThat(keyValueMap).containsValue(2);
assertThat(keyValueMap).as("foo").isNotEmpty();
assertThat(keyValueMap).isNotEmpty();
assertThat(keyValueMap).doesNotContainKey("foo");
assertThat(keyValueMap).doesNotContainKey("foo");
assertThat(keyValueMap).doesNotContainValue(2);
assertThat(keyValueMap).doesNotContainValue(2);
assertThat(stringList).as("foo").isNotEmpty().as("bar").isNotEmpty();
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false).as("bar").isTrue();
assertThat(stringList.isEmpty()).as("foo").satisfies(it -> it.booleanValue()).as("bar").isFalse();
}
}
@@ -0,0 +1,44 @@
import static org.assertj.core.api.Assertions.assertThat;
import java.util.*;
public class CollectionMapExpression {
private void collectionMapExpression() {
List<String> stringList = new ArrayList<>();
List<String> anotherList = new ArrayList<>();
Map<String, Integer> keyValueMap = new HashMap<>();
assertThat(stringList.isEmpty()).as("foo").isEqualTo(true);
assertThat(stringList.isEmpty()).isTrue();
assertThat(stringList.contains("foo")).isEqualTo(true);
assertThat(stringList.contains("foo")).isTrue();
assertThat(stringList.containsAll(anotherList)).isEqualTo(true);
assertThat(stringList.containsAll(anotherList)).isTrue();
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false);
assertThat(stringList.isEmpty()).isFalse();
assertThat(stringList.contains("foo")).isEqualTo(false);
assertThat(stringList.contains("foo")).isFalse();
assertThat(stringList.containsAll(anotherList)).isEqualTo(false);
assertThat(stringList.containsAll(anotherList)).isFalse();
assertThat(keyValueMap.isEmpty()).as("foo").isEqualTo(true);
assertThat(keyValueMap.isEmpty()).isTrue();
assertThat(keyValueMap.containsKey("foo")).isEqualTo(true);
assertThat(keyValueMap.containsKey("foo")).isTrue();
assertThat(keyValueMap.containsValue(2)).isEqualTo(true);
assertThat(keyValueMap.containsValue(2)).isTrue();
assertThat(keyValueMap.isEmpty()).as("foo").isEqualTo(false);
assertThat(keyValueMap.isEmpty()).isFalse();
assertThat(keyValueMap.containsKey("foo")).isEqualTo(false);
assertThat(keyValueMap.containsKey("foo")).isFalse();
assertThat(keyValueMap.containsValue(2)).isEqualTo(false);
assertThat(keyValueMap.containsValue(2)).isFalse();
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false).as("bar").isFalse();
assertThat(stringList.isEmpty()).as("foo").isEqualTo(false).as("bar").isTrue();
assertThat(stringList.isEmpty()).as("foo").satisfies(it -> it.booleanValue()).as("bar").isFalse();
}
}
@@ -14,5 +14,7 @@ public class EnumerableIsEmpty {
assertThat(new StringBuilder()).as("bar").hasSize(1); assertThat(new StringBuilder()).as("bar").hasSize(1);
assertThat(new ArrayList<Long>()).as("etc").hasSize(1); assertThat(new ArrayList<Long>()).as("etc").hasSize(1);
assertThat(new Long[1]).as("etc").hasSize(1); assertThat(new Long[1]).as("etc").hasSize(1);
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").isEmpty();
} }
} }
@@ -14,5 +14,7 @@ public class EnumerableIsEmpty {
assertThat(new StringBuilder()).as("bar").hasSize(1); assertThat(new StringBuilder()).as("bar").hasSize(1);
assertThat(new ArrayList<Long>()).as("etc").hasSize(1); assertThat(new ArrayList<Long>()).as("etc").hasSize(1);
assertThat(new Long[1]).as("etc").hasSize(1); assertThat(new Long[1]).as("etc").hasSize(1);
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").hasSize(0);
} }
} }
@@ -8,24 +8,24 @@ public class GuavaOptional {
private void guavaOptional() { private void guavaOptional() {
Optional<String> opt = Optional.absent(); Optional<String> opt = Optional.absent();
assertThat(opt).isPresent(); assertThat(opt).as("foo").isPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).isAbsent(); assertThat(opt).as("foo").isAbsent();
assertThat(opt).isAbsent(); assertThat(opt).isAbsent();
assertThat(opt).isAbsent(); assertThat(opt).isAbsent();
assertThat(opt).isAbsent(); assertThat(opt).isAbsent();
assertThat(opt).isAbsent(); assertThat(opt).isAbsent();
assertThat(opt).contains("foo"); assertThat(opt).as("foo").contains("foo");
assertThat(opt.get()).isSameAs("foo"); assertThat(opt.get()).isSameAs("foo");
assertThat(opt.get()).isNotEqualTo("foo"); assertThat(opt.get()).isNotEqualTo("foo");
assertThat(opt.get()).isNotSameAs("foo"); assertThat(opt.get()).isNotSameAs("foo");
assertThat(opt).contains("foo"); assertThat(opt).as("foo").contains("foo");
assertThat(opt).contains("foo"); assertThat(opt).contains("foo");
assertThat(opt).isNotEqualTo(Optional.of("foo")); assertThat(opt).isNotEqualTo(Optional.of("foo"));
assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); assertThat(opt).isNotEqualTo(Optional.fromNullable("foo"));
@@ -33,20 +33,23 @@ public class GuavaOptional {
assertThat(opt).isAbsent(); assertThat(opt).isAbsent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
org.assertj.guava.api.Assertions.assertThat(opt).contains("foo"); assertThat(opt).as("foo").contains("foo");
org.assertj.guava.api.Assertions.assertThat(opt).contains("foo"); assertThat(opt).contains("foo");
org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo")); org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo"));
org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo"));
org.assertj.guava.api.Assertions.assertThat(opt).isAbsent(); assertThat(opt).as("foo").isAbsent();
org.assertj.guava.api.Assertions.assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).contains("foo"); assertThat(opt).as("foo").contains("foo");
assertThat(opt).contains("foo"); assertThat(opt).contains("foo");
org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo")); org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo"));
org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo"));
assertThat(opt).isAbsent(); assertThat(opt).as("foo").isAbsent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).as("foo").isPresent().as("bar").isPresent();
assertThat(opt.isPresent()).as("foo").isEqualTo(true).as("bar").isEqualTo(Boolean.FALSE);
} }
} }
@@ -8,24 +8,24 @@ public class GuavaOptional {
private void guavaOptional() { private void guavaOptional() {
Optional<String> opt = Optional.absent(); Optional<String> opt = Optional.absent();
assertThat(opt.isPresent()).isEqualTo(true); assertThat(opt.isPresent()).as("foo").isEqualTo(true);
assertThat(opt.isPresent()).isEqualTo(Boolean.TRUE); assertThat(opt.isPresent()).isEqualTo(Boolean.TRUE);
assertThat(opt.isPresent()).isNotEqualTo(false); assertThat(opt.isPresent()).isNotEqualTo(false);
assertThat(opt.isPresent()).isNotEqualTo(Boolean.FALSE); assertThat(opt.isPresent()).isNotEqualTo(Boolean.FALSE);
assertThat(opt.isPresent()).isTrue(); assertThat(opt.isPresent()).isTrue();
assertThat(opt.isPresent()).isEqualTo(false); assertThat(opt.isPresent()).as("foo").isEqualTo(false);
assertThat(opt.isPresent()).isEqualTo(Boolean.FALSE); assertThat(opt.isPresent()).isEqualTo(Boolean.FALSE);
assertThat(opt.isPresent()).isNotEqualTo(true); assertThat(opt.isPresent()).isNotEqualTo(true);
assertThat(opt.isPresent()).isNotEqualTo(Boolean.TRUE); assertThat(opt.isPresent()).isNotEqualTo(Boolean.TRUE);
assertThat(opt.isPresent()).isFalse(); assertThat(opt.isPresent()).isFalse();
assertThat(opt.get()).isEqualTo("foo"); assertThat(opt.get()).as("foo").isEqualTo("foo");
assertThat(opt.get()).isSameAs("foo"); assertThat(opt.get()).isSameAs("foo");
assertThat(opt.get()).isNotEqualTo("foo"); assertThat(opt.get()).isNotEqualTo("foo");
assertThat(opt.get()).isNotSameAs("foo"); assertThat(opt.get()).isNotSameAs("foo");
assertThat(opt).isEqualTo(Optional.of("foo")); assertThat(opt).as("foo").isEqualTo(Optional.of("foo"));
assertThat(opt).isEqualTo(Optional.fromNullable("foo")); assertThat(opt).isEqualTo(Optional.fromNullable("foo"));
assertThat(opt).isNotEqualTo(Optional.of("foo")); assertThat(opt).isNotEqualTo(Optional.of("foo"));
assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); assertThat(opt).isNotEqualTo(Optional.fromNullable("foo"));
@@ -33,20 +33,23 @@ public class GuavaOptional {
assertThat(opt).isEqualTo(Optional.absent()); assertThat(opt).isEqualTo(Optional.absent());
assertThat(opt).isNotEqualTo(Optional.absent()); assertThat(opt).isNotEqualTo(Optional.absent());
org.assertj.guava.api.Assertions.assertThat(opt).isEqualTo(Optional.of("foo")); org.assertj.guava.api.Assertions.assertThat(opt).as("foo").isEqualTo(Optional.of("foo"));
org.assertj.guava.api.Assertions.assertThat(opt).isEqualTo(Optional.fromNullable("foo")); org.assertj.guava.api.Assertions.assertThat(opt).isEqualTo(Optional.fromNullable("foo"));
org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo")); org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo"));
org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo"));
org.assertj.guava.api.Assertions.assertThat(opt).isEqualTo(Optional.absent()); org.assertj.guava.api.Assertions.assertThat(opt).as("foo").isEqualTo(Optional.absent());
org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.absent()); org.assertj.guava.api.Assertions.assertThat(opt).isNotEqualTo(Optional.absent());
org.assertj.core.api.Assertions.assertThat(opt).isEqualTo(Optional.of("foo")); org.assertj.core.api.Assertions.assertThat(opt).as("foo").isEqualTo(Optional.of("foo"));
org.assertj.core.api.Assertions.assertThat(opt).isEqualTo(Optional.fromNullable("foo")); org.assertj.core.api.Assertions.assertThat(opt).isEqualTo(Optional.fromNullable("foo"));
org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo")); org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.of("foo"));
org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo")); org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.fromNullable("foo"));
org.assertj.core.api.Assertions.assertThat(opt).isEqualTo(Optional.absent()); org.assertj.core.api.Assertions.assertThat(opt).as("foo").isEqualTo(Optional.absent());
org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.absent()); org.assertj.core.api.Assertions.assertThat(opt).isNotEqualTo(Optional.absent());
assertThat(opt.isPresent()).as("foo").isEqualTo(true).as("bar").isEqualTo(Boolean.TRUE);
assertThat(opt.isPresent()).as("foo").isEqualTo(true).as("bar").isEqualTo(Boolean.FALSE);
} }
} }
@@ -5,18 +5,21 @@ public class InstanceOf {
private void instanceOf() { private void instanceOf() {
Boolean object = Boolean.TRUE; Boolean object = Boolean.TRUE;
assertThat(object).isInstanceOf(Boolean.class); assertThat(object).as("foo").isInstanceOf(Boolean.class);
assertThat(object).isInstanceOf(Boolean.class); assertThat(object).isInstanceOf(Boolean.class);
assertThat(object).isInstanceOf(Boolean.class); assertThat(object).isInstanceOf(Boolean.class);
assertThat(object).isInstanceOf(Boolean.class); assertThat(object).isInstanceOf(Boolean.class);
assertThat(object).isInstanceOf(Boolean.class); assertThat(object).isInstanceOf(Boolean.class);
assertThat(object).isNotInstanceOf(Boolean.class); assertThat(object).as("foo").isNotInstanceOf(Boolean.class);
assertThat(object).isNotInstanceOf(Boolean.class); assertThat(object).isNotInstanceOf(Boolean.class);
assertThat(object).isNotInstanceOf(Boolean.class); assertThat(object).isNotInstanceOf(Boolean.class);
assertThat(object).isNotInstanceOf(Boolean.class); assertThat(object).isNotInstanceOf(Boolean.class);
assertThat(object).isNotInstanceOf(Boolean.class); assertThat(object).isNotInstanceOf(Boolean.class);
assertThat(object).as("nah").isNotInstanceOf(Boolean.class); assertThat(object).as("nah").isNotInstanceOf(Boolean.class);
assertThat(object).as("foo").isInstanceOf(Boolean.class).as("bar").isInstanceOf(Boolean.class);
assertThat(object instanceof Boolean).as("foo").isEqualTo(Boolean.TRUE).as("bar").isEqualTo(false);
} }
} }
@@ -5,18 +5,21 @@ public class InstanceOf {
private void instanceOf() { private void instanceOf() {
Boolean object = Boolean.TRUE; Boolean object = Boolean.TRUE;
assertThat(object instanceof Boolean).isEqualTo(Boolean.TRUE); assertThat(object instanceof Boolean).as("foo").isEqualTo(Boolean.TRUE);
assertThat(object instanceof Boolean).isEqualTo(true); assertThat(object instanceof Boolean).isEqualTo(true);
assertThat(object instanceof Boolean).isNotEqualTo(Boolean.FALSE); assertThat(object instanceof Boolean).isNotEqualTo(Boolean.FALSE);
assertThat(object instanceof Boolean).isNotEqualTo(false); assertThat(object instanceof Boolean).isNotEqualTo(false);
assertThat(object instanceof Boolean).isTrue(); assertThat(object instanceof Boolean).isTrue();
assertThat(object instanceof Boolean).isEqualTo(Boolean.FALSE); assertThat(object instanceof Boolean).as("foo").isEqualTo(Boolean.FALSE);
assertThat(object instanceof Boolean).isEqualTo(false); assertThat(object instanceof Boolean).isEqualTo(false);
assertThat(object instanceof Boolean).isNotEqualTo(Boolean.TRUE); assertThat(object instanceof Boolean).isNotEqualTo(Boolean.TRUE);
assertThat(object instanceof Boolean).isNotEqualTo(true); assertThat(object instanceof Boolean).isNotEqualTo(true);
assertThat(object instanceof Boolean).isFalse(); assertThat(object instanceof Boolean).isFalse();
assertThat(((object)) instanceof Boolean).as("nah").isEqualTo(true && !true); assertThat(((object)) instanceof Boolean).as("nah").isEqualTo(true && !true);
assertThat(object instanceof Boolean).as("foo").isEqualTo(Boolean.TRUE).as("bar").isEqualTo(true);
assertThat(object instanceof Boolean).as("foo").isEqualTo(Boolean.TRUE).as("bar").isEqualTo(false);
} }
} }
@@ -6,23 +6,25 @@ public class InvertedBooleanCondition {
boolean primitive = false; boolean primitive = false;
Boolean object = Boolean.TRUE; Boolean object = Boolean.TRUE;
assertThat(primitive).as("foo").isFalse();
assertThat(primitive).isFalse(); assertThat(primitive).isFalse();
assertThat(primitive).isFalse(); assertThat(primitive).isFalse();
assertThat(primitive).isFalse(); assertThat(primitive).isFalse();
assertThat(primitive).isFalse(); assertThat(primitive).isFalse();
assertThat(primitive).isFalse();
assertThat(object).isFalse(); assertThat(object).as("foo").isFalse();
assertThat(object).isFalse(); assertThat(object).isFalse();
assertThat(object).isFalse(); assertThat(object).isFalse();
assertThat(object).isFalse(); assertThat(object).isFalse();
assertThat(object).isFalse(); assertThat(object).isFalse();
assertThat(primitive).as("foo").isTrue();
assertThat(primitive).isTrue(); assertThat(primitive).isTrue();
assertThat(primitive).isTrue(); assertThat(primitive).isTrue();
assertThat(primitive).isTrue(); assertThat(primitive).isTrue();
assertThat(primitive).isTrue(); assertThat(primitive).isTrue();
assertThat(primitive).isTrue();
assertThat(object).isTrue(); assertThat(object).as("foo").isTrue();
assertThat(object).isTrue(); assertThat(object).isTrue();
assertThat(object).isTrue(); assertThat(object).isTrue();
assertThat(object).isTrue(); assertThat(object).isTrue();
@@ -30,5 +32,8 @@ public class InvertedBooleanCondition {
assertThat(!((primitive))).as("nah").isTrue(); assertThat(!((primitive))).as("nah").isTrue();
assertThat(!object).isEqualTo(Boolean.TRUE && !Boolean.TRUE); assertThat(!object).isEqualTo(Boolean.TRUE && !Boolean.TRUE);
assertThat(primitive).as("foo").isFalse().as("bar").isFalse();
assertThat(primitive).as("foo").isFalse().as("bar").isTrue();
} }
} }
@@ -6,23 +6,25 @@ public class InvertedBooleanCondition {
boolean primitive = false; boolean primitive = false;
Boolean object = Boolean.TRUE; Boolean object = Boolean.TRUE;
assertThat(!primitive).isEqualTo(Boolean.TRUE); assertThat(!primitive).as("foo").isEqualTo(Boolean.TRUE);
assertThat(!primitive).isEqualTo(true); assertThat(!primitive).isEqualTo(true);
assertThat(!primitive).isNotEqualTo(Boolean.FALSE); assertThat(!primitive).isNotEqualTo(Boolean.FALSE);
assertThat(!primitive).isNotEqualTo(false); assertThat(!primitive).isNotEqualTo(false);
assertThat(!primitive).isTrue(); assertThat(!primitive).isTrue();
assertThat(!object).isEqualTo(Boolean.TRUE);
assertThat(!object).as("foo").isEqualTo(Boolean.TRUE);
assertThat(!object).isEqualTo(true); assertThat(!object).isEqualTo(true);
assertThat(!object).isNotEqualTo(Boolean.FALSE); assertThat(!object).isNotEqualTo(Boolean.FALSE);
assertThat(!object).isNotEqualTo(false); assertThat(!object).isNotEqualTo(false);
assertThat(!object).isTrue(); assertThat(!object).isTrue();
assertThat(!primitive).isEqualTo(Boolean.FALSE); assertThat(!primitive).as("foo").isEqualTo(Boolean.FALSE);
assertThat(!primitive).isEqualTo(false); assertThat(!primitive).isEqualTo(false);
assertThat(!primitive).isNotEqualTo(Boolean.TRUE); assertThat(!primitive).isNotEqualTo(Boolean.TRUE);
assertThat(!primitive).isNotEqualTo(true); assertThat(!primitive).isNotEqualTo(true);
assertThat(!primitive).isFalse(); assertThat(!primitive).isFalse();
assertThat(!object).isEqualTo(Boolean.FALSE);
assertThat(!object).as("foo").isEqualTo(Boolean.FALSE);
assertThat(!object).isEqualTo(false); assertThat(!object).isEqualTo(false);
assertThat(!object).isNotEqualTo(Boolean.TRUE); assertThat(!object).isNotEqualTo(Boolean.TRUE);
assertThat(!object).isNotEqualTo(true); assertThat(!object).isNotEqualTo(true);
@@ -30,5 +32,8 @@ public class InvertedBooleanCondition {
assertThat(!(((!((primitive)))))).as("nah").isEqualTo(true && !true); assertThat(!(((!((primitive)))))).as("nah").isEqualTo(true && !true);
assertThat(!object).isEqualTo(Boolean.TRUE && !Boolean.TRUE); assertThat(!object).isEqualTo(Boolean.TRUE && !Boolean.TRUE);
assertThat(!primitive).as("foo").isEqualTo(Boolean.TRUE).as("bar").isNotEqualTo(false);
assertThat(!primitive).as("foo").isEqualTo(Boolean.TRUE).as("bar").isNotEqualTo(true);
} }
} }
@@ -7,7 +7,7 @@ public class Java8Optional {
private void java8Optional() { private void java8Optional() {
Optional<String> opt = Optional.empty(); Optional<String> opt = Optional.empty();
assertThat(opt).isPresent(); assertThat(opt).as("foo").isPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
@@ -19,17 +19,22 @@ public class Java8Optional {
assertThat(opt).isNotPresent(); assertThat(opt).isNotPresent();
assertThat(opt).isNotPresent(); assertThat(opt).isNotPresent();
assertThat(opt).contains("foo"); assertThat(opt).as("foo").contains("foo");
assertThat(opt).containsSame("foo"); assertThat(opt).containsSame("foo");
assertThat(opt.get()).isNotEqualTo("foo"); assertThat(opt.get()).isNotEqualTo("foo");
assertThat(opt.get()).isNotSameAs("foo"); assertThat(opt.get()).isNotSameAs("foo");
assertThat(opt).contains("foo"); assertThat(opt).as("foo").contains("foo");
assertThat(opt).contains("foo"); assertThat(opt).contains("foo");
assertThat(opt).isNotEqualTo(Optional.of("foo")); assertThat(opt).isNotEqualTo(Optional.of("foo"));
assertThat(opt).isNotEqualTo(Optional.ofNullable("foo")); assertThat(opt).isNotEqualTo(Optional.ofNullable("foo"));
assertThat(opt).isNotPresent(); assertThat(opt).as("foo").isNotPresent();
assertThat(opt).isPresent(); assertThat(opt).isPresent();
assertThat(opt).as("foo").isPresent().as("bar").isPresent();
assertThat(opt.isPresent()).as("foo").isEqualTo(false).as("bar").isTrue();
assertThat(opt.get()).isEqualTo("foo").isSameAs("foo").isNotEqualTo("foo").isNotSameAs("foo");
} }
} }
@@ -7,7 +7,7 @@ public class Java8Optional {
private void java8Optional() { private void java8Optional() {
Optional<String> opt = Optional.empty(); Optional<String> opt = Optional.empty();
assertThat(opt.isPresent()).isEqualTo(true); assertThat(opt.isPresent()).as("foo").isEqualTo(true);
assertThat(opt.isPresent()).isEqualTo(Boolean.TRUE); assertThat(opt.isPresent()).isEqualTo(Boolean.TRUE);
assertThat(opt.isPresent()).isNotEqualTo(false); assertThat(opt.isPresent()).isNotEqualTo(false);
assertThat(opt.isPresent()).isNotEqualTo(Boolean.FALSE); assertThat(opt.isPresent()).isNotEqualTo(Boolean.FALSE);
@@ -19,17 +19,22 @@ public class Java8Optional {
assertThat(opt.isPresent()).isNotEqualTo(Boolean.TRUE); assertThat(opt.isPresent()).isNotEqualTo(Boolean.TRUE);
assertThat(opt.isPresent()).isFalse(); assertThat(opt.isPresent()).isFalse();
assertThat(opt.get()).isEqualTo("foo"); assertThat(opt.get()).as("foo").isEqualTo("foo");
assertThat(opt.get()).isSameAs("foo"); assertThat(opt.get()).isSameAs("foo");
assertThat(opt.get()).isNotEqualTo("foo"); assertThat(opt.get()).isNotEqualTo("foo");
assertThat(opt.get()).isNotSameAs("foo"); assertThat(opt.get()).isNotSameAs("foo");
assertThat(opt).isEqualTo(Optional.of("foo")); assertThat(opt).as("foo").isEqualTo(Optional.of("foo"));
assertThat(opt).isEqualTo(Optional.ofNullable("foo")); assertThat(opt).isEqualTo(Optional.ofNullable("foo"));
assertThat(opt).isNotEqualTo(Optional.of("foo")); assertThat(opt).isNotEqualTo(Optional.of("foo"));
assertThat(opt).isNotEqualTo(Optional.ofNullable("foo")); assertThat(opt).isNotEqualTo(Optional.ofNullable("foo"));
assertThat(opt).isEqualTo(Optional.empty()); assertThat(opt).as("foo").isEqualTo(Optional.empty());
assertThat(opt).isNotEqualTo(Optional.empty()); assertThat(opt).isNotEqualTo(Optional.empty());
assertThat(opt.isPresent()).as("foo").isEqualTo(true).as("bar").isTrue();
assertThat(opt.isPresent()).as("foo").isEqualTo(false).as("bar").isTrue();
assertThat(opt.get()).isEqualTo("foo").isSameAs("foo").isNotEqualTo("foo").isNotSameAs("foo");
} }
} }
@@ -6,6 +6,8 @@ public class JoinStatements {
private void joinStatements() { private void joinStatements() {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
List<String> otherList = new ArrayList<>();
// the future is always born in pain // the future is always born in pain
/* tricky */ /* tricky */
assertThat(list).as("foo").hasSize(2) assertThat(list).as("foo").hasSize(2)
@@ -21,20 +23,30 @@ public class JoinStatements {
// moar! // moar!
.doesNotContain("foobar"); .doesNotContain("foobar");
assertThat("narf").isNotEqualTo("puit").as("bar").contains("barbar").as("foo").hasSize(2); assertThat("narf").isNotEqualTo("puit");
assertThat(list).as("bar").contains("barbar").as("foo").hasSize(2);
assertThat(list).as("evil").extracting(String::length).contains(2); assertThat(list).as("evil").extracting(String::length).contains(2);
assertThat(list).as("bar").contains("barbar"); assertThat(list).as("bar").contains("barbar");
assertThat("narf").isNotEqualTo("puit").as("foo").hasSize(2); assertThat(otherList).contains("puit");
assertThat(list).as("foo").hasSize(2);
if (true) { if (true) {
assertThat(list).doesNotContain("narf").as("bar").contains("barbar"); assertThat(list).doesNotContain("narf").as("bar").contains("barbar");
} }
assertThat(list.get(0)).isNotEmpty().hasSize(3).isEqualTo("bar"); assertThat(list.get(0)).isNotEmpty().hasSize(3).isEqualTo("bar");
assertThat(otherList.get(0)).isNotEmpty();
assertThat(list.get(0)).hasSize(3);
assertThat(list.get(0) + "foo").isEqualTo("bar").doesNotStartWith("foo"); assertThat(list.get(0) + "foo").isEqualTo("bar").doesNotStartWith("foo");
assertThat(otherList.get(0) + "foo").isEqualTo("bar");
assertThat(list.get(0) + "foo").doesNotStartWith("foo");
Iterator<String> iterator = list.iterator(); Iterator<String> iterator = list.iterator();
assertThat(iterator.next()).isEqualTo("foo"); assertThat(iterator.next()).isEqualTo("foo");
assertThat(iterator.next()).isEqualTo("bar"); assertThat(iterator.next()).isEqualTo("bar");
assertThat(iterator.next().toLowerCase()).isEqualTo("foo");
assertThat(iterator.next().toLowerCase()).isEqualTo("bar");
} }
} }
@@ -6,6 +6,8 @@ public class JoinStatements {
private void joinStatements() { private void joinStatements() {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
List<String> otherList = new ArrayList<>();
// the future is always born in pain // the future is always born in pain
/* tricky */assertThat(list).as("foo").hasSize(2); /* do one */ /* do another */ /* tricky */assertThat(list).as("foo").hasSize(2); /* do one */ /* do another */
assertThat(list).as("bar").contains("barbar"); // comment to keep assertThat(list).as("bar").contains("barbar"); // comment to keep
@@ -24,7 +26,7 @@ public class JoinStatements {
assertThat(list).as("evil").extracting(String::length).contains(2); assertThat(list).as("evil").extracting(String::length).contains(2);
assertThat(list).as("bar").contains("barbar"); assertThat(list).as("bar").contains("barbar");
assertThat("narf").isNotEqualTo("puit"); assertThat(otherList).contains("puit");
assertThat(list).as("foo").hasSize(2); assertThat(list).as("foo").hasSize(2);
if (true) { if (true) {
assertThat(list).doesNotContain("narf"); assertThat(list).doesNotContain("narf");
@@ -34,11 +36,19 @@ public class JoinStatements {
assertThat(list.get(0)).hasSize(3); assertThat(list.get(0)).hasSize(3);
assertThat(list.get(0)).isEqualTo("bar"); assertThat(list.get(0)).isEqualTo("bar");
assertThat(otherList.get(0)).isNotEmpty();
assertThat(list.get(0)).hasSize(3);
assertThat(list.get(0) + "foo").isEqualTo("bar"); assertThat(list.get(0) + "foo").isEqualTo("bar");
assertThat(list.get(0) + "foo").doesNotStartWith("foo"); assertThat(list.get(0) + "foo").doesNotStartWith("foo");
assertThat(otherList.get(0) + "foo").isEqualTo("bar");
assertThat(list.get(0) + "foo").doesNotStartWith("foo");
Iterator<String> iterator = list.iterator(); Iterator<String> iterator = list.iterator();
assertThat(iterator.next()).isEqualTo("foo"); assertThat(iterator.next()).isEqualTo("foo");
assertThat(iterator.next()).isEqualTo("bar"); assertThat(iterator.next()).isEqualTo("bar");
assertThat(iterator.next().toLowerCase()).isEqualTo("foo");
assertThat(iterator.next().toLowerCase()).isEqualTo("bar");
} }
} }
@@ -10,5 +10,8 @@ public class ObjectIsNull {
assertThat("").isNotNull(); assertThat("").isNotNull();
assertThat("").as("nah").isNotNull(); assertThat("").as("nah").isNotNull();
assertThat(new Object()).isNotNull(); assertThat(new Object()).isNotNull();
assertThat(new Object()).as("foo").isNotNull().as("bar").isEqualTo(new Object()).as("etc").isNull();
assertThat(new Object()).as("foo").isEqualTo(null).as("bar").isEqualTo(new Object()).as("etc").isNotNull();
} }
} }
@@ -10,5 +10,8 @@ public class ObjectIsNull {
assertThat("").isNotEqualTo(null); assertThat("").isNotEqualTo(null);
assertThat("").as("nah").isNotEqualTo(null); assertThat("").as("nah").isNotEqualTo(null);
assertThat(new Object()).isNotEqualTo(null); assertThat(new Object()).isNotEqualTo(null);
assertThat(new Object()).as("foo").isNotEqualTo(null).as("bar").isEqualTo(new Object()).as("etc").isEqualTo(null);
assertThat(new Object()).as("foo").isEqualTo(null).as("bar").isEqualTo(new Object()).as("etc").isNotEqualTo(null);
} }
} }
@@ -95,5 +95,9 @@ public class Size {
assertThat(stringBuilder).hasSameSizeAs(array); assertThat(stringBuilder).hasSameSizeAs(array);
assertThat(stringBuilder).hasSameSizeAs(string); assertThat(stringBuilder).hasSameSizeAs(string);
assertThat(stringBuilder).hasSameSizeAs(stringBuilder); assertThat(stringBuilder).hasSameSizeAs(stringBuilder);
assertThat(stringBuilder.length()).as("foo").isEqualTo(0).isZero().as("bar").isNotZero().isEqualTo(10);
assertThat(stringBuilder).as("foo").isNotEmpty().hasSize(2).as("bar").hasSameSizeAs(otherList).hasSameSizeAs(array);
} }
} }
@@ -95,5 +95,9 @@ public class Size {
assertThat(stringBuilder).hasSize(array.length); assertThat(stringBuilder).hasSize(array.length);
assertThat(stringBuilder).hasSize(string.length()); assertThat(stringBuilder).hasSize(string.length());
assertThat(stringBuilder).hasSize(stringBuilder.length()); assertThat(stringBuilder).hasSize(stringBuilder.length());
assertThat(stringBuilder.length()).as("foo").isEqualTo(0).isZero().as("bar").isNotZero().isEqualTo(10);
assertThat(stringBuilder).as("foo").isNotEmpty().hasSize(2).as("bar").hasSize(otherList.size()).hasSize(array.length);
} }
} }
@@ -6,7 +6,7 @@ public class StringExpression {
String string = "string"; String string = "string";
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
assertThat(string).isEmpty(); assertThat(string).as("foo").isEmpty();
assertThat(string).isEmpty(); assertThat(string).isEmpty();
assertThat(string).isEqualTo("foo"); assertThat(string).isEqualTo("foo");
assertThat(string).isEqualTo("foo"); assertThat(string).isEqualTo("foo");
@@ -25,7 +25,7 @@ public class StringExpression {
assertThat(string).endsWith("foo"); assertThat(string).endsWith("foo");
assertThat(string).endsWith("foo"); assertThat(string).endsWith("foo");
assertThat(string).isNotEmpty(); assertThat(string).as("foo").isNotEmpty();
assertThat(string).isNotEmpty(); assertThat(string).isNotEmpty();
assertThat(string).isNotEqualTo("foo"); assertThat(string).isNotEqualTo("foo");
assertThat(string).isNotEqualTo("foo"); assertThat(string).isNotEqualTo("foo");
@@ -43,5 +43,9 @@ public class StringExpression {
assertThat(string).doesNotStartWith("foo"); assertThat(string).doesNotStartWith("foo");
assertThat(string).doesNotEndWith("foo"); assertThat(string).doesNotEndWith("foo");
assertThat(string).doesNotEndWith("foo"); assertThat(string).doesNotEndWith("foo");
assertThat(string).as("foo").doesNotEndWith("foo").as("bar").doesNotEndWith("foo");
assertThat(string.endsWith("foo")).as("foo").isEqualTo(false).as("bar").isTrue();
assertThat(string.endsWith("foo")).as("foo").satisfies(it -> it.booleanValue()).as("bar").isFalse();
} }
} }
@@ -6,7 +6,7 @@ public class StringExpression {
String string = "string"; String string = "string";
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
assertThat(string.isEmpty()).isEqualTo(true); assertThat(string.isEmpty()).as("foo").isEqualTo(true);
assertThat(string.isEmpty()).isTrue(); assertThat(string.isEmpty()).isTrue();
assertThat(string.equals("foo")).isEqualTo(true); assertThat(string.equals("foo")).isEqualTo(true);
assertThat(string.equals("foo")).isTrue(); assertThat(string.equals("foo")).isTrue();
@@ -14,8 +14,8 @@ public class StringExpression {
assertThat(string.equalsIgnoreCase("foo")).isTrue(); assertThat(string.equalsIgnoreCase("foo")).isTrue();
assertThat(string.contentEquals("foo")).isEqualTo(true); assertThat(string.contentEquals("foo")).isEqualTo(true);
assertThat(string.contentEquals("foo")).isTrue(); assertThat(string.contentEquals("foo")).isTrue();
assertThat(string.contentEquals(stringBuilder)).isTrue();
assertThat(string.contentEquals(stringBuilder)).isEqualTo(true); assertThat(string.contentEquals(stringBuilder)).isEqualTo(true);
assertThat(string.contentEquals(stringBuilder)).isTrue();
assertThat(string.contains("foo")).isEqualTo(true); assertThat(string.contains("foo")).isEqualTo(true);
assertThat(string.contains("foo")).isTrue(); assertThat(string.contains("foo")).isTrue();
assertThat(string.contains(stringBuilder)).isEqualTo(true); assertThat(string.contains(stringBuilder)).isEqualTo(true);
@@ -25,7 +25,7 @@ public class StringExpression {
assertThat(string.endsWith("foo")).isEqualTo(true); assertThat(string.endsWith("foo")).isEqualTo(true);
assertThat(string.endsWith("foo")).isTrue(); assertThat(string.endsWith("foo")).isTrue();
assertThat(string.isEmpty()).isEqualTo(false); assertThat(string.isEmpty()).as("foo").isEqualTo(false);
assertThat(string.isEmpty()).isFalse(); assertThat(string.isEmpty()).isFalse();
assertThat(string.equals("foo")).isEqualTo(false); assertThat(string.equals("foo")).isEqualTo(false);
assertThat(string.equals("foo")).isFalse(); assertThat(string.equals("foo")).isFalse();
@@ -33,8 +33,8 @@ public class StringExpression {
assertThat(string.equalsIgnoreCase("foo")).isFalse(); assertThat(string.equalsIgnoreCase("foo")).isFalse();
assertThat(string.contentEquals("foo")).isEqualTo(false); assertThat(string.contentEquals("foo")).isEqualTo(false);
assertThat(string.contentEquals("foo")).isFalse(); assertThat(string.contentEquals("foo")).isFalse();
assertThat(string.contentEquals(stringBuilder)).isFalse();
assertThat(string.contentEquals(stringBuilder)).isEqualTo(false); assertThat(string.contentEquals(stringBuilder)).isEqualTo(false);
assertThat(string.contentEquals(stringBuilder)).isFalse();
assertThat(string.contains("foo")).isEqualTo(false); assertThat(string.contains("foo")).isEqualTo(false);
assertThat(string.contains("foo")).isFalse(); assertThat(string.contains("foo")).isFalse();
assertThat(string.contains(stringBuilder)).isEqualTo(false); assertThat(string.contains(stringBuilder)).isEqualTo(false);
@@ -43,5 +43,9 @@ public class StringExpression {
assertThat(string.startsWith("foo")).isFalse(); assertThat(string.startsWith("foo")).isFalse();
assertThat(string.endsWith("foo")).isEqualTo(false); assertThat(string.endsWith("foo")).isEqualTo(false);
assertThat(string.endsWith("foo")).isFalse(); assertThat(string.endsWith("foo")).isFalse();
assertThat(string.endsWith("foo")).as("foo").isEqualTo(false).as("bar").isFalse();
assertThat(string.endsWith("foo")).as("foo").isEqualTo(false).as("bar").isTrue();
assertThat(string.endsWith("foo")).as("foo").satisfies(it -> it.booleanValue()).as("bar").isFalse();
} }
} }

Some files were not shown because too many files have changed in this diff Show More