The JoinAssertThatStatements inspection will now add line breaks on joining statements.

Unrelated: Upgraded Gradle to 5.4.1. Upgraded kotlin to 1.3.40. Upgraded jacoco to 0.8.4. Minor style change for immediate returns. Increased test/branch coverage.
This commit is contained in:
Chris Hodges 2019-06-23 18:51:12 +02:00
parent 5c455c3ca9
commit 095345a456
57 changed files with 283 additions and 194 deletions

View File

@ -79,7 +79,8 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
```
from: assertThat(expected).someCondition();
assertThat(expected).anotherCondition();
to: assertThat(expected).someCondition().anotherCondition();
to: assertThat(expected).someCondition()
.anotherCondition();
```
Joining will work on actual expressions inside ```assertThat()``` that are equivalent expressions,
except for method calls with known side-effect methods such as ```Iterator.next()``` and
@ -87,6 +88,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
The comments of the statements will be preserved. When using ```extracting()``` or similar,
the statements will not be merged.
The behavior regarding the insertion of line breaks between the expressions can be configured in the
inspection settings.
- AssertThatObjectIsNullOrNotNull
@ -516,6 +520,10 @@ Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for yo
## Changelog
#### V1.2 (23-Jun-19)
- Due to popular demand the JoinAssertThatStatements inspection will now add line breaks on joining statements.
The amount of statements joined without causing line breaks can be configured but defaults to 1 (always).
#### V1.1 (09-Jun-19)
- Improved JoinAssertThatStatements detection of expressions with side-effects and added pre/post-increment/decrement detection.
- Added Guava Optional ```opt.orNull() == null``` case. You know, I'm not making this stuff up, people actually write this kind of code.

View File

@ -1,13 +1,13 @@
plugins {
id 'java'
id 'org.jetbrains.intellij' version '0.4.9'
id 'org.jetbrains.kotlin.jvm' version '1.3.31'
id 'org.jetbrains.kotlin.jvm' version '1.3.40'
id 'jacoco'
id 'com.github.kt3k.coveralls' version '2.8.2'
}
group 'de.platon42'
version '1.1'
version '1.2'
repositories {
mavenCentral()
@ -22,8 +22,8 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
testCompile "org.assertj:assertj-core:3.12.2"
testCompile "org.assertj:assertj-guava:3.2.1"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.0-RC1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.0-RC1'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.0-RC2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.0-RC2'
testImplementation "org.jetbrains.kotlin:kotlin-test"
// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
}
@ -35,23 +35,17 @@ compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
intellij {
version '2019.1.2'
version '2019.1.3'
// pluginName 'Concise AssertJ Optimizing Nitpicker (Cajon)'
updateSinceUntilBuild false
}
patchPluginXml {
changeNotes """
<h4>V1.1 (09-Jun-19)</h4>
<h4>V1.2 (23-Jun-19)</h4>
<ul>
<li>Improved JoinAssertThatStatements detection of expressions with side-effects and added pre/post-increment/decrement detection.
<li>Added Guava Optional opt.orNull() == null case. You know, I'm not making this stuff up, people actually write this kind of code.
<li>Added Java 8 Optional opt.orElse(null) == null case, too.
<li>Extended JUnitAssertToAssertJ inspection to convert JUnit assume statements, too.
<li>Improved JUnitAssertToAssertJ quick fix to swap expected and actual expressions if the actual one is a constant.
<li>New ImplicitAssertion inspection for implicit isNotNull(), isNotEmpty() and isPresent() assertions that will be covered by chained assertions.
<li>Fix for multiple JUnit Conversions in batch mode with and without delta creating an exception.
<li>Added new AssertThatObjectExpression inspection for toString() and hashCode() and moved equals() from AssertThatBinaryExpression there.
<li>Due to popular demand the JoinAssertThatStatements inspection will now add line breaks on joining statements.
The amount of statements joined without causing line breaks can be configured but defaults to 1 (always).
</ul>
<p>Full changelog available at <a href="https://github.com/chrisly42/cajon-plugin#changelog">Github project site</a>.</p>
"""
@ -65,7 +59,7 @@ test {
}
jacoco {
toolVersion = '0.8.3'
toolVersion = '0.8.4'
}
jacocoTestReport {

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

View File

@ -144,9 +144,7 @@ fun PsiExpression.getAllTheSameExpectedBooleanConstants(): Boolean? {
for (methodCall in methodsToView) {
val expectedResult = methodCall.getExpectedBooleanResult()
if (expectedResult != null) {
if ((lockedResult != null) && (lockedResult != expectedResult)) {
return null
}
if ((lockedResult != null) && (lockedResult != expectedResult)) return null
lockedResult = expectedResult
} else {
val isNotConstant = CallMatcher.anyOf(
@ -157,9 +155,7 @@ fun PsiExpression.getAllTheSameExpectedBooleanConstants(): Boolean? {
AbstractAssertJInspection.IS_NOT_EQUAL_TO_BOOLEAN,
AbstractAssertJInspection.IS_NOT_EQUAL_TO_OBJECT
).test(methodCall)
if (isNotConstant) {
return null
}
if (isNotConstant) return null
}
}
return lockedResult
@ -173,9 +169,7 @@ fun PsiExpression.getAllTheSameNullNotNullConstants(): Boolean? {
for (methodCall in methodsToView) {
val expectedResult = methodCall.getExpectedNullNonNullResult()
if (expectedResult != null) {
if ((lockedResult != null) && (lockedResult != expectedResult)) {
return null
}
if ((lockedResult != null) && (lockedResult != expectedResult)) return null
lockedResult = expectedResult
} else {
val isNotConstant = CallMatcher.anyOf(
@ -184,9 +178,7 @@ fun PsiExpression.getAllTheSameNullNotNullConstants(): Boolean? {
AbstractAssertJInspection.IS_EQUAL_TO_OBJECT,
AbstractAssertJInspection.IS_NOT_EQUAL_TO_OBJECT
).test(methodCall)
if (isNotConstant) {
return null
}
if (isNotConstant) return null
}
}
return lockedResult

View File

@ -21,13 +21,9 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
@ -39,9 +35,9 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
val bothTypes = listOf(leftType, rightType)
val (isLeftNull, isRightNull) = bothTypes.map(TypeConversionUtil::isNullType)
if (isLeftNull && isRightNull) {
return
} else if (isLeftNull || isRightNull) {
if (isLeftNull && isRightNull) return
if (isLeftNull || isRightNull) {
val replacementMethod = expectedResult.map(MethodNames.IS_NULL, MethodNames.IS_NOT_NULL)
registerSplitMethod(holder, expectedCallExpression, replacementMethod) { desc, method ->
SplitBinaryExpressionMethodCallQuickFix(desc, method, pickRightOperand = isLeftNull, noExpectedExpression = true)

View File

@ -20,24 +20,17 @@ class AssertThatBooleanConditionInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val matchingCalls = listOf(
IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_BOOLEAN,
IS_NOT_EQUAL_TO_OBJECT, IS_NOT_EQUAL_TO_BOOLEAN
).map { it.test(expression) }
if (matchingCalls.none { it }) {
return
}
if (!checkAssertedType(expression, ABSTRACT_BOOLEAN_ASSERT_CLASSNAME)) {
return
}
if (matchingCalls.none { it }) return
if (!checkAssertedType(expression, ABSTRACT_BOOLEAN_ASSERT_CLASSNAME)) return
val expectedExpression = expression.firstArg
if (!TypeConversionUtil.isBooleanType(expectedExpression.type)) {
return
}
if (!TypeConversionUtil.isBooleanType(expectedExpression.type)) return
val expectedResult = expression.calculateConstantParameterValue(0) as? Boolean ?: return
val flippedBooleanTest = matchingCalls.drop(2).any { it }

View File

@ -44,13 +44,10 @@ class AssertThatCollectionOrMapExpressionInspection : AbstractAssertJInspection(
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val mapping = MAPPINGS.firstOrNull { it.callMatcher.test(assertThatArgument) } ?: return

View File

@ -21,13 +21,9 @@ class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val isLastExpression = expression.parent is PsiStatement
if (!(HAS_SIZE.test(expression) && isLastExpression)) {
return
}
if (!(HAS_SIZE.test(expression) && isLastExpression)) return
val value = expression.calculateConstantParameterValue(0) ?: return
if (value == 0) {

View File

@ -21,16 +21,12 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!checkPreconditions(staticMethodCall)) {
return
}
val actualExpression = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
if (!checkPreconditions(staticMethodCall)) return
val actualExpression = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val outmostMethodCall = statement.findOutmostMethodCall() ?: return
if (GUAVA_OPTIONAL_GET.test(actualExpression)) {
val expectedCallExpression = staticMethodCall.gatherAssertionCalls().singleOrNull() ?: return
@ -65,13 +61,10 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!checkPreconditions(staticMethodCall)) {
return
}
if (!checkPreconditions(staticMethodCall)) return
// 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)) {

View File

@ -20,13 +20,9 @@ class AssertThatInstanceOfInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return

View File

@ -18,13 +18,9 @@ class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection()
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
expression.getExpectedBooleanResult() ?: return
val prefixExpression = staticMethodCall.firstArg as? PsiPrefixExpression ?: return

View File

@ -20,15 +20,11 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_ANY.test(staticMethodCall)) {
return
}
val actualExpression = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
if (!ASSERT_THAT_ANY.test(staticMethodCall)) return
val actualExpression = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val outmostMethodCall = statement.findOutmostMethodCall() ?: return
if (OPTIONAL_GET.test(actualExpression)) {
val expectedCallExpression = staticMethodCall.gatherAssertionCalls().singleOrNull() ?: return
@ -58,13 +54,9 @@ class AssertThatJava8OptionalInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!ASSERT_THAT_JAVA8_OPTIONAL.test(staticMethodCall)) {
return
}
if (!ASSERT_THAT_JAVA8_OPTIONAL.test(staticMethodCall)) return
if (IS_EQUAL_TO_OBJECT.test(expression)) {
val innerExpectedCall = expression.firstArg as? PsiMethodCallExpression ?: return
if (CallMatcher.anyOf(OPTIONAL_OF, OPTIONAL_OF_NULLABLE).test(innerExpectedCall)) {

View File

@ -24,9 +24,7 @@ class AssertThatObjectExpressionInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return

View File

@ -19,15 +19,11 @@ class AssertThatObjectIsNullOrNotNullInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val isNotEqualTo = IS_NOT_EQUAL_TO_OBJECT.test(expression)
val isEqualTo = IS_EQUAL_TO_OBJECT.test(expression)
val isLastExpression = expression.parent is PsiStatement
if (!((isEqualTo && isLastExpression) || isNotEqualTo)) {
return
}
if (!((isEqualTo && isLastExpression) || isNotEqualTo)) return
if (expression.firstArg.type == PsiType.NULL) {
registerSimplifyMethod(holder, expression, isEqualTo.map(MethodNames.IS_NULL, MethodNames.IS_NOT_NULL))

View File

@ -74,19 +74,15 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_INT.test(staticMethodCall)) {
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
}
if (!(isForArrayOrCollection || isForString)) return
val matches = staticMethodCall.collectMethodCallsUpToStatement()
.mapNotNull { getMatch(it, isForArrayOrCollection, isForString) }
.toList()
@ -112,21 +108,16 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!HAS_SIZE.test(expression)) {
return
}
if (!expression.hasAssertThat()) return
if (!HAS_SIZE.test(expression)) return
val actualExpression = expression.firstArg
val isForArrayOrCollection = isArrayLength(actualExpression) || isCollectionSize(actualExpression)
val isForString = isCharSequenceLength(actualExpression)
if (!(isForArrayOrCollection
|| (isForString && checkAssertedType(expression, ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME)))
) {
return
}
) return
registerConciseMethod(
REMOVE_SIZE_DESCRIPTION_TEMPLATE,
holder,

View File

@ -48,13 +48,10 @@ class AssertThatStringExpressionInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) {
return
}
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
return
}
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val mapping = MAPPINGS.firstOrNull { it.callMatcher.test(assertThatArgument) } ?: return

View File

@ -22,19 +22,13 @@ class AssertThatStringIsEmptyInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val isEqual = IS_EQUAL_TO_OBJECT.test(expression)
val hasSize = HAS_SIZE.test(expression)
val isLastExpression = expression.parent is PsiStatement
if (!((isEqual || hasSize) && isLastExpression)) {
return
}
if (!((isEqual || hasSize) && isLastExpression)) return
if (!checkAssertedType(expression, ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME)) {
return
}
if (!checkAssertedType(expression, ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME)) return
val value = expression.calculateConstantParameterValue(0) ?: return
if ((isEqual && (value == "")) || (hasSize && (value == 0))) {

View File

@ -54,9 +54,7 @@ class AssumeThatInsteadOfReturnInspection : AbstractAssertJInspection() {
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
}
if (annotations.none(TEST_ANNOTATIONS::contains)) return
val containingClass = method.containingClass ?: return
val visitor: PsiElementVisitor = TestMethodVisitor(holder, isOnTheFly, containingClass)
method.accept(visitor)
@ -119,9 +117,7 @@ class AssumeThatInsteadOfReturnInspection : AbstractAssertJInspection() {
var aborted = false
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
if (foundAssertThat || aborted) {
return
}
if (foundAssertThat || aborted) return
if (++statementCount > MAX_STATEMENTS_COUNT) {
aborted = true
return

View File

@ -113,9 +113,8 @@ class ImplicitAssertionInspection : AbstractAssertJInspection() {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) {
return
}
if (!expression.hasAssertThat()) return
val mapping = MAPPINGS.firstOrNull { it.first.test(expression) } ?: return
val followupExpression = expression.findFluentCallTo(mapping.second) ?: return
val redundantName = getOriginalMethodName(expression) ?: return

View File

@ -2,19 +2,25 @@ package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.codeInspection.ui.SingleIntegerFieldOptionsPanel
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import com.siyeh.ig.psiutils.EquivalenceChecker
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.JoinStatementsQuickFix
import javax.swing.JComponent
class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
companion object {
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 DEFAULT_SEPARATE_LINE_LIMIT = 1
}
@JvmField
var separateLineLimit: Int = DEFAULT_SEPARATE_LINE_LIMIT
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
@ -63,9 +69,8 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
private fun isLegitAssertThatCall(statement: PsiStatement?): PsiMethodCallExpression? {
if ((statement is PsiExpressionStatement) && (statement.expression is PsiMethodCallExpression)) {
if (!statement.hasAssertThat()) {
return null
}
if (!statement.hasAssertThat()) return null
val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) }
return assertThatCall?.takeIf { it.findFluentCallTo(EXTRACTING_CALL_MATCHERS) == null }
}
@ -93,6 +98,10 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
}
}
override fun createOptionsPanel(): JComponent {
return SingleIntegerFieldOptionsPanel("Limit for joins before adding line breaks:", this, "separateLineLimit")
}
private fun registerProblem(holder: ProblemsHolder, isOnTheFly: Boolean, firstStatement: PsiStatement, lastStatement: PsiStatement) {
val problemDescriptor = holder.manager.createProblemDescriptor(
firstStatement,
@ -100,7 +109,7 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
CAN_BE_JOINED_DESCRIPTION,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
isOnTheFly,
JoinStatementsQuickFix()
JoinStatementsQuickFix(separateLineLimit)
)
holder.registerProblem(problemDescriptor)
}

View File

@ -7,7 +7,7 @@ import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.cajon.findStaticMethodCall
import de.platon42.intellij.plugins.cajon.shortenAndReformat
class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
class JoinStatementsQuickFix(private val separateLineLimit: Int) : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
companion object {
private const val JOIN_STATEMENTS_MESSAGE = "Join assertThat() statements"
@ -16,6 +16,10 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val firstStatement = descriptor.startElement as PsiExpressionStatement
val lastStatement = descriptor.endElement as PsiExpressionStatement
val expressionCount = countExpressions(firstStatement, lastStatement)
val addLineBreaks = (expressionCount > separateLineLimit)
do {
val commentsToKeep = ArrayList<PsiComment>()
val stuffToDelete = ArrayList<PsiElement>()
@ -37,10 +41,10 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
val lastElementBeforeConcat = assertThatCallOfCursorStatement.parent
commentsToKeep.forEach {
lastElementBeforeConcat.addAfter(it, lastElementBeforeConcat.firstChild)
val newLineNode =
PsiParserFacade.SERVICE.getInstance(project).createWhiteSpaceFromText("\n\t")
lastElementBeforeConcat.addAfter(newLineNode, lastElementBeforeConcat.firstChild)
addLineBreak(project, lastElementBeforeConcat)
}
if (commentsToKeep.isEmpty() && addLineBreaks) {
addLineBreak(project, lastElementBeforeConcat)
}
val newLeaf = previousStatement.firstChild
@ -50,4 +54,27 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
val codeBlock = PsiTreeUtil.getParentOfType(lastStatement, PsiCodeBlock::class.java) ?: return
codeBlock.shortenAndReformat()
}
private fun addLineBreak(project: Project, lastElementBeforeConcat: PsiElement) {
val newLineNode =
PsiParserFacade.SERVICE.getInstance(project).createWhiteSpaceFromText("\n\t")
lastElementBeforeConcat.addAfter(newLineNode, lastElementBeforeConcat.firstChild)
}
private fun countExpressions(firstStatement: PsiElement, lastStatement: PsiElement): Int {
var count = 0
var currentStatement = firstStatement
do {
while (currentStatement !is PsiExpressionStatement) {
currentStatement = currentStatement.nextSibling!!
}
count++
if (currentStatement === lastStatement) {
break
}
currentStatement = currentStatement.nextSibling!!
} while (true)
return count
}
}

View File

@ -7,7 +7,6 @@ import com.intellij.psi.*
import com.intellij.psi.util.PropertyUtilBase
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiTypesUtil
import com.intellij.util.ArrayUtil
import com.intellij.util.ProcessingContext
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
@ -56,11 +55,9 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
private fun findAndCreateReferences(element: PsiElement, finder: (PsiLiteralExpression) -> List<Pair<TextRange, List<PsiElement>>>?): Array<PsiReference> {
val literal = element as PsiLiteralExpression
val results = finder(literal)
if (results != null) {
return results.map { ExtractorReference(literal, it.first, it.second) }.toTypedArray()
}
return PsiReference.EMPTY_ARRAY
val results = finder(literal) ?: return PsiReference.EMPTY_ARRAY
return results.map { ExtractorReference(literal, it.first, it.second) }.toTypedArray()
}
}
@ -73,10 +70,6 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
class ExtractorReference(literal: PsiLiteralExpression, range: TextRange, private val targets: List<PsiElement>) :
PsiPolyVariantReferenceBase<PsiLiteralExpression>(literal, range, true) {
override fun getVariants(): Array<Any> {
return ArrayUtil.EMPTY_OBJECT_ARRAY
}
override fun resolve(): PsiElement? {
return multiResolve(false).map(ResolveResult::getElement).firstOrNull()
}
@ -88,9 +81,7 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
class PropertyOrFieldReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
return findAndCreateReferences(element, ::findReferences)
}
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> = findAndCreateReferences(element, ::findReferences)
fun findReferences(element: PsiLiteralExpression): List<Pair<TextRange, List<PsiElement>>>? {
val literal = element.value as? String ?: return null
@ -112,9 +103,7 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
class IterablePropertyOrFieldReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
return findAndCreateReferences(element, ::findReferences)
}
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> = findAndCreateReferences(element, ::findReferences)
fun findReferences(element: PsiLiteralExpression): List<Pair<TextRange, List<PsiElement>>>? {
val literal = element.value as? String ?: return null
@ -127,9 +116,8 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
isResultOf = true
}
if (!CallMatcher.anyOf(EXTRACTING_FROM_ITERABLE, FLAT_EXTRACTING_FROM_ITERABLE).test(methodCallExpression)) {
return null
}
if (!CallMatcher.anyOf(EXTRACTING_FROM_ITERABLE, FLAT_EXTRACTING_FROM_ITERABLE).test(methodCallExpression)) return null
val iterableType = findActualType(methodCallExpression) ?: return null
val innerType = iterableType.resolveGenerics().substitutor.substitute(iterableType.parameters[0])
val containingClass = PsiTypesUtil.getPsiClass(innerType) ?: return null
@ -139,16 +127,13 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
class IterableResultOfReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
return findAndCreateReferences(element, ::findReferences)
}
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> = findAndCreateReferences(element, ::findReferences)
fun findReferences(element: PsiLiteralExpression): List<Pair<TextRange, List<PsiElement>>>? {
val literal = element.value as? String ?: return null
val methodCallExpression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression::class.java) ?: return null
if (!EXTRACTING_RESULT_OF_FROM_ITERABLE.test(methodCallExpression)) {
return null
}
if (!EXTRACTING_RESULT_OF_FROM_ITERABLE.test(methodCallExpression)) return null
val iterableType = findActualType(methodCallExpression) ?: return null
val innerType = iterableType.resolveGenerics().substitutor.substitute(iterableType.parameters[0])
val containingClass = PsiTypesUtil.getPsiClass(innerType) ?: return null

View File

@ -7,15 +7,14 @@
Cajon is an IntelliJ IDEA Plugin for shortening and optimizing AssertJ assertions.
It adds several inspections and quick fixes to fully use the fluent assertion methods
and thus makes the intention clear and concise, also generating better messages on test failures.
It can also be used to convert JUnit 4 assertions to AssertJ.
It can also be used to convert JUnit 4 assertions and assumptions to AssertJ.
It supports referencing inside extracting()-methods with strings, adding refactoring safety.
<p>
<a href="https://github.com/chrisly42/cajon-plugin/blob/master/README.md">Full documentation here...</a>
]]></description>
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="173.2696.26"/>
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<depends>com.intellij.modules.lang</depends>
<depends>com.intellij.modules.platform</depends>
<depends>com.intellij.modules.java</depends>

View File

@ -2,6 +2,9 @@
<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.
<br>If the AssertThat()-Statement contains .extracting() methods, they will not be joined.
<br>During joining multiple statements, line breaks may be added to avoid too long lines. The number of statements to join without
adding line breaks can be configured.
<br>Also retains comments during operation and forces a line break for these cases.
</body>
</html>

View File

@ -23,6 +23,7 @@ abstract class AbstractCajonTest {
protected fun executeQuickFixes(myFixture: JavaCodeInsightTestFixture, regex: Regex, expectedFixes: Int) {
val quickfixes = myFixture.getAllQuickFixes().filter { it.text.matches(regex) }
assertThat(quickfixes).`as`("Fixes matched by $regex: ${myFixture.getAllQuickFixes().map { it.text }}").hasSize(expectedFixes)
quickfixes.forEach { it.familyName }
quickfixes.forEach(myFixture::launchAction)
}

View File

@ -5,6 +5,7 @@ import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.cajon.AbstractCajonTest
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.jupiter.api.Test
@ -70,4 +71,10 @@ internal class ExtractorReferenceContributorTest : AbstractCajonTest() {
myFixture.configureByFiles("FindReference10.java", "Address.java", "Contact.java")
assertThat(myFixture.elementAtCaret.text).startsWith("public String getStreetName()")
}
@Test
internal fun extractor_is_unable_to_find_reference(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.configureByFiles("FindReference11.java", "Address.java", "Contact.java")
assertThatThrownBy { myFixture.elementAtCaret.text }.isInstanceOf(AssertionError::class.java)
}
}

View File

@ -195,5 +195,8 @@ public class BinaryExpression {
assertThat(primAct == primExp).isFalse().as("doh!").isEqualTo(true);
assertThat(numberObjAct.equals(numberObjExp)).as("doh!").isTrue().isEqualTo(true);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -195,5 +195,8 @@ public class BinaryExpression {
assertThat(primAct == primExp).isFalse().as("doh!").isEqualTo(true);
assertThat(numberObjAct.equals(numberObjExp)).as("doh!").isTrue().isEqualTo(true);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -30,5 +30,9 @@ public class BooleanCondition {
assertThat("").isEqualTo(Boolean.TRUE);
assertThat(primitive).isTrue().as("foo").isTrue().as("bar").isTrue().isFalse();
assertThat(object).isEqualTo(Boolean.TYPE);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -30,5 +30,9 @@ public class BooleanCondition {
assertThat("").isEqualTo(Boolean.TRUE);
assertThat(primitive).isEqualTo(Boolean.TRUE).as("foo").isEqualTo(true).as("bar").isTrue().isFalse();
assertThat(object).isEqualTo(Boolean.TYPE);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -40,5 +40,8 @@ public class CollectionMapExpression {
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();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -40,5 +40,8 @@ public class CollectionMapExpression {
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();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -16,5 +16,8 @@ public class EnumerableIsEmpty {
assertThat(new Long[1]).as("etc").hasSize(1);
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").isEmpty();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -16,5 +16,8 @@ public class EnumerableIsEmpty {
assertThat(new Long[1]).as("etc").hasSize(1);
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").hasSize(0);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -56,5 +56,10 @@ public class GuavaOptional {
assertThat(opt).as("foo").isPresent().as("bar").isPresent();
assertThat(opt.isPresent()).as("foo").isEqualTo(true).as("bar").isEqualTo(Boolean.FALSE);
assertThat(opt.orNull()).as("foo").isEqualTo(null).isNotNull();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -56,5 +56,10 @@ public class GuavaOptional {
assertThat(opt.isPresent()).as("foo").isEqualTo(true).as("bar").isEqualTo(Boolean.TRUE);
assertThat(opt.isPresent()).as("foo").isEqualTo(true).as("bar").isEqualTo(Boolean.FALSE);
assertThat(opt.orNull()).as("foo").isEqualTo(null).isNotNull();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -284,5 +284,8 @@ public class ImplicitAssertion {
assertThat(guavaOptional).contains("foo");
assertThat(guavaOptional).extractingValue().isEqualTo("foo");
assertThat(guavaOptional).extractingCharSequence().isEqualTo("foo");
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -284,5 +284,8 @@ public class ImplicitAssertion {
assertThat(guavaOptional).isPresent().contains("foo");
assertThat(guavaOptional).isPresent().extractingValue().isEqualTo("foo");
assertThat(guavaOptional).isPresent().extractingCharSequence().isEqualTo("foo");
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -21,5 +21,8 @@ public class InstanceOf {
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);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -21,5 +21,8 @@ public class InstanceOf {
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);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -35,5 +35,8 @@ public class InvertedBooleanCondition {
assertThat(primitive).as("foo").isFalse().as("bar").isFalse();
assertThat(primitive).as("foo").isFalse().as("bar").isTrue();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -35,5 +35,8 @@ public class InvertedBooleanCondition {
assertThat(!primitive).as("foo").isEqualTo(Boolean.TRUE).as("bar").isNotEqualTo(false);
assertThat(!primitive).as("foo").isEqualTo(Boolean.TRUE).as("bar").isNotEqualTo(true);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -43,5 +43,10 @@ public class Java8Optional {
assertThat(opt.get()).isEqualTo("foo").isSameAs("foo").isNotEqualTo("foo").isNotSameAs("foo");
assertThat(opt.orElse("foo")).as("foo").isEqualTo(null);
assertThat(opt.orElse(null)).as("foo").isEqualTo(null).isNotNull();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -43,5 +43,10 @@ public class Java8Optional {
assertThat(opt.get()).isEqualTo("foo").isSameAs("foo").isNotEqualTo("foo").isNotSameAs("foo");
assertThat(opt.orElse("foo")).as("foo").isEqualTo(null);
assertThat(opt.orElse(null)).as("foo").isEqualTo(null).isNotNull();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -1,6 +1,7 @@
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class JoinStatements {
@ -24,21 +25,28 @@ public class JoinStatements {
.doesNotContain("foobar");
assertThat("narf").isNotEqualTo("puit");
assertThat(list).as("bar").contains("barbar").as("foo").hasSize(2);
assertThat(list).as("bar").contains("barbar")
.as("foo").hasSize(2);
assertThat(list).as("evil").extracting(String::length).contains(2);
assertThat(list).as("bar").contains("barbar");
assertThat(otherList).contains("puit");
assertThat(list).as("foo").hasSize(2);
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").isNotNull()
// hey, a comment mixed with line breaks due to too many joins
.isEqualTo("bar")
.doesNotStartWith("foo");
assertThat(otherList.get(0) + "foo").isEqualTo("bar");
assertThat(list.get(0) + "foo").doesNotStartWith("foo");
@ -57,5 +65,8 @@ public class JoinStatements {
assertThat(list.get(i++).toLowerCase()).isEqualTo("foo");
assertThat(list.get(--i)).isEqualTo("foo");
assertThat(list.get(--i)).isEqualTo("foo");
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -1,6 +1,7 @@
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class JoinStatements {
@ -39,6 +40,8 @@ public class JoinStatements {
assertThat(otherList.get(0)).isNotEmpty();
assertThat(list.get(0)).hasSize(3);
assertThat(list.get(0) + "foo").isNotNull();
// hey, a comment mixed with line breaks due to too many joins
assertThat(list.get(0) + "foo").isEqualTo("bar");
assertThat(list.get(0) + "foo").doesNotStartWith("foo");
@ -59,5 +62,8 @@ public class JoinStatements {
assertThat(list.get(i++).toLowerCase()).isEqualTo("foo");
assertThat(list.get(--i)).isEqualTo("foo");
assertThat(list.get(--i)).isEqualTo("foo");
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -23,5 +23,8 @@ public class ObjectExpression {
assertThat(object.equals(otherObject)).isEqualTo(foo);
assertThat(object).as("doh!").isEqualTo(otherObject).isEqualTo(otherObject);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -23,5 +23,8 @@ public class ObjectExpression {
assertThat(object.equals(otherObject)).isEqualTo(foo);
assertThat(object.equals(otherObject)).as("doh!").isTrue().isEqualTo(true);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -13,5 +13,8 @@ public class ObjectIsNull {
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();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -13,5 +13,8 @@ public class ObjectIsNull {
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);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -99,5 +99,12 @@ public class Size {
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);
int foo = 1;
assertThat(foo).isEqualTo(0);
assertThat(string.length()).isPositive();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -99,5 +99,12 @@ public class Size {
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);
int foo = 1;
assertThat(foo).isEqualTo(0);
assertThat(string.length()).isPositive();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -49,5 +49,8 @@ public class StringExpression {
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();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -49,5 +49,8 @@ public class StringExpression {
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();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -18,5 +18,8 @@ public class StringIsEmpty {
assertThat(string).as("foo").isEqualTo("").as("bar").hasSize(0).hasSameSizeAs("foo").isEmpty();
assertThat(string).as("foo").isEqualTo("").as("bar").hasSize(0).hasSameSizeAs("foo").isEmpty();
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -18,5 +18,8 @@ public class StringIsEmpty {
assertThat(string).as("foo").isEqualTo("").as("bar").hasSize(0).hasSameSizeAs("foo").isEqualTo("");
assertThat(string).as("foo").isEqualTo("").as("bar").hasSize(0).hasSameSizeAs("foo").hasSize(0);
org.junit.Assert.assertThat(foo, null);
fail("oh no!");
}
}

View File

@ -0,0 +1,15 @@
import org.assertj.core.extractor.Extractors;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class FindReference10 {
private void findReferences() {
List<Contact> contactList = Collections.emptyList();
assertThat(contactList).extracting("narf<caret>").isEqualTo("foo");
}
}