Compare commits

...
38 Commits
Author SHA1 Message Date
chrisly42 a657d2bfaa Updated readme for release. Typofix. 2022-08-15 23:13:31 +02:00
chrisly42 bb7497b494 Fix for issue #6. 2022-08-15 23:04:20 +02:00
chrisly42 1ba1363dd2 Added AssertThatIsZeroOneInspection. 2022-08-15 22:44:45 +02:00
chrisly42 c29d644f56 Updated dependencies, attempt to fix NPE, workaround for scheduled removal of a static field in PsiParserFacade.
Added PluginVerifier to build.gradle.
2022-08-15 21:39:32 +02:00
chrisly42 2d92d71af0 Travis-CI.com now? Really? 2021-07-16 21:44:04 +02:00
chrisly42 01c6b141ee Updated various dependencies (Kotlin 1.5.21) and AssertJ 3.20.2. Latest Gradle. Migrated to latest intellij-gradle-plugin. Slightly fixed a situation in LightCodeInsightExtension, where the fields were cleared in super-Method before they had been evaluated. 2021-07-16 19:59:38 +02:00
chrisly42 32eb8be1e3 Typofix. 2021-06-14 13:56:27 +02:00
chrisly42 6692ded98a Updated various dependencies (Kotlin 1.50.0) and AssertJ 3.19.0. Fixed issue#3 reported by hankem where usingRecursiveComparison() was not considered a complex transformation. 2021-05-06 12:42:23 +02:00
chrisly42 146465328c Cajon is written in Kotlin 1.4. 2020-10-02 23:14:23 +02:00
chrisly42 47dcc7ec5e Disable TSL 1.3 due to JDK11 bug for sending data to coveralls. 2020-10-02 23:06:38 +02:00
chrisly42 ce0b5ce872 Added inversion of boolean conditions inside isEqualTo() and isNotEqualTo() for InvertedBooleanCondition inspection. 2020-10-02 22:44:08 +02:00
chrisly42 d48c71d4ea Added several cases for hasSizeGreaterThan/LessThan/OrEqualTo() for EnumerablesEmpty inspection. 2020-10-02 19:24:22 +02:00
chrisly42 1340a34782 Fixed ImplicitAssertion crashing the plugin with IntelliJ 2020.3 EAP, added support for singleElement(). Unrelated: Documentation grammar fixes. 2020-10-02 18:54:23 +02:00
chrisly42 fbde6b3387 Upgraded gradle to 6.6.1.
Upgraded kotlin to 1.4.10.
Upgraded assertj to 3.17.2.
Upgraded junit-jupiter to 5.7.0.
Other minor upgrades.
2020-10-02 18:52:50 +02:00
chrisly42 b9110d226e Added a note about the plugin being for Java language projects only. 2020-10-02 16:21:29 +02:00
chrisly42 45307b364d Fixed two possible index out of bounds exceptions in ExtractorReferenceContributor and BogusAssertionInspection. Prepared release. 2020-07-31 17:01:13 +02:00
chrisly42 66b725c4d2 Updated libraries to the latest versions (including AssertJ 3.16.1 and Kotlin 1.40-rc).
Now uses Gradle 6.5.1.
2020-07-30 21:01:34 +02:00
chrisly42 48349a6528 Prepared for release. 2020-02-25 14:39:30 +01:00
chrisly42 9b25e50183 Improvements for TwistedAssertionInspection to no longer report .class types as constant to bother, nor matches() and doesNotMatch() for regexps. If both sides are constants, they will only show as weak problems. 2020-02-17 20:17:33 +01:00
chrisly42 e8ce8ce2c6 BogusAssertionInspection will no longer warn if the expression contains method calls and now tries to avoid valid hashCode() and equals() tests. 2020-02-17 18:33:11 +01:00
chrisly42 62f59b0fe2 Added new TwistedAssertion inspection that will warn about assertions with the actual expression being a constant indicating swapped use of actual and expected expressions.
Added new BogusAssertion inspection that showing typical copy and paste errors where actual and expected expressions are the same.
2020-02-14 13:36:04 +01:00
chrisly42 58298fabc6 Extended Testing-Framework to work around IntelliJ IDEA introducing an unwanted assertj-core dependency conflicting with our newer one. 2020-02-08 16:33:38 +01:00
chrisly42 77d3608fd3 Minor NPE Bugfix. Fixed use of "experimental API". Upgraded dependencies. 2020-02-04 20:01:05 +01:00
chrisly42 a0909d8c39 Prepared release. 2019-11-19 19:47:40 +01:00
chrisly42 5113cc15ab Added hasSize(), isEmpty() and isNotEmpty() for AssertThatFileExpression when using AssertJ >= 3.14.0. 2019-11-18 21:13:30 +01:00
chrisly42 ae2076a425 Bumped to AssertJ 3.14.0, AssertJ-Guava 3.3.0, Kotlin 1.3.60. IntelliJ-Plugin 0.4.13, Jacoco 0.8.5 2019-11-18 21:10:45 +01:00
chrisly42 42429c0f72 Added AssertThatComparableExpression for funny compareTo() uses. 2019-11-17 21:21:45 +01:00
chrisly42 8133f3850f Added first version of AssertThatPathExpression for a limited number transformations (more stuff is possible, but requires detection and transformation of static Files-methods). 2019-11-17 19:10:41 +01:00
chrisly42 8d03b3734c Fixed a lapsuus in AssertThatFileExpression also transforming listFiles() with a filter argument. 2019-11-17 17:14:28 +01:00
chrisly42 2f0d855d1e Minor documentation fixes. Prepared release. 2019-09-30 22:17:23 +02:00
chrisly42 6dab8ad552 Added several transformations to AssertThatStringExpression inspection. Specifically, uses of matches(), compareToIgnoreCase(), indexOf(), and trim(). 2019-09-30 20:27:43 +02:00
chrisly42 1983750077 Internal refactoring: Reduced code duplication by moving stuff into a common base class. 2019-09-30 17:25:16 +02:00
chrisly42 a0ed4eab76 Added new AssertThatFileExpression to move out many common methods from inside the assertThat() expression (exists(), getName(), getParent(), and many more). 2019-09-29 21:56:36 +02:00
chrisly42 acc81863f5 Fixed a bug in AssertThatBinaryExpression inspection for assertThat(null != expression) and related that would not correctly invert the condition on transformation. 2019-09-29 12:32:32 +02:00
chrisly42 2b97494c17 Really fixed AssertThatGuavaOptional inspections to avoid conversions from .get() to .contains() for array types. 2019-09-25 18:38:35 +02:00
chrisly42 e3444db213 Fixes to AssertThatSize inspection after extending it for Maps in previous release as not all combinations for .hasSameSizeAs() are supported.
Bumped to IntelliJ IDEA 2019.2.3.
2019-09-24 22:55:02 +02:00
chrisly42 855fb03f7c One more option for AssertThatCollectionOrMap inspection for warnings without quickfix.
AssertThatGuavaOptional inspections will now avoid conversions from .get() to .contains() for array types (currently not correctly supported by AssertJ-Guava).
2019-09-24 22:16:11 +02:00
chrisly42 8d678411b5 Fix for AssertThatCollectionOrMap inspection sometimes causing an index out of bounds exception.
Added an settings option for AssertThatCollectionOrMap inspection respecting the degenerated case of maps with null values.
Upgrade to JUnit Jupiter 5.5.2.
2019-09-09 23:13:45 +02:00
98 changed files with 3564 additions and 363 deletions
+1
View File
@@ -18,6 +18,7 @@
<option name="configurationPath" value="" />
<option name="exclusions">
<set>
<option value=".*\.md" />
<option value="src/test/resources/.*" />
</set>
</option>
+1 -1
View File
@@ -1,6 +1,6 @@
language: java
jdk:
- openjdk8
- openjdk11
before_script:
- chmod +x gradlew
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2019 Chris Hodges <chrisly@platon42.de>
Copyright 2019-2022 Chris Hodges <chrisly@platon42.de>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+377 -25
View File
@@ -1,4 +1,4 @@
# 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 - Concise AssertJ Optimizing Nitpicker [![Build Status](https://travis-ci.com/chrisly42/cajon-plugin.svg?branch=master)](https://travis-ci.com/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.
@@ -34,6 +34,10 @@ Then AssertJ would tell you the _actual contents_ of the collection on failure.
The plugin also supports the conversion of the most common JUnit 4 assertions to AssertJ.
## Wrong use of AssertJ
Cajon also warns about bogus or incorrect uses of AssertJ.
## Lookup and refactoring of string-based extracting()
AssertJ allows [extracting POJO fields/properties on iterables/arrays](http://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#extracted-properties-assertion).
@@ -42,12 +46,18 @@ Using strings is not safe for refactoring (and before Java 8 Lambdas were availa
creating extractor functions just for testing purpose was a bit too tedious).
This plugin adds support for referencing these fields (so you can ctrl(/cmd)-click on the
string to go to the definition) and also allows safe refactoring on the
string to go to the definition) and allows safe refactoring on the
fields (refactoring a getter method without a corresponding field will not work
correctly right now).
correctly right now) too.
## Usage
Cajon (though written in Kotlin) *only works with Java projects*.
There does not seem too much demand for AssertJ within Kotlin projects
and although possible, it would require a complete rewrite as the PSI
stuff in IntelliJ is very Java focused. Almost zero feedback is also not helping.
Enough bickering.
The plugin will report inspections in your opened editor file as warnings.
You can then quick-fix these with your quick-fix hotkey (usually Alt-Return or Opt-Return).
@@ -83,7 +93,7 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
.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
except for method calls with known side effect methods such as ```Iterator.next()``` and
pre/post-increment/decrement operations -- please notify me about others.
The comments of the statements will be preserved. When using ```extracting()``` or similar,
@@ -132,12 +142,19 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
- AssertThatInvertedBooleanCondition
Inverts the boolean condition to make it more readable.
Inverts the boolean condition in either ```assertThat()``` or ```isEqualTo()```/```isNotEqualTo()```
to make it more readable.
```
from: assertThat(!booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE);
from: assertThat(!booleanValue).isTrue()/isFalse();
to: assertThat(booleanValue).isFalse()/isTrue();
from: assertThat(booleanValue).isEqualTo(!primitiveBooleanExpression);
to: assertThat(booleanValue).isNotEqualTo(primitiveBooleanExpression);
from: assertThat(booleanValue).isNotEqualTo(!primitiveBooleanExpression);
to: assertThat(booleanValue).isEqualTo(primitiveBooleanExpression);
```
- AssertThatInstanceOf
@@ -154,6 +171,23 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
to: assertThat(object).isNotInstanceOf(classname.class);
```
- AssertThatIsZeroOne
Uses ```isZero()```, ```isNotZero()``` and ```isOne()``` instead.
Works with shorts, integers, longs, floats and doubles, and tries to evaluate
constant expressions, too.
```
from: assertThat(numeric).isEqualTo(0);
to: assertThat(numeric).isZero();
from: assertThat(numeric).isNotEqualTo(0);
to: assertThat(numeric).isNotZero();
from: assertThat(numeric).isEqualTo(1);
to: assertThat(numeric).isOne();
```
- AssertThatStringIsEmpty
Uses ```isEmpty()``` for empty string assertions.
@@ -189,12 +223,39 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
from: assertThat(stringActual.endsWith(stringExpected)).isTrue();
to: assertThat(stringActual).endsWith(stringExpected);
from: assertThat(stringActual.matches(stringExpected)).isTrue();
to: assertThat(stringActual).matches(stringExpected);
```
Analogously with ```isFalse()```.
More funny stuff (excerpt):
```
from: assertThat(stringActual.compareToIgnoreCase(stringExpected)).isEqualTo(0);
to: assertThat(stringActual).isEqualToIgnoringCase(stringExpected);
from: assertThat(stringActual.indexOf(stringExpected)).isEqualTo(0);
from: assertThat(stringActual.indexOf(stringExpected)).isZero();
to: assertThat(stringActual).startsWith(stringExpected);
from: assertThat(stringActual.indexOf(stringExpected)).isNotZero();
to: assertThat(stringActual).doesNotStartWith(stringExpected);
from: assertThat(stringActual.indexOf(stringExpected)).isEqualTo(-1);
from: assertThat(stringActual.indexOf(stringExpected)).isNegative();
to: assertThat(stringActual).doesNotContain(stringExpected);
from: assertThat(stringActual.indexOf(stringExpected)).isGreaterThanOrEqualTo(0);
to: assertThat(stringActual).contains(stringExpected);
from: assertThat(stringActual.trim()).isNotEmpty();
to: assertThat(stringActual).isNotBlank();
```
- AssertThatObjectExpression
Handles equals(), toString() and hashCode() inside an expected expression.
Handles ```equals()```, ```toString()``` and ```hashCode()``` inside an expected expression.
```
from: assertThat(objActual.equals(objExpected)).isTrue();
@@ -207,9 +268,38 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
to: assertThat(objActual).hasSameHashCodeAs(objExpected);
```
- AssertThatComparableExpression
Handles ```compareTo()``` inside an expected expression.
```
from: assertThat(obj1.compareTo(obj2)).isEqualTo(0);
to: assertThat(obj1).isEqualByComparingTo(obj2);
from: assertThat(obj1.compareTo(obj2)).isNotZero();
to: assertThat(obj1).isNotEqualByComparingTo(obj2);
from: assertThat(obj1.compareTo(obj2)).isNotEqualTo(-1);
from: assertThat(obj1.compareTo(obj2)).isGreaterThanOrEqualTo(0);
from: assertThat(obj1.compareTo(obj2)).isGreaterThan(-1);
from: assertThat(obj1.compareTo(obj2)).isNotNegative();
to: assertThat(obj1).isGreaterThanOrEqualTo(obj2);
from: assertThat(obj1.compareTo(obj2)).isOne();
to: assertThat(obj1).isGreaterThan(obj2);
from: assertThat(obj1.compareTo(obj2)).isNotPositive();
to: assertThat(obj1).isLessThanOrEqualTo(obj2);
from: assertThat(obj1.compareTo(obj2)).isLessThan(0);
to: assertThat(obj1).isLessThan(obj2);
```
Several more combinations omitted...
- AssertThatCollectionOrMapExpression
Moves collection and map operations inside ```assertThat()``` out.
Moves ```Collection``` and ```Map``` operations inside ```assertThat()``` out.
```
from: assertThat(collection.isEmpty()).isTrue();
@@ -232,7 +322,7 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
```
Analogously with ```isFalse()``` (except for ```containsAll()```).
Additional transformations for maps:
Additional transformations for ```Map``` instances:
```
from: assertThat(map.get(key)).isEqualTo(value);
@@ -248,19 +338,128 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
to: assertThat(map).doesNotContainKey(key);
```
The last transformation is the default, but may not be 100% equivalent depending upon the map
being a degenerated case with ```null``` values, where ```map.get(key)``` returns ```null```,
but ```containsKey(key)``` is ```true```.
For that special case (which is usually the result of a bad design decision!)
the quickfix should rather generate ```assertThat(map).containsEntry(key, null)```.
Therefore, the behavior can be configured in the settings for this inspection to either
create the default case (```doesNotContainKey```), the degenerated case (```containsEntry```),
choosing between both fixes (does not work well for batch processing), or ignore this edge case
altogether (just to be sure to not break any code).
- AssertThatFileExpression
Moves ```File``` method calls inside ```assertThat()``` out.
```
from: assertThat(file.canRead()).isTrue();
to: assertThat(file).canRead();
from: assertThat(file.canWrite()).isTrue();
to: assertThat(file).canWrite();
from: assertThat(file.exists()).isTrue();
to: assertThat(file).exists();
from: assertThat(file.exists()).isFalse();
to: assertThat(file).doesNotExist();
from: assertThat(file.isAbsolute()).isTrue();
to: assertThat(file).isAbsolute();
from: assertThat(file.isAbsolute()).isFalse();
to: assertThat(file).isRelative();
from: assertThat(file.isDirectory()).isTrue();
to: assertThat(file).isDirectory();
from: assertThat(file.isFile()).isTrue();
to: assertThat(file).isFile();
from: assertThat(file.getName()).isEqualTo(filename);
to: assertThat(file).hasName(filename);
from: assertThat(file.getParent()).isEqualTo(pathname);
to: assertThat(file).hasParent(pathname);
from: assertThat(file.getParent()).isNull();
from: assertThat(file.getParentFile()).isNull();
to: assertThat(file).hasNoParent();
from: assertThat(file.list()).isEmpty();
from: assertThat(file.listFiles()).isEmpty();
to: assertThat(file).isEmptyDirectory();
from: assertThat(file.list()).isNotEmpty();
from: assertThat(file.listFiles()).isNotEmpty();
to: assertThat(file).isNotEmptyDirectory();
```
and additionally with AssertJ 3.14.0 or later
```
from: assertThat(file.length()).isEqualTo(0);
from: assertThat(file.length()).isZero();
to: assertThat(file).isEmpty();
from: assertThat(file.length()).isNotEqualTo(0);
from: assertThat(file.length()).isNotZero();
to: assertThat(file).isNotEmpty();
from: assertThat(file.length()).isEqualTo(len);
to: assertThat(file).hasSize(len);
```
- AssertThatPathExpression
Moves ```Path``` method calls inside ```assertThat()``` out.
Note: Uses hasParentRaw() instead of hasParent() for quickfixes, because it is semantically
equivalent. For most cases though, hasParent() will show identical behavior.
```
from: assertThat(path.isAbsolute()).isTrue();
to: assertThat(path).isAbsolute();
from: assertThat(path.isAbsolute()).isFalse();
to: assertThat(path).isRelative();
from: assertThat(path.getParent()).isEqualTo(pathname);
to: assertThat(path).hasParentRaw(pathname);
from: assertThat(path.getParent()).isNull();
to: assertThat(path).hasNoParentRaw();
from: assertThat(path.startsWith(otherPath)).isTrue();
to: assertThat(path).startsWithRaw(otherPath);
from: assertThat(path.endsWith(otherPath)).isTrue();
to: assertThat(path).endsWithRaw(otherPath);
```
- AssertThatEnumerableIsEmpty
Uses ```isEmpty()``` for ```hasSize(0)``` iterable assertions instead.
Uses ```isEmpty()``` for ```hasSize(0)```, ```hasSizeLessThanOrEqualTo(0)```, and
```hasSizeLessThan(1)``` iterable (enumerable) assertions instead.
Also suggests ```isNotEmpty()``` for ```hasSizeGreaterThan(0)``` and
```hasSizeGreaterThanOrEqualTo(1)```.
```
from: assertThat(enumerable).hasSize(0);
from: assertThat(enumerable).hasSizeLessThanOrEqualTo(0);
from: assertThat(enumerable).hasSizeLessThan(1);
to: assertThat(enumerable).isEmpty();
from: assertThat(enumerable).hasSizeGreaterThan(0);
from: assertThat(enumerable).hasSizeGreaterThanOrEqualTo(1);
to: assertThat(enumerable).isNotEmpty();
```
- AssertThatSize
Makes assertions on sizes of arrays, collections, maps, strings,
or ```CharSequence```s more concise.
Makes assertions on sizes on ```Array```, ```Collection```,
```Map```, ```String```, or ```CharSequence``` instances more concise.
```
from: assertThat(array.length).isEqualTo(0);
@@ -296,14 +495,15 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
from: assertThat(array.length).isGreaterThanOrEqualTo(expression);
to: assertThat(array).hasSizeGreaterThanOrEqualTo(expression);
```
and analogously for collections, maps, strings and CharSequences, e.g:
and analogously for ```Collection```, ```Map```, ```String``` and
```CharSequence``` objects, e.g:
```
from: assertThat("string".length()).isLessThan(1);
to: assertThat("string").isEmpty();
from: assertThat("string".length()).isEqualTo(map.size())
to: assertThat("string").hasSameSizeAs(map);
from: assertThat(map.size()).isEqualTo(anotherMap.size())
to: assertThat(map).hasSameSizeAs(anotherMap);
from: assertThat("string".length()).hasSize("strong".length())
to: assertThat("string").hasSameSizeAs("strong");
@@ -328,6 +528,84 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
```
...and many, many more combinations (more than 150).
- TwistedAssertion
Examines the actual expression for common mistakes such as mixing expected and actual expression.
For simple cases, a quick fix is offered to swap them. Otherwise, only a warning is issued.
```
from: assertThat(5).isEqualTo(variable);
to: assertThat(variable).isEqualTo(5);
from: assertThat(8.0).isGreaterThan(variable);
to: assertThat(variable).isLessOrEqualTo(8.0);
```
There are, of course, more variations of the theme.
If both sides of an assertion are constant expressions, the problem will only appear as
a weak warning without a quick fix.
Constants used on the actual side of ```.matches()``` and ```doesNotMatch()``` will not be
reported for regular expression testing.
Neither will a ```Class``` type be considered a constant in the classic sense, so
```assertThat(SomeClass.class).isAssignableFrom(SomeOtherClass.class)``` will not be reported.
- BogusAssertion
Sometimes programmers make copy and paste or logical errors writing down assertions
that will never fail due to the same actual and expected assertions.
This inspection will warn about obvious cases such as the following ones.
```
assertThat(object).isEqualTo(object);
assertThat(object).isSameAs(object);
assertThat(object).hasSameClassAs(object);
assertThat(object).hasSameHashCodeAs(object);
assertThat(array).hasSameSizeAs(array);
assertThat(array).contains(array);
assertThat(array).containsAnyOf(array);
assertThat(array).containsExactly(array);
assertThat(array).containsExactlyInAnyOrder(array);
assertThat(array).containsExactlyInAnyOrder(array);
assertThat(array).containsOnly(array);
assertThat(array).containsSequence(array);
assertThat(array).containsSubsequence(array);
assertThat(array).startsWith(array);
assertThat(array).endsWith(array);
assertThat(enumerable).hasSameSizeAs(enumerable);
assertThat(iterable).hasSameElementsAs(iterable);
assertThat(iterable).containsAll(iterable);
assertThat(iterable).containsAnyElementOf(iterable);
assertThat(iterable).containsOnlyElementsOf(iterable);
assertThat(iterable).containsExactlyElementsOf(iterable);
assertThat(iterable).containsSequence(iterable);
assertThat(iterable).containsSubsequence(iterable);
assertThat(charSeq).isEqualToIgnoringCase(charSeq);
assertThat(charSeq).startsWith(charSeq);
assertThat(charSeq).endsWith(charSeq);
assertThat(charSeq).containsSequence(charSeq);
assertThat(charSeq).containsSubsequence(charSeq);
assertThat(map).containsAllEntriesOf(map);
assertThat(map).containsExactlyEntriesOf(map);
assertThat(map).containsExactlyInAnyOrderEntriesOf(map);
assertThat(map).hasSameSizeAs(map);
```
Note that expressions with method calls will not cause a warning as the method call might have side effects
that result in the assertion not being bogus at all.
If the assertions is either ```isEqualTo()``` or ```hasSameHashCodeAs()``` it may be checking custom
```equals()``` or ```hashCode()``` behavior. If the test method name containing the statement has a
name that contains 'equal' or 'hashcode' (case-insensitive), the warning will be weakened to information
level.
- ImplicitAssertion
Detects and removes implicit use of ```isNotNull()```, ```isNotEmpty()``` and
@@ -423,7 +701,7 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
to: assertThat(opt).isPresent();
```
AssertJ for Guava needs to be available in the classpath.
AssertJ for Guava needs to be available in the classpath for this inspection to work.
- AssumeThatInsteadOfReturn
@@ -516,6 +794,8 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
### Implemented referencing
You can ctrl-click on references inside .extracting() method parameters to go the
referencing method definition.
```
.extracting("field")
.extracting("outerField.fieldInsideObjectTypeOfOuterField.andSoOn")
@@ -529,35 +809,107 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
.flatExtracting(Extractors.byName("fieldOrPropertyOrBareMethod.orAPathLikeAbove")
.flatExtracting(Extractors.resultOf("bareMethod")
```
Works on both POJOs and ```Iterable```s/```Array```s.
This works on both POJOs and ```Iterable```s/```Array```s.
Implementation is very basic though and does not work with fancy cascaded ```.extracting()``` sequences.
If there's demand, I could add it.
## Development notice
Cajon is written in Kotlin 1.3.
Cajon is written in Kotlin 1.7.
Cajon is probably the only plugin that uses JUnit 5 Jupiter for unit testing so far (or at least the only one that I'm aware of ;) ).
The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing and it took me quite a while to make it work with JUnit 5.
Cajon is probably the only plugin that uses JUnit 5 Jupiter for unit testing so far (or at least the only one I'm aware of ;) ).
The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing, and it took me quite a while to make it work with JUnit 5.
Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for your projects (with attribution).
## Planned features
- More Optional fixes such as opt1.get() == opt2.get() etc.
- More moving out of methods for File, Path, LocalDate/Time etc.
- Converting ```foo.compareTo(bar) == 0``` to ```isEqualTo()``` (yes, I've *really* seen code like that)
- Extraction with property names to lambda with Java 8
- More Optional fixes such as ```opt1.get() == opt2.get()``` etc.
- More moving out of methods for LocalDate/Time etc.
- assertThat(foo.toLowerCase()/toUpperCase()).isEqualTo("foo") -> assertThat(foo).isEqualToIgnoringCase()
- Extraction with property names to lambda/method reference with Java 8
```
from: assertThat(object).extracting("propOne", "propNoGetter", "propTwo.innerProp")...
to: assertThat(object).extracting(type::getPropOne, it -> it.propNoGetter, it -> it.getPropTwo().getInnerProp())...
```
- Support primitives in assertThat(map.containsKey(1)).isTrue();
## Changelog
### V1.13 (15-Aug-22)
- Maintenance. Updated various dependencies (Kotlin 1.7.10) and AssertJ 3.23.1 and AssertJ-Guava 3.5.0.
- Tried to fix unreproducible issue #9.
- Added workaround for upcoming API change in IntelliJ breaking older releases.
- Added AssertThatIsZeroOne inspection demanded by issue #5.
- Fix for wrongly joining statements that cannot be trivially joined (e.g. with filteredOn). Fixes issue #6.
### V1.12 (06-May-21)
- Maintenance. Updated various dependencies (Kotlin 1.50.0) and AssertJ 3.19.0
- Fixed issue#3 reported by hankem where usingRecursiveComparison() was not considered a complex transformation.
#### V1.11 (03-Oct-20) Day of German Unity Edition
- Now is being built with JDK 11 (with Java 8 target).
- Updated various dependencies (Kotlin 1.40.10) and AssertJ 3.17.2.
- Fixed the ImplicitAssertion inspection that broke the plugin with IntelliJ 2020.3 EAP as reported by Frédéric Thomas.
Thanks!
- Added new singleElement() from AssertJ >= 3.17.0 to ImplicitAssertionInspection.
- Added several cases for ```hasSizeGreaterThan/LessThan/OrEqualTo()``` for EnumerablesEmpty inspection.
- Added inversion of boolean conditions inside ```isEqualTo()``` and ```isNotEqualTo()``` for InvertedBooleanCondition
inspection.
#### V1.10 (31-Jul-20) Friday the 31st Edition
- Updated libraries to the latest versions (including AssertJ 3.16.1 and Kotlin 1.40-rc).
- Fixed two possible index out-of-bounds exceptions in ExtractorReferenceContributor and BogusAssertionInspection.
#### V1.9 (25-Feb-20) Mardi Gras Edition
- TwistedAssertion inspection will no longer warn for ```.matches()``` and ```doesNotMatch()``` for regular expressions.
Apparently, ```assertThat("somestring").matches(regex)``` is a valid test if the regex is what needs to be tested.
If the actual expression is of ```Class``` type, this will no longer be reported.
- If the expected expression in TwistedAssertion is also a constant, the warning will be weakened and
no quick fix will be available.
- BogusAssertion inspection will no longer warn if the expression contains method calls.
Moreover, for assertions of ```isEqualTo()``` and ```hasSameHashCodeAs()```, AND if the containing method name contains 'equal' or 'hashcode',
the warning will be reduced to information level as the assertion may be testing ```equals()``` or ```hashCode()``` for validity.
#### V1.8 (14-Feb-20) Valentine Edition
- Maintenance. Removed experimental API use. Updated dependencies. Fixed testing problems introduced with IntelliJ IDEA 2019.3
- Added new TwistedAssertion inspection that will warn about assertions with the actual expression being a constant indicating
swapped use of actual and expected expressions.
- Added new BogusAssertion inspection that showing typical copy and paste errors where actual and expected expressions are the same.
#### V1.7 (19-Nov-19)
- Fixed a lapsuus in AssertThatFileExpression also transforming ```.listFiles()``` with a filter argument.
- Added first version of AssertThatPathExpression for a limited number transformations (more stuff is possible,
but requires detection and transformation of static ```Files```-methods).
- Added AssertThatComparableExpression for funny ```compareTo()``` uses.
- Added ```hasSize(), isEmpty()``` and ```isNotEmpty()``` for AssertThatFileExpression when using AssertJ >= 3.14.0.
#### V1.6 (30-Sep-19)
- Really fixed AssertThatGuavaOptional inspections to avoid conversions from ```.get()``` to ```.contains()```
for array types. Sigh. Shouldn't be working >12h a day and then do some more stuff at home.
- Fixed a bug in AssertThatBinaryExpression inspection for ```assertThat(null != expression)``` and related
that would not correctly invert the condition on transformation.
- Added new AssertThatFileExpression to move out many common methods from inside the
```assertThat()``` expression (```exists(), getName(), getParent()```, and many more).
- Added several transformations to AssertThatStringExpression inspection.
Specifically, uses of ```matches()```, ```compareToIgnoreCase()```, ```indexOf()```, and ```trim()```.
#### V1.5 (24-Sep-19)
- Fix for AssertThatCollectionOrMap inspection sometimes causing an index out-of-bounds exception.
- AssertThatGuavaOptional inspections will now avoid conversions from ```.get()``` to ```.contains()```
for array types (currently not correctly supported by ```contains()``` in AssertJ-Guava).
- Added a settings option for AssertThatCollectionOrMap inspection respecting the degenerated case of maps with ```null``` values.
It is now possible to change the behavior for ```map.get(key) == null```, so it can offer either ```.doesNotContainKey()``` (default)
or ```.containsEntry(key, null)```, or even both.
- Fixes to AssertThatSize inspection after extending it for Maps in previous release as not all
combinations for ```.hasSameSizeAs()``` are supported.
#### V1.4 (25-Aug-19)
- Minor fix for highlighting of JoinVarArgsContains inspection.
- Extended AssertThatSize inspection to Maps, too.
- Extended AssertThatCollectionOrMap inspection for several ```assertThat(map.get())``` cases as suggested by Stefan H.
- Extended AssertThatCollectionOrMap inspection for several ```assertThat(map.get())``` cases as suggested by Georgij G.
#### V1.3 (03-Aug-19)
- New JoinVarArgsContains inspection that will detect multiple ```.contains()```, ```.doesNotContain()```,
@@ -634,7 +986,7 @@ Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for yo
#### V0.2 (01-Apr-19)
- Fixed descriptions and quick fix texts.
- Fixed highlighting of found problems and also 'Run inspection by Name' returning nothing.
- Fixed highlighting of found problems and 'Run inspection by Name' returning nothing, too.
#### V0.1 (31-Mar-19)
- Initial release.
+38 -22
View File
@@ -1,13 +1,15 @@
plugins {
id 'java'
id 'org.jetbrains.intellij' version '0.4.10'
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
id 'org.jetbrains.intellij' version '1.8.0'
id 'org.jetbrains.kotlin.jvm' version '1.7.10'
id 'jacoco'
id 'com.github.kt3k.coveralls' version '2.8.4'
id 'com.github.kt3k.coveralls' version '2.12.0'
}
group 'de.platon42'
version '1.4'
version '1.13'
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
repositories {
mavenCentral()
@@ -20,37 +22,47 @@ repositories {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
testCompile "org.assertj:assertj-core:3.13.2"
testCompile "org.assertj:assertj-guava:3.2.1"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.1'
testImplementation "org.assertj:assertj-core:3.23.1"
testImplementation "org.assertj:assertj-guava:3.5.0"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
intellij {
version '2019.2.1'
// pluginName 'Concise AssertJ Optimizing Nitpicker (Cajon)'
updateSinceUntilBuild false
plugins = ['java']
setVersion("2022.2") // LATEST-EAP-SNAPSHOT
//pluginName.set(provider { 'Concise AssertJ Optimizing Nitpicker (Cajon)' })
setUpdateSinceUntilBuild(false)
setPlugins(["com.intellij.java"])
}
runPluginVerifier {
ideVersions = ["IC-193.5662.53", "IC-222.3345.118"] // 2020.3 - 2022.2
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/verifier"
}
patchPluginXml {
changeNotes """
<h4>V1.4 (25-Aug-19)</h4>
setChangeNotes("""
<h4>V1.13 (15-Aug-22)</h4>
<ul>
<li>Minor fix for highlighting of JoinVarArgsContains inspection.
<li>Extended AssertThatSize inspection to Maps, too.
<li>Extended AssertThatCollectionOrMap inspection for several assertThat(map.get()) cases as suggested by Stefan H.
<li>Maintenance. Updated various dependencies (Kotlin 1.7.10) and AssertJ 3.23.1 and AssertJ-Guava 3.5.0.
<li>Tried to fix unreproducible issue #9.
<li>Added workaround for upcoming API change in IntelliJ breaking older releases.
<li>Added AssertThatIsZeroOne inspection demanded by issue #5.
<li>Fix for wrongly joining statements that cannot be trivially joined (e.g. with filteredOn). Fixes issue #6.
</ul>
<p>Full changelog available at <a href="https://github.com/chrisly42/cajon-plugin#changelog">Github project site</a>.</p>
"""
""")
}
test {
@@ -60,17 +72,21 @@ test {
}
}
tasks.test {
systemProperty("idea.force.use.core.classloader", "true")
}
jacoco {
toolVersion = '0.8.4'
toolVersion = '0.8.8'
}
jacocoTestReport {
reports {
xml.enabled true
csv.enabled false
xml.required.set(true)
csv.required.set(false)
}
}
publishPlugin {
token intellijPublishToken
setToken(intellijPublishToken)
}
+1
View File
@@ -1,3 +1,4 @@
kotlin.code.style=official
kotlin.incremental=true
intellijPublishToken=perm:dummy
systemProp.jdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"
Binary file not shown.
+1 -2
View File
@@ -1,6 +1,5 @@
#Thu Feb 21 17:35:51 CET 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
Vendored
+34 -21
View File
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -56,7 +72,7 @@ case "`uname`" in
Darwin* )
darwin=true
;;
MINGW* )
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -138,19 +156,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
Vendored
+24 -19
View File
@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
@@ -12,46 +12,100 @@ class AssertJClassNames {
@NonNls
const val DESCRIPTABLE_INTERFACE = "org.assertj.core.api.Descriptable"
@NonNls
const val EXTENSION_POINTS_INTERFACE = "org.assertj.core.api.ExtensionPoints"
@NonNls
const val ENUMERABLE_ASSERT_INTERFACE = "org.assertj.core.api.EnumerableAssert"
@NonNls
const val OBJECT_ENUMERABLE_ASSERT_INTERFACE = "org.assertj.core.api.ObjectEnumerableAssert"
@NonNls
const val ASSERT_INTERFACE = "org.assertj.core.api.Assert"
@NonNls
const val ABSTRACT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractAssert"
@NonNls
const val ABSTRACT_OBJECT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractObjectAssert"
@NonNls
const val ABSTRACT_BOOLEAN_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractBooleanAssert"
@NonNls
const val ABSTRACT_SHORT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractShortAssert"
@NonNls
const val ABSTRACT_INTEGER_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractIntegerAssert"
@NonNls
const val ABSTRACT_LONG_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractLongAssert"
@NonNls
const val ABSTRACT_FLOAT_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractFloatAssert"
@NonNls
const val ABSTRACT_DOUBLE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractDoubleAssert"
@NonNls
const val ABSTRACT_COMPARABLE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractComparableAssert"
@NonNls
const val ABSTRACT_STRING_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractStringAssert"
@NonNls
const val ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractCharSequenceAssert"
@NonNls
const val ABSTRACT_MAP_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractMapAssert"
@NonNls
const val ABSTRACT_BOOLEAN_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractBooleanArrayAssert"
@NonNls
const val ABSTRACT_BYTE_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractByteArrayAssert"
@NonNls
const val ABSTRACT_SHORT_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractShortArrayAssert"
@NonNls
const val ABSTRACT_INT_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractIntArrayAssert"
@NonNls
const val ABSTRACT_LONG_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractLongArrayAssert"
@NonNls
const val ABSTRACT_FLOAT_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractFloatArrayAssert"
@NonNls
const val ABSTRACT_DOUBLE_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractDoubleArrayAssert"
@NonNls
const val ABSTRACT_CHAR_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractCharArrayAssert"
@NonNls
const val ABSTRACT_OBJECT_ARRAY_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractObjectArrayAssert"
@NonNls
const val ABSTRACT_ITERABLE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractIterableAssert"
@NonNls
const val ABSTRACT_FILE_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractFileAssert"
@NonNls
const val ABSTRACT_OPTIONAL_ASSERT_CLASSNAME = "org.assertj.core.api.AbstractOptionalAssert"
@NonNls
const val EXTRACTORS_CLASSNAME = "org.assertj.core.extractor.Extractors"
@NonNls
const val GUAVA_OPTIONAL_CLASSNAME = "com.google.common.base.Optional"
@NonNls
const val GUAVA_ASSERTIONS_CLASSNAME = "org.assertj.guava.api.Assertions"
@NonNls
const val GUAVA_OPTIONAL_ASSERTIONS_CLASSNAME = "org.assertj.guava.api.OptionalAssert"
}
@@ -21,24 +21,50 @@ val EXTRACTING_CALL_MATCHERS = CallMatcher.anyOf(
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 USING_COMPARATOR = CallMatcher.anyOf(
CallMatcher.instanceCall(
AssertJClassNames.ASSERT_INTERFACE,
"usingComparator",
"usingDefaultComparator"
),
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ASSERT_CLASSNAME, "usingRecursiveComparison"),
CallMatcher.instanceCall(
AssertJClassNames.ABSTRACT_OBJECT_ASSERT_CLASSNAME,
"usingComparatorForFields",
"usingComparatorForType"
)
)!!
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"
"singleElement", "hasOnlyOneElementSatisfying", "anyMatch", "noneMatch", "anySatisfy", "noneSatisfy"
)!!
val FILTERED_ON = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME, "filteredOn", "filteredOnNull", "filteredOnAssertions")!!
val COMPLEX_CALLS_THAT_MAKES_STUFF_TRICKY = CallMatcher.anyOf(
EXTRACTING_CALL_MATCHERS,
DESCRIBED_AS,
WITH_REPRESENTATION_AND_SUCH,
FILTERED_ON,
USING_COMPARATOR,
IN_HEXADECIMAL_OR_BINARY
)!!
val COMPLEX_STUFF_THAT_MAKES_JOINING_IMPOSSIBLE = CallMatcher.anyOf(
EXTRACTING_CALL_MATCHERS,
WITH_REPRESENTATION_AND_SUCH,
FILTERED_ON,
USING_COMPARATOR,
IN_HEXADECIMAL_OR_BINARY
)!!
@@ -1,6 +1,5 @@
package de.platon42.intellij.plugins.cajon
import com.intellij.lang.jvm.JvmModifier
import com.intellij.psi.*
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.codeStyle.JavaCodeStyleManager
@@ -33,7 +32,7 @@ fun PsiElement.findOutmostMethodCall(): PsiMethodCallExpression? {
fun PsiElement.findStaticMethodCall(): PsiMethodCallExpression? {
var elem: PsiElement? = this
while (elem != null) {
if ((elem is PsiMethodCallExpression) && (elem.resolveMethod()?.hasModifier(JvmModifier.STATIC) == true)) {
if ((elem is PsiMethodCallExpression) && (elem.resolveMethod()?.hasModifierProperty(PsiModifier.STATIC) == true)) {
return elem
}
elem = elem.firstChild
@@ -44,7 +43,7 @@ fun PsiElement.findStaticMethodCall(): PsiMethodCallExpression? {
fun PsiElement.gatherAssertionCalls(): List<PsiMethodCallExpression> {
val assertThatMethodCall = findStaticMethodCall() ?: return emptyList()
return assertThatMethodCall.collectMethodCallsUpToStatement()
.filterNot { NOT_ACTUAL_ASSERTIONS.test(it) }
.filterNot(NOT_ACTUAL_ASSERTIONS::test)
.toList()
}
@@ -116,8 +115,7 @@ fun PsiMethodCallExpression.getExpectedNullNonNullResult(): Boolean? {
}
fun PsiMethodCallExpression.calculateConstantParameterValue(argIndex: Int): Any? {
if (argIndex >= argumentList.expressions.size) return null
return getArg(argIndex).calculateConstantValue()
return getArgOrNull(argIndex)?.calculateConstantValue()
}
fun PsiExpression.calculateConstantValue(): Any? {
@@ -17,19 +17,25 @@ class MethodNames {
@NonNls
const val AS = "as"
@NonNls
const val DESCRIBED_AS = "describedAs"
@NonNls
const val IN_HEXADECIMAL = "inHexadecimal"
@NonNls
const val IN_BINARY = "inBinary"
@NonNls
const val IS_EQUAL_TO = "isEqualTo"
@NonNls
const val IS_NOT_EQUAL_TO = "isNotEqualTo"
@NonNls
const val IS_SAME_AS = "isSameAs"
@NonNls
const val IS_NOT_SAME_AS = "isNotSameAs"
@@ -38,85 +44,133 @@ class MethodNames {
@NonNls
const val IS_GREATER_THAN = "isGreaterThan"
@NonNls
const val IS_GREATER_THAN_OR_EQUAL_TO = "isGreaterThanOrEqualTo"
@NonNls
const val IS_LESS_THAN = "isLessThan"
@NonNls
const val IS_LESS_THAN_OR_EQUAL_TO = "isLessThanOrEqualTo"
@NonNls
const val IS_ZERO = "isZero"
@NonNls
const val IS_NOT_ZERO = "isNotZero"
@NonNls
const val IS_ONE = "isOne"
@NonNls
const val IS_TRUE = "isTrue"
@NonNls
const val IS_FALSE = "isFalse"
@NonNls
const val IS_NULL = "isNull" // terminal, returns void
@NonNls
const val IS_NOT_NULL = "isNotNull"
@NonNls
const val IS_CLOSE_TO = "isCloseTo"
@NonNls
const val IS_NOT_CLOSE_TO = "isNotCloseTo"
@NonNls
const val IS_INSTANCE_OF = "isInstanceOf"
@NonNls
const val IS_NOT_INSTANCE_OF = "isNotInstanceOf"
@NonNls
const val IS_NULL_OR_EMPTY = "isNullOrEmpty" // terminal, returns void
@NonNls
const val IS_EMPTY = "isEmpty" // terminal, returns void
@NonNls
const val IS_NOT_EMPTY = "isNotEmpty"
@NonNls
const val HAS_SIZE = "hasSize"
@NonNls
const val HAS_SIZE_LESS_THAN = "hasSizeLessThan"
@NonNls
const val HAS_SIZE_LESS_THAN_OR_EQUAL_TO = "hasSizeLessThanOrEqualTo"
@NonNls
const val HAS_SIZE_GREATER_THAN = "hasSizeGreaterThan"
@NonNls
const val HAS_SIZE_GREATER_THAN_OR_EQUAL_TO = "hasSizeGreaterThanOrEqualTo"
@NonNls
const val HAS_SAME_SIZE_AS = "hasSameSizeAs"
@NonNls
const val CONTAINS = "contains"
@NonNls
const val CONTAINS_ONLY_ONCE = "containsOnlyOnce"
@NonNls
const val DOES_NOT_CONTAIN = "doesNotContain"
@NonNls
const val CONTAINS_EXACTLY = "containsExactly"
@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 CONTAINS_ENTRY = "containsEntry"
@NonNls
const val DOES_NOT_CONTAIN_ENTRY = "doesNotContainEntry"
@NonNls
const val IS_EQUAL_TO_IC = "isEqualToIgnoringCase"
@NonNls
const val IS_NOT_EQUAL_TO_IC = "isNotEqualToIgnoringCase"
@NonNls
const val STARTS_WITH = "startsWith"
@NonNls
const val ENDS_WITH = "endsWith"
@NonNls
const val DOES_NOT_START_WITH = "doesNotStartWith"
@NonNls
const val DOES_NOT_END_WITH = "doesNotEndWith"
@NonNls
const val CONTAINS_SAME = "containsSame"
@NonNls
const val IS_PRESENT = "isPresent"
@NonNls
const val IS_NOT_PRESENT = "isNotPresent"
@@ -15,6 +15,7 @@ import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_D
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_FLOAT_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_INTEGER_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_LONG_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_SHORT_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_STRING_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ASSERTIONS_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ASSERT_INTERFACE
@@ -25,7 +26,7 @@ import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.qualifierExpression
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSimpleMethodCallQuickFix
open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
abstract class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
companion object {
const val SIMPLIFY_MESSAGE_TEMPLATE = "%s() can be simplified to %s()"
@@ -72,6 +73,8 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
val ASSERT_THAT_BOOLEAN = CallMatcher.staticCall(ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)
.parameterTypes("boolean")!!
val ASSERT_THAT_BOOLEAN_OBJ = CallMatcher.staticCall(ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)
.parameterTypes(CommonClassNames.JAVA_LANG_BOOLEAN)!!
val ASSERT_THAT_ANY = CallMatcher.staticCall(ASSERTIONS_CLASSNAME, MethodNames.ASSERT_THAT)
.parameterCount(1)!!
@@ -86,6 +89,8 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val IS_EQUAL_TO_STRING = CallMatcher.instanceCall(ABSTRACT_STRING_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO)
.parameterTypes(CommonClassNames.JAVA_LANG_STRING)!!
val IS_EQUAL_TO_SHORT = CallMatcher.instanceCall(ABSTRACT_SHORT_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO)
.parameterTypes("short")!!
val IS_EQUAL_TO_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO)
.parameterTypes("int")!!
val IS_EQUAL_TO_LONG = CallMatcher.instanceCall(ABSTRACT_LONG_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO)
@@ -101,6 +106,8 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val IS_NOT_EQUAL_TO_BOOLEAN = CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO)
.parameterTypes("boolean")!!
val IS_NOT_EQUAL_TO_SHORT = CallMatcher.instanceCall(ABSTRACT_SHORT_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO)
.parameterTypes("short")!!
val IS_NOT_EQUAL_TO_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO)
.parameterTypes("int")!!
val IS_NOT_EQUAL_TO_LONG = CallMatcher.instanceCall(ABSTRACT_LONG_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO)
@@ -120,10 +127,20 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
val IS_NOT_NULL = CallMatcher.instanceCall(ASSERT_INTERFACE, MethodNames.IS_NOT_NULL)
.parameterCount(0)!!
val IS_EMPTY = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.IS_EMPTY)
.parameterCount(0)!!
val IS_NOT_EMPTY = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.IS_NOT_EMPTY)
.parameterCount(0)!!
val HAS_SIZE = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE)
.parameterTypes("int")!!
val HAS_SIZE_GREATER_THAN_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_GREATER_THAN)
.parameterTypes("int")!!
val HAS_SIZE_GREATER_THAN_OR_EQUAL_TO_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_GREATER_THAN_OR_EQUAL_TO)
.parameterTypes("int")!!
val HAS_SIZE_LESS_THAN_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_LESS_THAN)
.parameterTypes("int")!!
val HAS_SIZE_LESS_THAN_OR_EQUAL_TO_INT = CallMatcher.instanceCall(ENUMERABLE_ASSERT_INTERFACE, MethodNames.HAS_SIZE_LESS_THAN_OR_EQUAL_TO)
.parameterTypes("int")!!
val IS_GREATER_THAN_INT = CallMatcher.instanceCall(ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_GREATER_THAN)
.parameterTypes("int")!!
@@ -135,9 +152,23 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
val IS_LESS_THAN_OR_EQUAL_TO_INT = CallMatcher.instanceCall(ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_LESS_THAN_OR_EQUAL_TO)
.parameterTypes("int")!!
val IS_ZERO = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, MethodNames.IS_ZERO)
val IS_ZERO_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, MethodNames.IS_ZERO)
.parameterCount(0)!!
val IS_NOT_ZERO = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, MethodNames.IS_NOT_ZERO)
val IS_NOT_ZERO_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, MethodNames.IS_NOT_ZERO)
.parameterCount(0)!!
val IS_ZERO_LONG = CallMatcher.instanceCall(ABSTRACT_LONG_ASSERT_CLASSNAME, MethodNames.IS_ZERO)
.parameterCount(0)!!
val IS_NOT_ZERO_LONG = CallMatcher.instanceCall(ABSTRACT_LONG_ASSERT_CLASSNAME, MethodNames.IS_NOT_ZERO)
.parameterCount(0)!!
val IS_ONE_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, "isOne")
.parameterCount(0)!!
val IS_NEGATIVE_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, "isNegative")
.parameterCount(0)!!
val IS_NOT_NEGATIVE_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, "isNotNegative")
.parameterCount(0)!!
val IS_POSITIVE_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, "isPositive")
.parameterCount(0)!!
val IS_NOT_POSITIVE_INT = CallMatcher.instanceCall(ABSTRACT_INTEGER_ASSERT_CLASSNAME, "isNotPositive")
.parameterCount(0)!!
val IS_TRUE = CallMatcher.instanceCall(ABSTRACT_BOOLEAN_ASSERT_CLASSNAME, MethodNames.IS_TRUE)
@@ -151,12 +182,12 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
.parameterCount(0)!!
val CHAR_SEQUENCE_LENGTH = CallMatcher.instanceCall("java.lang.CharSequence", "length")
.parameterCount(0)!!
val OBJECT_EQUALS = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_OBJECT, "equals")
val OBJECT_EQUALS = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_OBJECT, MethodNames.EQUALS)
.parameterTypes(CommonClassNames.JAVA_LANG_OBJECT)!!
val OPTIONAL_GET = CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "get")
.parameterCount(0)!!
val OPTIONAL_IS_PRESENT = CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "isPresent")
val OPTIONAL_IS_PRESENT = CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_OPTIONAL, MethodNames.IS_PRESENT)
.parameterCount(0)!!
val OPTIONAL_OR_ELSE = CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "orElse")
.parameterCount(1)!!
@@ -170,7 +201,7 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
val GUAVA_OPTIONAL_GET = CallMatcher.instanceCall(GUAVA_OPTIONAL_CLASSNAME, "get")
.parameterCount(0)!!
val GUAVA_OPTIONAL_IS_PRESENT = CallMatcher.instanceCall(GUAVA_OPTIONAL_CLASSNAME, "isPresent")
val GUAVA_OPTIONAL_IS_PRESENT = CallMatcher.instanceCall(GUAVA_OPTIONAL_CLASSNAME, MethodNames.IS_PRESENT)
.parameterCount(0)!!
val GUAVA_OPTIONAL_OR_NULL = CallMatcher.instanceCall(GUAVA_OPTIONAL_CLASSNAME, "orNull")
.parameterCount(0)!!
@@ -227,6 +258,20 @@ open class AbstractAssertJInspection : AbstractBaseJavaLocalInspectionTool() {
holder.registerProblem(expression, message, quickfix)
}
protected fun registerMoveOutMethod(
holder: ProblemsHolder,
expression: PsiMethodCallExpression,
oldActualExpression: PsiMethodCallExpression,
replacementMethod: String,
quickFixSupplier: (String) -> List<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 quickfixes = quickFixSupplier(description)
holder.registerProblem(expression, message, *quickfixes.toTypedArray())
}
protected fun registerReplaceMethod(
holder: ProblemsHolder,
expression: PsiMethodCallExpression,
@@ -4,39 +4,51 @@ import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool
import com.intellij.psi.PsiMethodCallExpression
import org.jetbrains.annotations.NonNls
open class AbstractJUnitAssertInspection : AbstractBaseJavaLocalInspectionTool() {
abstract class AbstractJUnitAssertInspection : AbstractBaseJavaLocalInspectionTool() {
companion object {
@NonNls
const val JUNIT_ASSERT_CLASSNAME = "org.junit.Assert"
@NonNls
const val JUNIT_ASSUME_CLASSNAME = "org.junit.Assume"
@NonNls
const val ASSERT_TRUE_METHOD = "assertTrue"
@NonNls
const val ASSERT_FALSE_METHOD = "assertFalse"
@NonNls
const val ASSERT_NULL_METHOD = "assertNull"
@NonNls
const val ASSERT_NOT_NULL_METHOD = "assertNotNull"
@NonNls
const val ASSERT_EQUALS_METHOD = "assertEquals"
@NonNls
const val ASSERT_NOT_EQUALS_METHOD = "assertNotEquals"
@NonNls
const val ASSERT_SAME_METHOD = "assertSame"
@NonNls
const val ASSERT_NOT_SAME_METHOD = "assertNotSame"
@NonNls
const val ASSERT_ARRAY_EQUALS_METHOD = "assertArrayEquals"
@NonNls
const val ASSUME_TRUE_METHOD = "assumeTrue"
@NonNls
const val ASSUME_FALSE_METHOD = "assumeFalse"
@NonNls
const val ASSUME_NOT_NULL_METHOD = "assumeNotNull"
@NonNls
const val ASSUME_NO_EXCEPTION = "assumeNoException"
@@ -0,0 +1,64 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiExpressionStatement
import com.intellij.psi.PsiMethodCallExpression
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
abstract class AbstractMoveOutInspection : AbstractAssertJInspection() {
protected fun createInspectionsForMappings(
statement: PsiExpressionStatement,
holder: ProblemsHolder,
mappings: List<MoveOutMapping>
) {
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
val assertThatArgument = staticMethodCall.getArgOrNull(0) as? PsiMethodCallExpression ?: return
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
for (mapping in mappings.filter { it.callMatcher.test(assertThatArgument) }) {
if (mapping.expectBoolean && ASSERT_THAT_BOOLEAN.test(staticMethodCall)) {
val expectedBooleanResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: continue
if (mapping.additionalCondition?.invoke(statement, expectedCallExpression) == false) continue
val replacementMethod = if (expectedBooleanResult) mapping.replacementForTrue else mapping.replacementForFalse ?: return
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method)
}
} else if (mapping.expectNullNonNull != null) {
val expectedNullNonNullResult = expectedCallExpression.getExpectedNullNonNullResult() ?: continue
if (mapping.additionalCondition?.invoke(statement, expectedCallExpression) == false) continue
val replacementMethod = if (expectedNullNonNullResult xor mapping.expectNullNonNull) mapping.replacementForTrue else mapping.replacementForFalse ?: continue
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method, useNullNonNull = true)
}
} else if (mapping.expectedMatcher?.test(expectedCallExpression) == true) {
if (mapping.additionalCondition?.invoke(statement, expectedCallExpression) == false) continue
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, mapping.replacementForTrue) { desc, method ->
MoveOutMethodCallExpressionQuickFix(
desc, method,
replaceOnlyThisMethod = mapping.expectedMatcher,
replaceFromOriginalMethod = mapping.replaceFromOriginalMethod,
noExpectedExpression = mapping.noExpectedExpression
)
}
}
}
}
class MoveOutMapping(
val callMatcher: CallMatcher,
val replacementForTrue: String,
val replacementForFalse: String? = null,
val expectBoolean: Boolean = false,
val expectNullNonNull: Boolean? = null,
val expectedMatcher: CallMatcher? = null,
val replaceFromOriginalMethod: Boolean = false,
val noExpectedExpression: Boolean = false,
val additionalCondition: ((PsiExpressionStatement, PsiMethodCallExpression) -> Boolean)? = null
)
}
@@ -38,7 +38,13 @@ class AssertThatBinaryExpressionInspection : AbstractAssertJInspection() {
if (isLeftNull && isRightNull) return
if (isLeftNull || isRightNull) {
val replacementMethod = expectedResult.map(MethodNames.IS_NULL, MethodNames.IS_NOT_NULL)
val expectedResultOnOp =
when (binaryExpression.operationTokenType) {
JavaTokenType.EQEQ -> expectedResult
JavaTokenType.NE -> !expectedResult
else -> return
}
val replacementMethod = expectedResultOnOp.map(MethodNames.IS_NULL, MethodNames.IS_NOT_NULL)
registerSplitMethod(holder, expectedCallExpression, replacementMethod) { desc, method ->
SplitBinaryExpressionMethodCallQuickFix(desc, method, pickRightOperand = isLeftNull, noExpectedExpression = true)
}
@@ -21,18 +21,19 @@ class AssertThatBooleanConditionInspection : AbstractAssertJInspection() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
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
val isEqualToObject = IS_EQUAL_TO_OBJECT.test(expression)
val isEqualToPrimitive = IS_EQUAL_TO_BOOLEAN.test(expression)
val isNotEqualToObject = IS_NOT_EQUAL_TO_OBJECT.test(expression)
val isNotEqualToPrimitive = IS_NOT_EQUAL_TO_BOOLEAN.test(expression)
if (!(isEqualToObject || isEqualToPrimitive || isNotEqualToObject || isNotEqualToPrimitive)) return
if (!checkAssertedType(expression, ABSTRACT_BOOLEAN_ASSERT_CLASSNAME)) return
val expectedExpression = expression.firstArg
if (!TypeConversionUtil.isBooleanType(expectedExpression.type)) return
val expectedResult = expression.calculateConstantParameterValue(0) as? Boolean ?: return
val flippedBooleanTest = matchingCalls.drop(2).any { it }
val flippedBooleanTest = isNotEqualToObject || isNotEqualToPrimitive
val replacementMethod = (expectedResult xor flippedBooleanTest).map(MethodNames.IS_TRUE, MethodNames.IS_FALSE)
registerSimplifyMethod(holder, expression, replacementMethod)
@@ -1,15 +1,22 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.ui.ComboBox
import com.intellij.psi.*
import com.intellij.util.ui.FormBuilder
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
import java.awt.BorderLayout
import javax.swing.JComponent
import javax.swing.JPanel
class AssertThatCollectionOrMapExpressionInspection : AbstractAssertJInspection() {
class AssertThatCollectionOrMapExpressionInspection : AbstractMoveOutInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting a collection or map specific expression"
private const val DEFAULT_MAP_VALUES_NEVER_NULL = 2
private val MAP_GET_MATCHER = CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "get").parameterCount(1)
@@ -32,34 +39,37 @@ class AssertThatCollectionOrMapExpressionInspection : AbstractAssertJInspection(
)
private val MAPPINGS = listOf(
Mapping(
MoveOutMapping(
CallMatcher.anyOf(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "isEmpty").parameterCount(0),
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "isEmpty").parameterCount(0)
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, MethodNames.IS_EMPTY).parameterCount(0),
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, MethodNames.IS_EMPTY).parameterCount(0)
),
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY, expectBoolean = true
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "contains").parameterCount(1),
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, MethodNames.CONTAINS).parameterCount(1),
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN, expectBoolean = true
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "containsAll").parameterCount(1),
MethodNames.CONTAINS_ALL, null
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, MethodNames.CONTAINS_ALL).parameterCount(1),
MethodNames.CONTAINS_ALL, expectBoolean = true
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "containsKey").parameterCount(1),
MethodNames.CONTAINS_KEY, MethodNames.DOES_NOT_CONTAIN_KEY
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, MethodNames.CONTAINS_KEY).parameterCount(1),
MethodNames.CONTAINS_KEY, MethodNames.DOES_NOT_CONTAIN_KEY, expectBoolean = true
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "containsValue").parameterCount(1),
MethodNames.CONTAINS_VALUE, MethodNames.DOES_NOT_CONTAIN_VALUE
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, MethodNames.CONTAINS_VALUE).parameterCount(1),
MethodNames.CONTAINS_VALUE, MethodNames.DOES_NOT_CONTAIN_VALUE, expectBoolean = true
)
)
}
override fun getDisplayName() = DISPLAY_NAME
@JvmField
var behaviorForMapValueEqualsNull: Int = DEFAULT_MAP_VALUES_NEVER_NULL
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
@@ -67,44 +77,82 @@ class AssertThatCollectionOrMapExpressionInspection : AbstractAssertJInspection(
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val assertThatArgument = staticMethodCall.getArgOrNull(0) as? PsiMethodCallExpression ?: return
if (MAP_GET_MATCHER.test(assertThatArgument)) {
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val nullOrNotNull = expectedCallExpression.getAllTheSameNullNotNullConstants()
if (nullOrNotNull != null) {
val replacementMethod = nullOrNotNull.map("containsKey", "doesNotContainKey")
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
if (nullOrNotNull == true) {
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, MethodNames.CONTAINS_KEY) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method, useNullNonNull = true)
}
} else if (nullOrNotNull == false) {
when (behaviorForMapValueEqualsNull) {
1 -> // warning only
registerMoveOutMethod(
holder,
expectedCallExpression,
assertThatArgument,
""
) { _ -> emptyList() }
2 -> // as doesNotContainKey(key)
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, MethodNames.DOES_NOT_CONTAIN_KEY) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method, useNullNonNull = true)
}
3 -> // as containsEntry(key, null)
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, MethodNames.CONTAINS_ENTRY) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method, keepExpectedAsSecondArgument = true, useNullNonNull = true)
}
4 -> // both
registerMoveOutMethod(
holder,
expectedCallExpression,
assertThatArgument,
MethodNames.DOES_NOT_CONTAIN_KEY + "/" + MethodNames.CONTAINS_ENTRY
) { _ ->
listOf(
MoveOutMethodCallExpressionQuickFix(
"Remove get() of actual expression and use assertThat().doesNotContainKey() instead (regular map)",
MethodNames.DOES_NOT_CONTAIN_KEY,
useNullNonNull = true
),
MoveOutMethodCallExpressionQuickFix(
"Remove get() of actual expression and use assertThat().containsEntry(key, null) instead (degenerated map)",
MethodNames.CONTAINS_ENTRY,
keepExpectedAsSecondArgument = true,
useNullNonNull = true
)
)
}
}
} else {
if (ANY_IS_EQUAL_TO_MATCHER.test(expectedCallExpression)) {
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, "containsEntry") { desc, method ->
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, MethodNames.CONTAINS_ENTRY) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method, keepExpectedAsSecondArgument = true)
}
} else if (ANY_IS_NOT_EQUAL_TO_MATCHER.test(expectedCallExpression)) {
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, "doesNotContainEntry") { desc, method ->
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, MethodNames.DOES_NOT_CONTAIN_ENTRY) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method, keepExpectedAsSecondArgument = true)
}
}
}
} else {
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
val mapping = MAPPINGS.firstOrNull { it.callMatcher.test(assertThatArgument) } ?: return
val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
val replacementMethod = if (expectedResult) mapping.replacementForTrue else mapping.replacementForFalse ?: return
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method)
}
createInspectionsForMappings(statement, holder, MAPPINGS)
}
}
}
}
private class Mapping(
val callMatcher: CallMatcher,
val replacementForTrue: String,
val replacementForFalse: String?
)
override fun createOptionsPanel(): JComponent {
val comboBox = ComboBox(
arrayOf("ignore", "warning only, no fixes", "as doesNotContainKey(key)", "as containsEntry(key, null)", "both choices")
)
comboBox.selectedIndex = behaviorForMapValueEqualsNull
comboBox.addActionListener { behaviorForMapValueEqualsNull = comboBox.selectedIndex }
val panel = JPanel(BorderLayout())
panel.add(
FormBuilder.createFormBuilder().addLabeledComponent("Fix get() on maps expecting null values:", comboBox).panel,
BorderLayout.NORTH
)
return panel
}
}
@@ -0,0 +1,115 @@
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.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantValue
import de.platon42.intellij.plugins.cajon.firstArg
class AssertThatComparableInspection : AbstractMoveOutInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting a compareTo() expression"
private val ARG_IS_ZERO_CONST: (PsiExpressionStatement, PsiMethodCallExpression) -> Boolean = { _, call -> call.firstArg.calculateConstantValue() == 0 }
private val ARG_IS_PLUS_ONE_CONST: (PsiExpressionStatement, PsiMethodCallExpression) -> Boolean = { _, call -> call.firstArg.calculateConstantValue() == 1 }
private val ARG_IS_MINUS_ONE_CONST: (PsiExpressionStatement, PsiMethodCallExpression) -> Boolean = { _, call -> call.firstArg.calculateConstantValue() == -1 }
private val COMPARABLE_COMPARE_TO =
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_COMPARABLE, "compareTo").parameterCount(1)
private val MAPPINGS = listOf(
MoveOutMapping(
COMPARABLE_COMPARE_TO,
"isEqualByComparingTo", expectedMatcher = IS_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
"isEqualByComparingTo", expectedMatcher = IS_ZERO_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
"isNotEqualByComparingTo", expectedMatcher = IS_NOT_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
"isNotEqualByComparingTo", expectedMatcher = IS_NOT_ZERO_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_GREATER_THAN_OR_EQUAL_TO, expectedMatcher = IS_GREATER_THAN_OR_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_GREATER_THAN_OR_EQUAL_TO, expectedMatcher = CallMatcher.anyOf(IS_NOT_EQUAL_TO_INT, IS_GREATER_THAN_INT), replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_MINUS_ONE_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_GREATER_THAN_OR_EQUAL_TO, expectedMatcher = IS_NOT_NEGATIVE_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_GREATER_THAN, expectedMatcher = CallMatcher.anyOf(IS_EQUAL_TO_INT, IS_GREATER_THAN_OR_EQUAL_TO_INT), replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_PLUS_ONE_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_GREATER_THAN, expectedMatcher = IS_GREATER_THAN_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_GREATER_THAN, expectedMatcher = CallMatcher.anyOf(IS_POSITIVE_INT, IS_ONE_INT), replaceFromOriginalMethod = true
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_LESS_THAN_OR_EQUAL_TO, expectedMatcher = IS_LESS_THAN_OR_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_LESS_THAN_OR_EQUAL_TO, expectedMatcher = CallMatcher.anyOf(IS_NOT_EQUAL_TO_INT, IS_LESS_THAN_INT), replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_PLUS_ONE_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_LESS_THAN_OR_EQUAL_TO, expectedMatcher = IS_NOT_POSITIVE_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_LESS_THAN, expectedMatcher = CallMatcher.anyOf(IS_EQUAL_TO_INT, IS_LESS_THAN_OR_EQUAL_TO_INT), replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_MINUS_ONE_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_LESS_THAN, expectedMatcher = IS_LESS_THAN_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
COMPARABLE_COMPARE_TO,
MethodNames.IS_LESS_THAN, expectedMatcher = IS_NEGATIVE_INT, replaceFromOriginalMethod = true
)
)
}
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
createInspectionsForMappings(statement, holder, MAPPINGS)
}
}
}
}
@@ -5,6 +5,7 @@ import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.PsiStatement
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantParameterValue
import de.platon42.intellij.plugins.cajon.hasAssertThat
@@ -12,7 +13,7 @@ import de.platon42.intellij.plugins.cajon.hasAssertThat
class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting an empty enumerable"
private const val DISPLAY_NAME = "Asserting an empty or not empty enumerable"
}
override fun getDisplayName() = DISPLAY_NAME
@@ -23,11 +24,17 @@ class AssertThatEnumerableIsEmptyInspection : AbstractAssertJInspection() {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) return
val isLastExpression = expression.parent is PsiStatement
if (!(HAS_SIZE.test(expression) && isLastExpression)) return
val value = expression.calculateConstantParameterValue(0) ?: return
if (value == 0) {
val isEmpty = (CallMatcher.anyOf(HAS_SIZE, HAS_SIZE_LESS_THAN_OR_EQUAL_TO_INT).test(expression) && (value == 0)) ||
(HAS_SIZE_LESS_THAN_INT.test(expression) && (value == 1))
val isNotEmpty = (HAS_SIZE_GREATER_THAN_INT.test(expression) && (value == 0)) ||
(HAS_SIZE_GREATER_THAN_OR_EQUAL_TO_INT.test(expression) && (value == 1))
if (isEmpty && isLastExpression) {
registerSimplifyMethod(holder, expression, MethodNames.IS_EMPTY)
} else if (isNotEmpty) {
registerSimplifyMethod(holder, expression, MethodNames.IS_NOT_EMPTY)
}
}
}
@@ -0,0 +1,119 @@
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.*
class AssertThatFileExpressionInspection : AbstractMoveOutInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting a file specific expression"
private val ARG_IS_ZERO_CONST: (PsiExpressionStatement, PsiMethodCallExpression) -> Boolean = { _, call -> call.firstArg.calculateConstantValue() == 0 }
private val ARG_IS_NOT_ZERO_CONST: (PsiExpressionStatement, PsiMethodCallExpression) -> Boolean = { _, call ->
val constant =
call.firstArg.calculateConstantValue()
(constant != null) && (constant != 0)
}
private val MAPPINGS = listOf(
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "canRead").parameterCount(0),
"canRead", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "canWrite").parameterCount(0),
"canWrite", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "exists").parameterCount(0),
"exists", "doesNotExist", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "isAbsolute").parameterCount(0),
"isAbsolute", "isRelative", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "isDirectory").parameterCount(0),
"isDirectory", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "isFile").parameterCount(0),
"isFile", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getName").parameterCount(0),
"hasName",
expectedMatcher = CallMatcher.anyOf(IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_STRING)
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getParent", "getParentFile").parameterCount(0),
"hasNoParent", expectNullNonNull = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getParent").parameterCount(0),
"hasParent",
expectedMatcher = CallMatcher.anyOf(IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_STRING)
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "getParentFile").parameterCount(0),
"hasParent",
expectedMatcher = IS_EQUAL_TO_OBJECT
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "list", "listFiles").parameterCount(0),
"isEmptyDirectory",
expectedMatcher = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ARRAY_ASSERT_CLASSNAME, MethodNames.IS_EMPTY)
.parameterCount(0)
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "list", "listFiles").parameterCount(0),
"isNotEmptyDirectory",
expectedMatcher = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ARRAY_ASSERT_CLASSNAME, MethodNames.IS_NOT_EMPTY)
.parameterCount(0)
)
)
private val MAPPINGS_SINCE_ASSERTJ_3_14_0 = listOf(
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "length").parameterCount(0),
MethodNames.IS_EMPTY, expectedMatcher = IS_ZERO_LONG, noExpectedExpression = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "length").parameterCount(0),
MethodNames.IS_EMPTY, expectedMatcher = IS_EQUAL_TO_LONG, noExpectedExpression = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "length").parameterCount(0),
MethodNames.IS_NOT_EMPTY, expectedMatcher = IS_NOT_ZERO_LONG, noExpectedExpression = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "length").parameterCount(0),
MethodNames.IS_NOT_EMPTY, expectedMatcher = IS_NOT_EQUAL_TO_LONG, noExpectedExpression = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_IO_FILE, "length").parameterCount(0),
MethodNames.HAS_SIZE, expectedMatcher = IS_EQUAL_TO_LONG,
additionalCondition = ARG_IS_NOT_ZERO_CONST
)
)
}
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
createInspectionsForMappings(statement, holder, MAPPINGS)
if (hasAssertJMethod(statement, AssertJClassNames.ABSTRACT_FILE_ASSERT_CLASSNAME, MethodNames.HAS_SIZE)) {
createInspectionsForMappings(statement, holder, MAPPINGS_SINCE_ASSERTJ_3_14_0)
}
}
}
}
}
@@ -29,6 +29,7 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
val actualExpression = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val outmostMethodCall = statement.findOutmostMethodCall() ?: return
if (GUAVA_OPTIONAL_GET.test(actualExpression)) {
if (actualExpression.type is PsiArrayType) return
val expectedCallExpression = staticMethodCall.gatherAssertionCalls().singleOrNull() ?: return
if (CallMatcher.anyOf(IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_STRING).test(expectedCallExpression)) {
registerMoveOutMethod(holder, outmostMethodCall, actualExpression, MethodNames.CONTAINS) { desc, method ->
@@ -91,9 +92,7 @@ class AssertThatGuavaOptionalInspection : AbstractAssertJInspection() {
}
private fun checkPreconditions(staticMethodCall: PsiMethodCallExpression): Boolean {
val assertThatGuava = GUAVA_ASSERT_THAT_ANY.test(staticMethodCall)
if (ASSERT_THAT_ANY.test(staticMethodCall) || assertThatGuava) {
if (CallMatcher.anyOf(ASSERT_THAT_ANY, GUAVA_ASSERT_THAT_ANY).test(staticMethodCall)) {
JavaPsiFacade.getInstance(staticMethodCall.project)
.findClass(AssertJClassNames.GUAVA_ASSERTIONS_CLASSNAME, GlobalSearchScope.allScope(staticMethodCall.project)) ?: return false
return true
@@ -1,8 +1,13 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.util.PsiUtil
import com.intellij.psi.util.TypeConversionUtil
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.InvertUnaryExpressionQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.InvertUnaryStatementQuickFix
class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection() {
@@ -10,6 +15,8 @@ class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection()
companion object {
private const val DISPLAY_NAME = "Asserting an inverted boolean condition"
private const val INVERT_CONDITION_MESSAGE = "Condition inside assertThat() could be inverted"
private const val REMOVE_INSTANCEOF_DESCRIPTION_TEMPLATE = "Invert condition in %s() and use %s() instead"
private const val INVERT_OUTSIDE_CONDITION_MESSAGE = "Condition outside assertThat() could be inverted"
}
override fun getDisplayName() = DISPLAY_NAME
@@ -20,13 +27,27 @@ class AssertThatInvertedBooleanConditionInspection : AbstractAssertJInspection()
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) return
val staticMethodCall = expression.findStaticMethodCall() ?: return
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
expression.getExpectedBooleanResult() ?: return
if (expression.getExpectedBooleanResult() != null) {
if (!ASSERT_THAT_BOOLEAN.test(staticMethodCall)) return
val prefixExpression = staticMethodCall.firstArg as? PsiPrefixExpression ?: return
if (prefixExpression.operationTokenType == JavaTokenType.EXCL) {
val outmostMethodCall = expression.findOutmostMethodCall() ?: return
holder.registerProblem(outmostMethodCall, INVERT_CONDITION_MESSAGE, InvertUnaryStatementQuickFix())
}
} else {
if (!CallMatcher.anyOf(ASSERT_THAT_BOOLEAN, ASSERT_THAT_BOOLEAN_OBJ).test(staticMethodCall)) return
val isEqualTo = CallMatcher.anyOf(IS_EQUAL_TO_BOOLEAN, IS_EQUAL_TO_OBJECT).test(expression)
val isNotEqualTo = CallMatcher.anyOf(IS_NOT_EQUAL_TO_BOOLEAN, IS_NOT_EQUAL_TO_OBJECT).test(expression)
if (!(isEqualTo || isNotEqualTo)) return
val prefixExpression = expression.firstArg as? PsiPrefixExpression ?: return
val operand = PsiUtil.skipParenthesizedExprDown(prefixExpression.operand) ?: return
if (!TypeConversionUtil.isPrimitiveAndNotNull(operand.type)) return
val originalMethod = getOriginalMethodName(expression) ?: return
val prefixExpression = staticMethodCall.firstArg as? PsiPrefixExpression ?: return
if (prefixExpression.operationTokenType == JavaTokenType.EXCL) {
val outmostMethodCall = expression.findOutmostMethodCall() ?: return
holder.registerProblem(outmostMethodCall, INVERT_CONDITION_MESSAGE, InvertUnaryStatementQuickFix())
val replacementMethod = isEqualTo.map(MethodNames.IS_NOT_EQUAL_TO, MethodNames.IS_EQUAL_TO)
val description = REMOVE_INSTANCEOF_DESCRIPTION_TEMPLATE.format(originalMethod, replacementMethod)
val textRange = TextRange(staticMethodCall.textLength, expression.textLength)
holder.registerProblem(expression, textRange, INVERT_OUTSIDE_CONDITION_MESSAGE, InvertUnaryExpressionQuickFix(description, replacementMethod))
}
}
}
@@ -0,0 +1,81 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiMethodCallExpression
import com.intellij.psi.util.TypeConversionUtil
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
class AssertThatIsZeroOneInspection : AbstractAssertJInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting a zero or one value"
}
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
super.visitMethodCallExpression(expression)
if (!expression.hasAssertThat()) return
val isEqualTo = CallMatcher.anyOf(IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_SHORT, IS_EQUAL_TO_INT, IS_EQUAL_TO_LONG, IS_EQUAL_TO_FLOAT, IS_EQUAL_TO_DOUBLE).test(expression)
val isNotEqualTo =
CallMatcher.anyOf(IS_NOT_EQUAL_TO_OBJECT, IS_NOT_EQUAL_TO_SHORT, IS_NOT_EQUAL_TO_INT, IS_NOT_EQUAL_TO_LONG, IS_NOT_EQUAL_TO_FLOAT, IS_NOT_EQUAL_TO_DOUBLE)
.test(expression)
if (!(isEqualTo || isNotEqualTo)) return
val expectedExpression = expression.firstArg
if (!TypeConversionUtil.isNumericType(expectedExpression.type)) return
val expectedResult = expression.calculateConstantParameterValue(0) ?: return
var isZero = false
var isOne = false
when (expectedResult) {
is Short -> {
isZero = (expectedResult == 0.toShort())
isOne = (expectedResult == 1.toShort())
}
is Int -> {
isZero = (expectedResult == 0)
isOne = (expectedResult == 1)
}
is Long -> {
isZero = (expectedResult == 0L)
isOne = (expectedResult == 1L)
}
is Float -> {
isZero = (expectedResult == 0.0f)
isOne = (expectedResult == 1.0f)
}
is Double -> {
isZero = (expectedResult == 0.0)
isOne = (expectedResult == 1.0)
}
}
if (isZero || isOne) {
val numericBaseClass = listOf(
AssertJClassNames.ABSTRACT_SHORT_ASSERT_CLASSNAME,
AssertJClassNames.ABSTRACT_INTEGER_ASSERT_CLASSNAME,
AssertJClassNames.ABSTRACT_LONG_ASSERT_CLASSNAME,
AssertJClassNames.ABSTRACT_FLOAT_ASSERT_CLASSNAME,
AssertJClassNames.ABSTRACT_DOUBLE_ASSERT_CLASSNAME
).any { checkAssertedType(expression, it) }
if (!numericBaseClass) return
}
if (isZero) {
registerSimplifyMethod(holder, expression, isEqualTo.map(MethodNames.IS_ZERO, MethodNames.IS_NOT_ZERO))
} else if (isOne && isEqualTo) {
registerSimplifyMethod(holder, expression, MethodNames.IS_ONE)
}
}
}
}
}
@@ -5,10 +5,8 @@ import com.intellij.psi.*
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.HasHashCodeQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.MoveOutMethodCallExpressionQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.RemoveActualOutmostMethodCallQuickFix
class AssertThatObjectExpressionInspection : AbstractAssertJInspection() {
class AssertThatObjectExpressionInspection : AbstractMoveOutInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting equals(), toString(), or hashCode()"
@@ -16,6 +14,17 @@ class AssertThatObjectExpressionInspection : AbstractAssertJInspection() {
private val OBJECT_TO_STRING = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_OBJECT, "toString").parameterCount(0)
private val OBJECT_HASHCODE = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_OBJECT, "hashCode").parameterCount(0)
private val MAPPINGS = listOf(
MoveOutMapping(
OBJECT_EQUALS,
MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO, expectBoolean = true
),
MoveOutMapping(
OBJECT_TO_STRING,
MethodNames.HAS_TO_STRING, expectedMatcher = CallMatcher.anyOf(IS_EQUAL_TO_OBJECT, IS_EQUAL_TO_STRING)
)
)
}
override fun getDisplayName() = DISPLAY_NAME
@@ -25,31 +34,18 @@ class AssertThatObjectExpressionInspection : AbstractAssertJInspection() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) return
val staticMethodCall = statement.findStaticMethodCall() ?: return
val assertThatArgument = staticMethodCall.firstArg as? PsiMethodCallExpression ?: return
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
when {
OBJECT_EQUALS.test(assertThatArgument) -> {
val expectedResult = expectedCallExpression.getAllTheSameExpectedBooleanConstants() ?: return
val replacementMethod = expectedResult.map(MethodNames.IS_EQUAL_TO, MethodNames.IS_NOT_EQUAL_TO)
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method)
}
}
OBJECT_TO_STRING.test(assertThatArgument) -> {
staticMethodCall.findFluentCallTo(IS_EQUAL_TO_OBJECT) ?: staticMethodCall.findFluentCallTo(IS_EQUAL_TO_STRING) ?: return
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, MethodNames.HAS_TO_STRING) { desc, method ->
RemoveActualOutmostMethodCallQuickFix(desc, method)
}
}
OBJECT_HASHCODE.test(assertThatArgument) -> {
val isEqualTo = staticMethodCall.findFluentCallTo(IS_EQUAL_TO_INT) ?: return
val expectedExpression = isEqualTo.firstArg as? PsiMethodCallExpression ?: return
if (OBJECT_HASHCODE.test(expectedExpression)) {
holder.registerProblem(expectedCallExpression, HASHCODE_MESSAGE_TEMPLATE, HasHashCodeQuickFix())
}
val staticMethodCall = statement.findStaticMethodCall() ?: return
val assertThatArgument = staticMethodCall.getArgOrNull(0) as? PsiMethodCallExpression ?: return
if (OBJECT_HASHCODE.test(assertThatArgument)) {
val expectedCallExpression = statement.findOutmostMethodCall() ?: return
val isEqualTo = staticMethodCall.findFluentCallTo(IS_EQUAL_TO_INT) ?: return
val expectedExpression = isEqualTo.firstArg as? PsiMethodCallExpression ?: return
if (OBJECT_HASHCODE.test(expectedExpression)) {
holder.registerProblem(expectedCallExpression, HASHCODE_MESSAGE_TEMPLATE, HasHashCodeQuickFix())
}
} else {
createInspectionsForMappings(statement, holder, MAPPINGS)
}
}
}
@@ -0,0 +1,52 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.JavaElementVisitor
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiExpressionStatement
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.MethodNames
class AssertThatPathExpressionInspection : AbstractMoveOutInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting a path specific expression"
private const val JAVA_NIO_PATH = "java.nio.file.Path"
private val MAPPINGS = listOf(
MoveOutMapping(
CallMatcher.instanceCall(JAVA_NIO_PATH, "isAbsolute").parameterCount(0),
"isAbsolute", "isRelative", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(JAVA_NIO_PATH, MethodNames.STARTS_WITH).parameterTypes(JAVA_NIO_PATH),
"startsWithRaw", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(JAVA_NIO_PATH, MethodNames.ENDS_WITH).parameterTypes(JAVA_NIO_PATH),
"endsWithRaw", expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(JAVA_NIO_PATH, "getParent").parameterCount(0),
"hasParentRaw",
expectedMatcher = IS_EQUAL_TO_OBJECT
),
MoveOutMapping(
CallMatcher.instanceCall(JAVA_NIO_PATH, "getParent").parameterCount(0),
"hasNoParentRaw", expectNullNonNull = true
)
)
}
override fun getDisplayName() = DISPLAY_NAME
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitExpressionStatement(statement)
createInspectionsForMappings(statement, holder, MAPPINGS)
}
}
}
}
@@ -5,6 +5,7 @@ import com.intellij.psi.*
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_ITERABLE_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.ABSTRACT_MAP_ASSERT_CLASSNAME
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceHasSizeMethodCallQuickFix
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceSizeMethodCallQuickFix
@@ -34,7 +35,7 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
&& ((psiReferenceExpression.resolve() as? PsiField)?.name == "length"))
}
fun getMatch(expression: PsiMethodCallExpression, isForArrayCollectionOrMap: Boolean, isForString: Boolean): Match? {
fun getMatch(expression: PsiMethodCallExpression, isForArrayOrCollection: Boolean, isForMap: Boolean, isForString: Boolean): Match? {
val isLastExpression = expression.parent is PsiStatement
val constValue = expression.calculateConstantParameterValue(0)
if (IS_EQUAL_TO_INT.test(expression)) {
@@ -42,10 +43,11 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
Match(expression, MethodNames.IS_EMPTY, noExpectedExpression = true)
} else {
val equalToExpression = expression.firstArg
val equalsArrayCollectionOrMapSize = isArrayLength(equalToExpression) ||
isCollectionSize(equalToExpression) || isMapSize(equalToExpression)
if (isForArrayCollectionOrMap && equalsArrayCollectionOrMapSize ||
isForString && (equalsArrayCollectionOrMapSize || isCharSequenceLength(equalToExpression))
val equalsArrayOrCollectionSize = isArrayLength(equalToExpression) ||
isCollectionSize(equalToExpression)
if ((isForArrayOrCollection && equalsArrayOrCollectionSize)
|| (isForMap && (equalsArrayOrCollectionSize || isMapSize(equalToExpression)))
|| (isForString && (equalsArrayOrCollectionSize || isCharSequenceLength(equalToExpression)))
) {
Match(expression, MethodNames.HAS_SAME_SIZE_AS, expectedIsCollection = true)
} else {
@@ -55,10 +57,10 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
} 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))
|| IS_ZERO_INT.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))
|| IS_NOT_ZERO_INT.test(expression))
if ((isTestForEmpty && isLastExpression) || isTestForNotEmpty) {
val replacementMethod = isTestForEmpty.map(MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY)
return Match(expression, replacementMethod, noExpectedExpression = true)
@@ -83,12 +85,13 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
if (!ASSERT_THAT_INT.test(staticMethodCall)) return
val actualExpression = staticMethodCall.firstArg
val isForArrayCollectionOrMap = isArrayLength(actualExpression) || isCollectionSize(actualExpression) || isMapSize(actualExpression)
val isForArrayOrCollection = isArrayLength(actualExpression) || isCollectionSize(actualExpression)
val isForMap = isMapSize(actualExpression)
val isForString = isCharSequenceLength(actualExpression)
if (!(isForArrayCollectionOrMap || isForString)) return
if (!(isForArrayOrCollection || isForMap || isForString)) return
val matches = staticMethodCall.collectMethodCallsUpToStatement()
.mapNotNull { getMatch(it, isForArrayCollectionOrMap, isForString) }
.mapNotNull { getMatch(it, isForArrayOrCollection, isForMap, isForString) }
.toList()
if (matches.isNotEmpty()) {
if (matches.size == 1) {
@@ -116,9 +119,11 @@ class AssertThatSizeInspection : AbstractAssertJInspection() {
if (!HAS_SIZE.test(expression)) return
val actualExpression = expression.firstArg
val isForArrayCollectionOrMap = isArrayLength(actualExpression) || isCollectionSize(actualExpression) || isMapSize(actualExpression)
val isForArrayOrCollection = isArrayLength(actualExpression) || isCollectionSize(actualExpression)
val isForMap = isMapSize(actualExpression)
val isForString = isCharSequenceLength(actualExpression)
if (!(isForArrayCollectionOrMap
if (!(isForArrayOrCollection
|| (isForMap && checkAssertedType(expression, ABSTRACT_MAP_ASSERT_CLASSNAME))
|| (isForString && checkAssertedType(expression, ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME)))
) return
@@ -3,41 +3,138 @@ 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
import de.platon42.intellij.plugins.cajon.MethodNames
import de.platon42.intellij.plugins.cajon.calculateConstantValue
import de.platon42.intellij.plugins.cajon.firstArg
class AssertThatStringExpressionInspection : AbstractAssertJInspection() {
class AssertThatStringExpressionInspection : AbstractMoveOutInspection() {
companion object {
private const val DISPLAY_NAME = "Asserting a string specific expression"
private val ARG_IS_ZERO_CONST: (PsiExpressionStatement, PsiMethodCallExpression) -> Boolean = { _, call -> call.firstArg.calculateConstantValue() == 0 }
private val ARG_IS_MINUS_ONE_CONST: (PsiExpressionStatement, PsiMethodCallExpression) -> Boolean = { _, call -> call.firstArg.calculateConstantValue() == -1 }
private val STRING_COMPARE_TO_IGNORE_CASE =
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "compareToIgnoreCase").parameterTypes(CommonClassNames.JAVA_LANG_STRING)
private val STRING_INDEX_OF = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "indexOf").parameterTypes(CommonClassNames.JAVA_LANG_STRING)
private val STRING_TRIM = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "trim").parameterCount(0)
private val MAPPINGS = listOf(
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "isEmpty").parameterCount(0),
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, MethodNames.IS_EMPTY).parameterCount(0),
MethodNames.IS_EMPTY, MethodNames.IS_NOT_EMPTY, expectBoolean = true
),
Mapping(
MoveOutMapping(
CallMatcher.anyOf(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "equals").parameterCount(1),
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, MethodNames.EQUALS).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, expectBoolean = true
),
Mapping(
MoveOutMapping(
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, expectBoolean = true
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "contains").parameterCount(1),
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, MethodNames.CONTAINS).parameterCount(1),
MethodNames.CONTAINS, MethodNames.DOES_NOT_CONTAIN, expectBoolean = true
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "startsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
MethodNames.STARTS_WITH, MethodNames.DOES_NOT_START_WITH
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, MethodNames.STARTS_WITH).parameterTypes(CommonClassNames.JAVA_LANG_STRING),
MethodNames.STARTS_WITH, MethodNames.DOES_NOT_START_WITH, expectBoolean = true
),
Mapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "endsWith").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
MethodNames.ENDS_WITH, MethodNames.DOES_NOT_END_WITH
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, MethodNames.ENDS_WITH).parameterTypes(CommonClassNames.JAVA_LANG_STRING),
MethodNames.ENDS_WITH, MethodNames.DOES_NOT_END_WITH, expectBoolean = true
),
MoveOutMapping(
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "matches").parameterTypes(CommonClassNames.JAVA_LANG_STRING),
"matches", "doesNotMatch", expectBoolean = true
),
MoveOutMapping(
STRING_COMPARE_TO_IGNORE_CASE,
MethodNames.IS_EQUAL_TO_IC, expectedMatcher = IS_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
STRING_COMPARE_TO_IGNORE_CASE,
MethodNames.IS_EQUAL_TO_IC, expectedMatcher = IS_ZERO_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
STRING_COMPARE_TO_IGNORE_CASE,
MethodNames.IS_NOT_EQUAL_TO_IC, expectedMatcher = IS_NOT_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
STRING_COMPARE_TO_IGNORE_CASE,
MethodNames.IS_NOT_EQUAL_TO_IC, expectedMatcher = IS_NOT_ZERO_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.STARTS_WITH, expectedMatcher = IS_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.STARTS_WITH, expectedMatcher = IS_ZERO_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.DOES_NOT_START_WITH, expectedMatcher = IS_NOT_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.DOES_NOT_START_WITH, expectedMatcher = IS_NOT_ZERO_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.CONTAINS, expectedMatcher = IS_NOT_NEGATIVE_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.CONTAINS, expectedMatcher = IS_NOT_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_MINUS_ONE_CONST
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.CONTAINS, expectedMatcher = IS_GREATER_THAN_OR_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.CONTAINS, expectedMatcher = IS_GREATER_THAN_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_MINUS_ONE_CONST
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.DOES_NOT_CONTAIN, expectedMatcher = IS_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_MINUS_ONE_CONST
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.DOES_NOT_CONTAIN, expectedMatcher = IS_NEGATIVE_INT, replaceFromOriginalMethod = true
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.DOES_NOT_CONTAIN, expectedMatcher = IS_LESS_THAN_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_ZERO_CONST
),
MoveOutMapping(
STRING_INDEX_OF,
MethodNames.DOES_NOT_CONTAIN, expectedMatcher = IS_LESS_THAN_OR_EQUAL_TO_INT, replaceFromOriginalMethod = true,
additionalCondition = ARG_IS_MINUS_ONE_CONST
),
MoveOutMapping(
STRING_TRIM,
"isNotBlank", expectedMatcher = IS_NOT_EMPTY
)
)
}
@@ -48,27 +145,8 @@ class AssertThatStringExpressionInspection : AbstractAssertJInspection() {
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
registerMoveOutMethod(holder, expectedCallExpression, assertThatArgument, replacementMethod) { desc, method ->
MoveOutMethodCallExpressionQuickFix(desc, method)
}
createInspectionsForMappings(statement, holder, MAPPINGS)
}
}
}
private class Mapping(
val callMatcher: CallMatcher,
val replacementForTrue: String,
val replacementForFalse: String
)
}
@@ -0,0 +1,177 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import com.siyeh.ig.callMatcher.CallMatcher
import com.siyeh.ig.psiutils.EquivalenceChecker
import de.platon42.intellij.plugins.cajon.*
class BogusAssertionInspection : AbstractAssertJInspection() {
companion object {
private const val DISPLAY_NAME = "Bogus assertion due to same actual and expected expressions"
private const val ACTUAL_IS_EQUAL_TO_EXPECTED_MESSAGE = "Actual expression in assertThat() is the same as expected"
private const val WEAK_ACTUAL_IS_EQUAL_TO_EXPECTED_MESSAGE = "Same actual and expected expression, but may be testing equals() or hashCode()"
private val SAME_OBJECT =
CallMatcher.instanceCall(
AssertJClassNames.ASSERT_INTERFACE,
MethodNames.IS_EQUAL_TO,
MethodNames.IS_SAME_AS,
"hasSameClassAs",
"hasSameHashCodeAs"
).parameterCount(1)
private val ARRAY_METHODS = arrayOf(
MethodNames.HAS_SAME_SIZE_AS,
MethodNames.CONTAINS,
"containsAnyOf",
MethodNames.CONTAINS_EXACTLY,
"containsExactlyInAnyOrder",
"containsOnly",
"containsSequence",
"containsSubsequence",
MethodNames.STARTS_WITH,
MethodNames.ENDS_WITH
)
private val SAME_BOOLEAN_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_BOOLEAN_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_BYTE_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_BYTE_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_SHORT_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_SHORT_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_INT_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_INT_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_LONG_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_LONG_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_FLOAT_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_FLOAT_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_DOUBLE_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_DOUBLE_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_CHAR_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_CHAR_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val SAME_OBJECT_ARRAY_CONTENTS =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_OBJECT_ARRAY_ASSERT_CLASSNAME, *ARRAY_METHODS).parameterCount(1)
private val HASHCODE_OR_IS_EQUAL_TO =
CallMatcher.instanceCall(
AssertJClassNames.ASSERT_INTERFACE,
MethodNames.IS_EQUAL_TO, "hasSameHashCodeAs"
).parameterCount(1)
private val SAME_ENUMERABLE_CONTENTS =
CallMatcher.instanceCall(
AssertJClassNames.ENUMERABLE_ASSERT_INTERFACE,
MethodNames.HAS_SAME_SIZE_AS
).parameterCount(1)
private val SAME_ITERABLE_CONTENTS =
CallMatcher.instanceCall(
AssertJClassNames.ABSTRACT_ITERABLE_ASSERT_CLASSNAME,
"hasSameElementsAs",
MethodNames.CONTAINS_ALL,
"containsAnyElementsOf",
"containsOnlyElementsOf",
"containsExactlyElementsOf",
"containsSequence",
"containsSubsequence"
).parameterCount(1)
private val SAME_MAP_CONTENTS =
CallMatcher.instanceCall(
AssertJClassNames.ABSTRACT_MAP_ASSERT_CLASSNAME,
"containsAllEntriesOf",
"containsExactlyEntriesOf",
"containsExactlyInAnyOrderEntriesOf",
MethodNames.HAS_SAME_SIZE_AS
).parameterCount(1)
private val SAME_CHAR_SEQUENCE_CONTENTS =
CallMatcher.instanceCall(
AssertJClassNames.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME,
MethodNames.IS_EQUAL_TO,
MethodNames.IS_EQUAL_TO_IC,
MethodNames.STARTS_WITH,
MethodNames.ENDS_WITH,
"containsSequence",
"containsSubsequence"
).parameterCount(1)
private val SAME_ACTUAL_AND_EXPECTED_MATCHERS = CallMatcher.anyOf(
SAME_OBJECT,
SAME_ENUMERABLE_CONTENTS,
SAME_ITERABLE_CONTENTS,
SAME_MAP_CONTENTS,
SAME_CHAR_SEQUENCE_CONTENTS,
SAME_BOOLEAN_ARRAY_CONTENTS,
SAME_BYTE_ARRAY_CONTENTS,
SAME_SHORT_ARRAY_CONTENTS,
SAME_INT_ARRAY_CONTENTS,
SAME_LONG_ARRAY_CONTENTS,
SAME_FLOAT_ARRAY_CONTENTS,
SAME_DOUBLE_ARRAY_CONTENTS,
SAME_CHAR_ARRAY_CONTENTS,
SAME_OBJECT_ARRAY_CONTENTS
)
}
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 assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) } ?: return
val actualExpression = assertThatCall.firstArg
val allCalls = assertThatCall.collectMethodCallsUpToStatement().toList()
// Note: replace with TrackingEquivalenceChecker() for IDEA >= 2019.1
val equivalenceChecker = EquivalenceChecker.getCanonicalPsiEquivalence()!!
val isSameExpression = allCalls
.filter { it.argumentList.expressions.size == 1 }
.filter(SAME_ACTUAL_AND_EXPECTED_MATCHERS::test)
.any { equivalenceChecker.expressionsAreEquivalent(actualExpression, it.firstArg) }
if (isSameExpression) {
if (!hasExpressionWithSideEffects(actualExpression)) {
if (allCalls.any(HASHCODE_OR_IS_EQUAL_TO::test)) {
val method = PsiTreeUtil.getParentOfType(statement, PsiMethod::class.java, true)
val methodName = method?.name
if ((methodName != null)
&& ((methodName.contains("equal", ignoreCase = true) || methodName.contains("hashcode", ignoreCase = true)))
) {
if (isOnTheFly) {
holder.registerProblem(statement, WEAK_ACTUAL_IS_EQUAL_TO_EXPECTED_MESSAGE, ProblemHighlightType.INFORMATION)
}
return
}
}
holder.registerProblem(statement, ACTUAL_IS_EQUAL_TO_EXPECTED_MESSAGE)
}
}
}
private fun hasExpressionWithSideEffects(actualExpression: PsiExpression): Boolean {
var result = false
PsiTreeUtil.processElements(actualExpression) { element ->
val matched = when (element) {
is PsiUnaryExpression -> (element.operationTokenType == JavaTokenType.PLUSPLUS)
|| (element.operationTokenType == JavaTokenType.MINUSMINUS)
is PsiMethodCallExpression -> true
else -> false
}
if (matched) {
result = true
false
} else {
true
}
}
return result
}
}
}
}
@@ -30,27 +30,26 @@ class ImplicitAssertionInspection : AbstractAssertJInspection() {
private val OBJECT_ENUMERABLE_ANY_CONTENT_ASSERTIONS = CallMatcher.instanceCall(
AssertJClassNames.OBJECT_ENUMERABLE_ASSERT_INTERFACE,
MethodNames.CONTAINS, "containsOnly", "containsOnlyNulls", MethodNames.CONTAINS_ONLY_ONCE,
"containsExactly", "containsExactlyInAnyOrder", "containsExactlyInAnyOrderElementsOf",
"containsAll", "containsAnyOf",
MethodNames.CONTAINS_EXACTLY, "containsExactlyInAnyOrder", "containsExactlyInAnyOrderElementsOf",
MethodNames.CONTAINS_ALL, "containsAnyOf",
"containsAnyElementsOf", "containsExactlyElementsOf", "containsOnlyElementsOf",
"isSubsetOf", "containsSequence", "containsSubsequence",
"doesNotContainSequence", "doesNotContainSubsequence", "doesNotContain",
"doesNotContainSequence", "doesNotContainSubsequence", MethodNames.DOES_NOT_CONTAIN,
"doesNotContainAnyElementsOf", "doesNotHaveDuplicates",
"startsWith", "endsWith", "containsNull", "doesNotContainNull",
MethodNames.STARTS_WITH, MethodNames.ENDS_WITH, "containsNull", "doesNotContainNull",
"are", "areNot", "have", "doNotHave", "areAtLeastOne", "areAtLeast", "areAtMost", "areExactly",
"haveAtLeastOne", "haveAtLeast", "haveAtMost", "haveExactly",
"doesNotHave", "doesNotHaveSameClassAs",
"hasAtLeastOneElementOfType", "hasOnlyElementsOfType", "hasOnlyElementsOfTypes",
"doesNotHaveAnyElementsOfTypes",
"has", "doesNotHave",
"hasOnlyOneElementSatisfying", "hasSameElementsAs",
"singleElement", "hasOnlyOneElementSatisfying", "hasSameElementsAs",
"allMatch", "allSatisfy", "anyMatch", "anySatisfy", "noneMatch", "noneSatisfy"
)!!
private val OBJECT_ENUMERABLE_AT_LEAST_ONE_CONTENT_ASSERTIONS = CallMatcher.instanceCall(
AssertJClassNames.OBJECT_ENUMERABLE_ASSERT_INTERFACE,
"containsOnlyNulls",
"startsWith", "endsWith", "containsNull",
MethodNames.STARTS_WITH, MethodNames.ENDS_WITH, "containsNull",
"areAtLeastOne",
"haveAtLeastOne",
"hasAtLeastOneElementOfType",
@@ -73,10 +72,10 @@ class ImplicitAssertionInspection : AbstractAssertJInspection() {
private val NON_NULL_CORE_ASSERTIONS = CallMatcher.instanceCall(
AssertJClassNames.ASSERT_INTERFACE,
"isInstanceOf", "isInstanceOfSatisfying", "isInstanceOfAny", "isExactlyInstanceOf", "isOfAnyClassIn",
"isNotInstanceOf", "isNotInstanceOfAny", "isNotExactlyInstanceOf", "isNotOfAnyClassIn",
MethodNames.IS_INSTANCE_OF, "isInstanceOfSatisfying", "isInstanceOfAny", "isExactlyInstanceOf", "isOfAnyClassIn",
MethodNames.IS_NOT_INSTANCE_OF, "isNotInstanceOfAny", "isNotExactlyInstanceOf", "isNotOfAnyClassIn",
"hasSameClassAs", "doesNotHaveSameClassAs",
"hasToString", "hasSameHashCodeAs"
MethodNames.HAS_TO_STRING, "hasSameHashCodeAs"
)!!
private val GUAVA_IS_PRESENT = CallMatcher.instanceCall(AssertJClassNames.GUAVA_OPTIONAL_ASSERTIONS_CLASSNAME, MethodNames.IS_PRESENT)
@@ -72,7 +72,7 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
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 }
return assertThatCall?.takeIf { it.findFluentCallTo(COMPLEX_STUFF_THAT_MAKES_JOINING_IMPOSSIBLE) == null }
}
return null
}
@@ -83,6 +83,7 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
val matched = when (element) {
is PsiUnaryExpression -> (element.operationTokenType == JavaTokenType.PLUSPLUS)
|| (element.operationTokenType == JavaTokenType.MINUSMINUS)
is PsiMethodCallExpression -> KNOWN_METHODS_WITH_SIDE_EFFECTS.test(element)
else -> false
}
@@ -26,7 +26,7 @@ class JoinVarArgsContainsInspection : AbstractAssertJInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
super.visitStatement(statement)
super.visitExpressionStatement(statement)
if (!statement.hasAssertThat()) return
val assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) } ?: return
@@ -35,7 +35,7 @@ class JoinVarArgsContainsInspection : AbstractAssertJInspection() {
if (allCalls.find(COMPLEX_CALLS_THAT_MAKES_STUFF_TRICKY::test) != null) return
val onlyAssertionCalls = allCalls
.filterNot { NOT_ACTUAL_ASSERTIONS.test(it) }
.filterNot(NOT_ACTUAL_ASSERTIONS::test)
.toList()
for (methodMatcher in MATCHERS) {
@@ -0,0 +1,108 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
import de.platon42.intellij.plugins.cajon.quickfixes.SwapActualAndExpectedExpressionMethodCallQuickFix
class TwistedAssertionInspection : AbstractAssertJInspection() {
companion object {
private const val DISPLAY_NAME = "Twisted or suspicious actual and expected expressions"
private const val TWISTED_ACTUAL_AND_EXPECTED_MESSAGE = "Twisted actual and expected expressions in assertion"
private const val SWAP_ACTUAL_AND_EXPECTED_DESCRIPTION = "Swap actual and expected expressions in assertion"
private const val SWAP_ACTUAL_AND_EXPECTED_AND_REPLACE_DESCRIPTION_TEMPLATE = "Replace %s() by %s() and swap actual and expected expressions"
private const val ACTUAL_IS_A_CONSTANT_MESSAGE = "Actual expression in assertThat() is a constant"
private val GENERIC_IS_EQUAL_TO = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, MethodNames.IS_EQUAL_TO).parameterCount(1)
private val GENERIC_IS_NOT_EQUAL_TO = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, MethodNames.IS_NOT_EQUAL_TO).parameterCount(1)
private val GENERIC_IS_SAME_AS = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, MethodNames.IS_SAME_AS).parameterCount(1)
private val GENERIC_IS_NOT_SAME_AS = CallMatcher.instanceCall(AssertJClassNames.ASSERT_INTERFACE, MethodNames.IS_NOT_SAME_AS).parameterCount(1)
private val GENERIC_IS_GREATER_THAN = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_GREATER_THAN).parameterCount(1)
private val GENERIC_IS_GREATER_THAN_OR_EQUAL_TO =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_GREATER_THAN_OR_EQUAL_TO).parameterCount(1)
private val GENERIC_IS_LESS_THAN = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_LESS_THAN).parameterCount(1)
private val GENERIC_IS_LESS_THAN_OR_EQUAL_TO =
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_COMPARABLE_ASSERT_CLASSNAME, MethodNames.IS_LESS_THAN_OR_EQUAL_TO).parameterCount(1)
private val STRING_IS_EQUAL_TO_IC = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME, MethodNames.IS_EQUAL_TO_IC).parameterCount(1)
private val STRING_REGEX_MATCHING = CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME, "matches", "doesNotMatch").parameterCount(1)
private val CALL_MATCHER_TO_REPLACEMENT_MAP = mapOf(
GENERIC_IS_EQUAL_TO to MethodNames.IS_EQUAL_TO,
GENERIC_IS_NOT_EQUAL_TO to MethodNames.IS_NOT_EQUAL_TO,
GENERIC_IS_SAME_AS to MethodNames.IS_SAME_AS,
GENERIC_IS_NOT_SAME_AS to MethodNames.IS_NOT_SAME_AS,
GENERIC_IS_GREATER_THAN to MethodNames.IS_LESS_THAN_OR_EQUAL_TO,
GENERIC_IS_GREATER_THAN_OR_EQUAL_TO to MethodNames.IS_LESS_THAN,
GENERIC_IS_LESS_THAN to MethodNames.IS_GREATER_THAN_OR_EQUAL_TO,
GENERIC_IS_LESS_THAN_OR_EQUAL_TO to MethodNames.IS_GREATER_THAN,
STRING_IS_EQUAL_TO_IC to MethodNames.IS_EQUAL_TO_IC,
CallMatcher.instanceCall(AssertJClassNames.ABSTRACT_CHAR_SEQUENCE_ASSERT_CLASSNAME, MethodNames.IS_NOT_EQUAL_TO_IC).parameterCount(1)
to MethodNames.IS_NOT_EQUAL_TO_IC
)
}
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 assertThatCall = PsiTreeUtil.findChildrenOfType(statement, PsiMethodCallExpression::class.java).find { ALL_ASSERT_THAT_MATCHERS.test(it) } ?: return
val actualExpression = assertThatCall.firstArg
actualExpression.calculateConstantValue() ?: return
val allCalls = assertThatCall.collectMethodCallsUpToStatement().toList()
val tooComplex = allCalls.find(USING_COMPARATOR::test) != null
var severity = ProblemHighlightType.GENERIC_ERROR_OR_WARNING
if (actualExpression.type is PsiClassType) {
val psiManager = PsiManager.getInstance(statement.project)
val javaLangClass = PsiType.getJavaLangClass(psiManager, GlobalSearchScope.allScope(statement.project))
if (actualExpression.type!!.isAssignableFrom(javaLangClass)) {
return
}
}
if (!tooComplex) {
val onlyAssertionCalls = allCalls
.filterNot(NOT_ACTUAL_ASSERTIONS::test)
.toList()
if (onlyAssertionCalls.size == 1) {
val expectedMethodCall = onlyAssertionCalls.first()
if (STRING_REGEX_MATCHING.test(expectedMethodCall)) {
return
}
if (expectedMethodCall.getArgOrNull(0)?.calculateConstantValue() == null) {
val matchedMethod = CALL_MATCHER_TO_REPLACEMENT_MAP.asSequence().firstOrNull { it.key.test(expectedMethodCall) }
if (matchedMethod != null) {
val originalMethodName = getOriginalMethodName(expectedMethodCall)
val replacementMethod = matchedMethod.value
val description = if (originalMethodName == replacementMethod) {
SWAP_ACTUAL_AND_EXPECTED_DESCRIPTION
} else {
SWAP_ACTUAL_AND_EXPECTED_AND_REPLACE_DESCRIPTION_TEMPLATE.format(originalMethodName, replacementMethod)
}
holder.registerProblem(
statement,
TWISTED_ACTUAL_AND_EXPECTED_MESSAGE,
SwapActualAndExpectedExpressionMethodCallQuickFix(description, replacementMethod)
)
return
}
} else {
severity = ProblemHighlightType.WEAK_WARNING
}
}
}
holder.registerProblem(statement, ACTUAL_IS_A_CONSTANT_MESSAGE, severity)
}
}
}
}
@@ -0,0 +1,31 @@
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.firstArg
import de.platon42.intellij.plugins.cajon.replaceQualifierFromMethodCall
class InvertUnaryExpressionQuickFix(description: String, private val replacementMethod: String) : AbstractCommonQuickFix(description) {
companion object {
private const val INVERT_CONDITION_DESCRIPTION = "Invert condition in isEqualTo()/isNotEqualTo() expressions"
}
override fun getFamilyName(): String {
return INVERT_CONDITION_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val methodCall = descriptor.startElement as? PsiMethodCallExpression ?: return
val assertExpression = methodCall.firstArg as? PsiUnaryExpression ?: return
val operand = PsiUtil.skipParenthesizedExprDown(assertExpression.operand) ?: return
val expectedExpression = createExpectedMethodCall(assertExpression, replacementMethod, operand)
expectedExpression.replaceQualifierFromMethodCall(methodCall)
methodCall.replace(expectedExpression)
}
}
@@ -56,9 +56,14 @@ class JoinStatementsQuickFix(private val separateLineLimit: Int) : AbstractCommo
}
private fun addLineBreak(project: Project, lastElementBeforeConcat: PsiElement) {
val newLineNode =
val newLineNode = try {
PsiParserFacade.getInstance(project).createWhiteSpaceFromText("\n\t")
} catch (ex: NoSuchMethodError) {
// scheduled for removal, but alternate version not even available in 2020.3.
// So keep it here until we run into a problem.
// Changing the min version from 2017.3 to 2021.x is a major thing.
PsiParserFacade.SERVICE.getInstance(project).createWhiteSpaceFromText("\n\t")
}
lastElementBeforeConcat.addAfter(newLineNode, lastElementBeforeConcat.firstChild)
}
@@ -2,7 +2,10 @@ 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.PsiExpression
import com.intellij.psi.PsiMethodCallExpression
import com.siyeh.ig.callMatcher.CallMatcher
import de.platon42.intellij.plugins.cajon.*
class MoveOutMethodCallExpressionQuickFix(
@@ -10,7 +13,9 @@ class MoveOutMethodCallExpressionQuickFix(
private val replacementMethod: String,
private val useNullNonNull: Boolean = false,
private val noExpectedExpression: Boolean = false,
private val keepExpectedAsSecondArgument: Boolean = false
private val keepExpectedAsSecondArgument: Boolean = false,
private val replaceOnlyThisMethod: CallMatcher? = null,
private val replaceFromOriginalMethod: Boolean = false
) :
AbstractCommonQuickFix(description) {
@@ -26,30 +31,52 @@ class MoveOutMethodCallExpressionQuickFix(
val outmostCallExpression = descriptor.startElement as? PsiMethodCallExpression ?: return
val assertThatMethodCall = outmostCallExpression.findStaticMethodCall() ?: return
val assertExpression = assertThatMethodCall.firstArg as? PsiMethodCallExpression ?: return
val assertExpressionArg = if (noExpectedExpression) null else assertExpression.getArgOrNull(0)?.copy()
val assertExpressionArg = if (noExpectedExpression) null else assertExpression.getArgOrNull(0)?.copy() as PsiExpression?
if (keepExpectedAsSecondArgument) {
assertExpressionArg ?: return
val secondArg = outmostCallExpression.getArgOrNull(0)?.copy() ?: return
when {
replaceOnlyThisMethod != null -> {
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
.filter(replaceOnlyThisMethod::test)
.toList()
assertExpression.replace(assertExpression.qualifierExpression)
assertExpression.replace(assertExpression.qualifierExpression)
val expectedExpression = createExpectedMethodCall(outmostCallExpression, replacementMethod, assertExpressionArg, secondArg)
expectedExpression.replaceQualifierFromMethodCall(outmostCallExpression)
outmostCallExpression.replace(expectedExpression)
} else {
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
.filter { (if (useNullNonNull) it.getExpectedNullNonNullResult() else it.getExpectedBooleanResult()) != null }
.toList()
methodsToFix
.forEach {
val expectedExpression = createExpectedMethodCall(
it,
replacementMethod,
*if (replaceFromOriginalMethod || noExpectedExpression) listOfNotNull(assertExpressionArg).toTypedArray() else it.argumentList.expressions
)
expectedExpression.replaceQualifierFromMethodCall(it)
it.replace(expectedExpression)
}
}
keepExpectedAsSecondArgument -> {
assertExpressionArg ?: return
val secondArg =
if (useNullNonNull) JavaPsiFacade.getElementFactory(project).createExpressionFromText("null", null) else outmostCallExpression.getArgOrNull(0)?.copy() ?: return
assertExpression.replace(assertExpression.qualifierExpression)
assertExpression.replace(assertExpression.qualifierExpression)
methodsToFix
.forEach {
val expectedExpression = createExpectedMethodCall(it, replacementMethod, *listOfNotNull(assertExpressionArg).toTypedArray())
expectedExpression.replaceQualifierFromMethodCall(it)
it.replace(expectedExpression)
}
val expectedExpression = createExpectedMethodCall(outmostCallExpression, replacementMethod, assertExpressionArg, secondArg)
expectedExpression.replaceQualifierFromMethodCall(outmostCallExpression)
outmostCallExpression.replace(expectedExpression)
}
else -> {
val methodsToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
.filter { (if (useNullNonNull) it.getExpectedNullNonNullResult() else it.getExpectedBooleanResult()) != null }
.toList()
assertExpression.replace(assertExpression.qualifierExpression)
methodsToFix
.forEach {
val expectedExpression = createExpectedMethodCall(it, replacementMethod, *listOfNotNull(assertExpressionArg).toTypedArray())
expectedExpression.replaceQualifierFromMethodCall(it)
it.replace(expectedExpression)
}
}
}
}
}
@@ -0,0 +1,34 @@
package de.platon42.intellij.plugins.cajon.quickfixes
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import de.platon42.intellij.plugins.cajon.*
class SwapActualAndExpectedExpressionMethodCallQuickFix(
description: String,
private val replacementMethod: String
) : AbstractCommonQuickFix(description) {
companion object {
private const val SPLIT_EXPRESSION_DESCRIPTION = "Swap actual and expected expressions of assertions"
}
override fun getFamilyName(): String {
return SPLIT_EXPRESSION_DESCRIPTION
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val assertThatMethodCall = descriptor.startElement.findStaticMethodCall() ?: return
val methodToFix = assertThatMethodCall.collectMethodCallsUpToStatement()
.filterNot(NOT_ACTUAL_ASSERTIONS::test)
.first()
val oldActualExpression = assertThatMethodCall.firstArg.copy()!!
assertThatMethodCall.firstArg.replace(methodToFix.firstArg)
val expectedExpression = createExpectedMethodCall(methodToFix, replacementMethod, oldActualExpression)
expectedExpression.replaceQualifierFromMethodCall(methodToFix)
methodToFix.replace(expectedExpression)
}
}
@@ -1,6 +1,5 @@
package de.platon42.intellij.plugins.cajon.references
import com.intellij.lang.jvm.JvmModifier
import com.intellij.openapi.util.TextRange
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.*
@@ -30,7 +29,7 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
val matchedGetter = PropertyUtilBase.findPropertyGetter(containingClass, partName, false, true)
val fieldResult = PropertyUtilBase.findPropertyField(containingClass, partName, false)
val textRange = TextRange(startOffset + 1, nextOffset)
val matchedBareMethod = containingClass.allMethods.find { (it.name == partName) && !it.hasModifier(JvmModifier.STATIC) }
val matchedBareMethod = containingClass.allMethods.find { (it.name == partName) && !it.hasModifierProperty(PsiModifier.STATIC) }
val targets = listOfNotNull<PsiElement>(fieldResult, matchedGetter, matchedBareMethod)
if (targets.isNotEmpty()) {
val results = listOf(textRange to targets)
@@ -44,7 +43,7 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
}
private fun lookupMethod(containingClass: PsiClass, methodName: String): List<Pair<TextRange, List<PsiElement>>>? {
val matchedMethod = containingClass.allMethods.find { (it.name == methodName) && !it.hasModifier(JvmModifier.STATIC) } ?: return null
val matchedMethod = containingClass.allMethods.find { (it.name == methodName) && !it.hasModifierProperty(PsiModifier.STATIC) } ?: return null
val textRange = TextRange(1, methodName.length + 1)
return listOf(textRange to listOf(matchedMethod))
}
@@ -71,7 +70,7 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
class ExtractorReference(literal: PsiLiteralExpression, range: TextRange, private val targets: List<PsiElement>) :
PsiPolyVariantReferenceBase<PsiLiteralExpression>(literal, range, true) {
// Do not remove due to compatiblity issue with IDEA <= 2018.2
// Do not remove due to compatibility issue with IDEA <= 2018.2
override fun getVariants(): Array<Any> {
return ArrayUtil.EMPTY_OBJECT_ARRAY
}
@@ -125,6 +124,7 @@ class ExtractorReferenceContributor : PsiReferenceContributor() {
if (!CallMatcher.anyOf(EXTRACTING_FROM_ITERABLE, FLAT_EXTRACTING_FROM_ITERABLE).test(methodCallExpression)) return null
val iterableType = findActualType(methodCallExpression) ?: return null
if (iterableType.parameters.isEmpty()) return null
val innerType = iterableType.resolveGenerics().substitutor.substitute(iterableType.parameters[0])
val containingClass = PsiTypesUtil.getPsiClass(innerType) ?: return null
return if (isResultOf) lookupMethod(containingClass, literal) else lookupFieldOrProperty(containingClass, literal, 0)
+17 -3
View File
@@ -5,10 +5,11 @@
<description><![CDATA[
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
It adds several <b>inspections and quick fixes</b> 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 and assumptions to AssertJ.
It supports referencing inside extracting()-methods with strings, adding refactoring safety.
It can also be used to <b>convert JUnit 4 assertions and assumptions to AssertJ</b>.
It supports <b>referencing inside extracting</b>()-methods with strings, adding refactoring safety.
<b>Bogus or twisted assertions</b> are also reported.
<p>
<a href="https://github.com/chrisly42/cajon-plugin/blob/master/README.md">Full documentation here...</a>
]]></description>
@@ -27,6 +28,8 @@
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBooleanConditionInspection"/>
<localInspection groupPath="Java" shortName="AssertThatInvertedBooleanCondition" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatInvertedBooleanConditionInspection"/>
<localInspection groupPath="Java" shortName="AssertThatIsZeroOne" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatIsZeroOneInspection"/>
<localInspection groupPath="Java" shortName="AssertThatInstanceOf" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatInstanceOfInspection"/>
<localInspection groupPath="Java" shortName="AssertThatStringIsEmpty" enabledByDefault="true" level="WARNING"
@@ -41,10 +44,16 @@
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatBinaryExpressionInspection"/>
<localInspection groupPath="Java" shortName="AssertThatObjectExpression" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatObjectExpressionInspection"/>
<localInspection groupPath="Java" shortName="AssertThatComparable" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatComparableInspection"/>
<localInspection groupPath="Java" shortName="AssertThatStringExpression" enabledByDefault="true" level="WARNING"
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="AssertThatFileExpression" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatFileExpressionInspection"/>
<localInspection groupPath="Java" shortName="AssertThatPathExpression" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatPathExpressionInspection"/>
<localInspection groupPath="Java" shortName="JoinAssertThatStatements" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.JoinAssertThatStatementsInspection"/>
@@ -61,6 +70,11 @@
<localInspection groupPath="Java" shortName="ImplicitAssertion" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.ImplicitAssertionInspection"/>
<localInspection groupPath="Java" shortName="TwistedAssertion" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.TwistedAssertionInspection"/>
<localInspection groupPath="Java" shortName="BogusAssertion" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.BogusAssertionInspection"/>
<localInspection groupPath="Java" shortName="JUnitAssertToAssertJ" enabledByDefault="true" level="WARNING"
implementationClass="de.platon42.intellij.plugins.cajon.inspections.JUnitAssertToAssertJInspection"/>
</extensions>
@@ -6,5 +6,13 @@ assertThat(map.get(key)).isEqualTo/isNotEqualTo(value) into assertThat(map).cont
<br>someMethod() can be isEmpty(), contains(), and containsAll() for collections and
isEmpty(), containsKey(), and containsValue() for maps.
get() may be transformed into containsKey(), doesNotContainKey(), containsEntry() or doesNotContainEntry().
<br>
If you are using degenerated maps in your project that may contain null values (i.e.
map.contains(key) == true AND map.get(key) == null
is valid for some entries in your map), the default behavior of the quickfix
assertThat(map.get(key)).isNull() turning into assertThat(map).doesNotContainKey(key)
is not an equivalent transformation. The settings below can change this behavior to instead transform it into
assertThat(map).containsEntry(key, null) for those cases, create both quickfix choices or simply ignore this
case altogether (if in doubt).
</body>
</html>
@@ -0,0 +1,5 @@
<html>
<body>
Turns assertThat(obj1.compareTo(obj2)) into assertThat(obj1).someMethod(obj2).
</body>
</html>
@@ -1,6 +1,6 @@
<html>
<body>
Turns assertThat(enumerable).hasSize(0) into assertThat(enumerable).isEmpty().
Turns assertThat(enumerable).hasSize(0) and similar into assertThat(enumerable).isEmpty() or .isNotEmpty().
<!-- tooltip end -->
<br>Works with anything that is enumerable such as arrays, iterables, collections, etc.
</body>
@@ -0,0 +1,8 @@
<html>
<body>
Operates on assertions on objects of type File. Turns assertThat(file.someMethod(arg)).someAssertion() into assertThat(file).someMethod(arg).
<!-- tooltip end -->
<br>someMethod() can be canRead(), canWrite(), exists(), isAbsolute(), isDirectory(), isFile(),
getName(), getParent(), getParentFile(), list() and listFiles().
</body>
</html>
@@ -1,6 +1,6 @@
<html>
<body>
Turns assertThat(!condition).isEqualTo(true/false) into assertThat(condition).isFalse()/isTrue().
Turns assertThat(!condition).isEqualTo(true/false) into assertThat(condition).isFalse()/isTrue() and negates .is(Not)EqualTo(!var).
<!-- tooltip end -->
<br>Also works with constant expressions and Boolean.TRUE/FALSE.
</body>
@@ -0,0 +1,8 @@
<html>
<body>
Turns assertThat(numeric).isEqualTo(0/1) into assertThat(numeric).isZero()/isOne()
or assertThat(numeric).isNotEqualTo(0) into assertThat(numeric).isNotZero().
<!-- tooltip end -->
<br>Also works with constant expressions.
</body>
</html>
@@ -0,0 +1,7 @@
<html>
<body>
Operates on assertions on objects of type Path. Turns assertThat(file.someMethod(arg)).someAssertion() into assertThat(path).someMethod(arg).
<!-- tooltip end -->
<br>someMethod() can be isAbsolute(), getParent(), startsWith() and endsWith().
</body>
</html>
@@ -2,6 +2,7 @@
<body>
Turns assertThat(string.someMethod(arg)).isTrue/isFalse() into assertThat(string).someMethod(arg).
<!-- tooltip end -->
<br>someMethod() can be isEmpty(), equals(), equalsIgnoreCase(), contentEquals(), contains(), startsWith(), and endsWith().
<br>someMethod() can be isEmpty(), equals(), equalsIgnoreCase(), contentEquals(), contains(), startsWith(), endsWith(),
matches(), compareToIgnoreCase(), indexOf(), and trim().
</body>
</html>
@@ -0,0 +1,6 @@
<html>
<body>
Finds typical copy and paste errors where the assertion will never fail, such as assertThat(foo).isEqualTo(foo), because actual
and expected expressions are the same.
</body>
</html>
@@ -0,0 +1,7 @@
<html>
<body>
Finds assertion method calls that have the expected and actual expressions twisted, such as assertThat(5).isEqualTo(foo).
<!-- tooltip end -->
For some obvious cases, a quickfix to swap the actual and expected expressions is provided.
</body>
</html>
@@ -6,5 +6,5 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface AddLocalJarToModule {
Class[] value();
Class<?>[] value();
}
@@ -0,0 +1,24 @@
package de.platon42.intellij.jupiter;
import com.intellij.openapi.roots.DependencyScope;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Repeatable(AddMavenDependencyToModule.List.class)
public @interface AddMavenDependencyToModule {
String value();
boolean includeTransitiveDependencies = false;
DependencyScope scope = DependencyScope.COMPILE;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface List {
AddMavenDependencyToModule[] value();
}
}
@@ -1,18 +1,30 @@
package de.platon42.intellij.jupiter;
import com.intellij.jarRepository.JarRepositoryManager;
import com.intellij.jarRepository.RemoteRepositoryDescription;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.DependencyScope;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.ui.OrderRoot;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.*;
import com.intellij.testFramework.EdtTestUtilKt;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.TestLoggerFactory;
import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy;
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryProperties;
import org.junit.jupiter.api.extension.*;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
@@ -23,7 +35,11 @@ import java.lang.reflect.Parameter;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class LightCodeInsightExtension implements ParameterResolver, AfterTestExecutionCallback, InvocationInterceptor {
@@ -121,15 +137,19 @@ public class LightCodeInsightExtension implements ParameterResolver, AfterTestEx
@Override
public void setUp() throws Exception {
super.setUp();
Store store = getStore(extensionContext);
store.put("disposable", Disposer.newDisposable("LightCodeInsightFixtureTestCaseWrapper"));
}
@Override
public void tearDown() throws Exception {
super.tearDown();
UsefulTestCase.clearFields(this);
if (myFixture != null && getProject() != null && !getProject().isDisposed()) {
Disposer.dispose(getProject());
Store store = getStore(extensionContext);
Disposable disposable = (Disposable) store.get("disposable");
if (myFixture != null && disposable != null) {
Disposer.dispose(disposable);
store.remove("disposable");
}
super.tearDown();
}
@NotNull
@@ -150,15 +170,17 @@ public class LightCodeInsightExtension implements ParameterResolver, AfterTestEx
@Override
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
super.configureModule(module, model, contentEntry);
AddLocalJarToModule methodOrClassAnnotation = getMethodOrClassAnnotation(AddLocalJarToModule.class);
if (methodOrClassAnnotation != null) {
Stream.of(methodOrClassAnnotation.value()).forEach(it -> addJarContaining(model, it));
AddLocalJarToModule localJars = getMethodOrClassAnnotation(AddLocalJarToModule.class);
if (localJars != null) {
Stream.of(localJars.value()).forEach(it -> addJarContaining(model, it));
}
List<AddMavenDependencyToModule> mavenDependencies = getMethodOrClassAnnotations(AddMavenDependencyToModule.class);
mavenDependencies.forEach(it -> addFromMaven(model, it.value(), it.includeTransitiveDependencies, it.scope));
}
};
}
void addJarContaining(ModifiableRootModel model, Class clazz) {
void addJarContaining(ModifiableRootModel model, Class<?> clazz) {
try {
Path jarPath = Paths.get(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());
@@ -175,6 +197,33 @@ public class LightCodeInsightExtension implements ParameterResolver, AfterTestEx
}
}
void addFromMaven(ModifiableRootModel model, String mavenCoordinates,
boolean includeTransitiveDependencies, DependencyScope dependencyScope) {
List<RemoteRepositoryDescription> remoteRepositoryDescriptions = RemoteRepositoryDescription.DEFAULT_REPOSITORIES;
RepositoryLibraryProperties libraryProperties = new RepositoryLibraryProperties(mavenCoordinates, includeTransitiveDependencies);
Collection<OrderRoot> roots =
JarRepositoryManager.loadDependenciesModal(model.getProject(), libraryProperties, false, false, null, remoteRepositoryDescriptions);
LibraryTable.ModifiableModel tableModel = model.getModuleLibraryTable().getModifiableModel();
Library library = tableModel.createLibrary(mavenCoordinates);
Library.ModifiableModel libraryModel = library.getModifiableModel();
if (roots.isEmpty()) {
throw new IllegalStateException(String.format("No roots for '%s'", mavenCoordinates));
}
for (OrderRoot root : roots) {
libraryModel.addRoot(root.getFile(), root.getType());
}
LibraryOrderEntry libraryOrderEntry = model.findLibraryOrderEntry(library);
if (libraryOrderEntry == null) {
throw new IllegalStateException("Unable to find registered library " + mavenCoordinates);
}
libraryOrderEntry.setScope(dependencyScope);
libraryModel.commit();
tableModel.commit();
}
@Override
protected String getTestDataPath() {
TestDataPath testDataPath = getMethodOrClassAnnotation(TestDataPath.class);
@@ -199,5 +248,12 @@ public class LightCodeInsightExtension implements ParameterResolver, AfterTestEx
}
return annotation;
}
private <T extends Annotation> List<T> getMethodOrClassAnnotations(Class<T> clazz) {
return Stream.of(extensionContext.getRequiredTestMethod().getAnnotationsByType(clazz),
extensionContext.getRequiredTestClass().getAnnotationsByType(clazz))
.flatMap(Arrays::stream)
.collect(Collectors.toList());
}
}
}
@@ -1,13 +1,14 @@
package de.platon42.intellij.plugins.cajon
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.pom.java.LanguageLevel
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import de.platon42.intellij.jupiter.AddLocalJarToModule
import de.platon42.intellij.jupiter.AddMavenDependencyToModule
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestJdk
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Condition
import org.junit.jupiter.api.DisplayNameGeneration
import org.junit.jupiter.api.DisplayNameGenerator
import org.junit.jupiter.api.extension.ExtendWith
@@ -16,15 +17,31 @@ import java.lang.reflect.Method
@ExtendWith(LightCodeInsightExtension::class)
@TestDataPath("src/test/resources")
@TestJdk(LanguageLevel.JDK_1_8, annotations = true, useInternal = true)
@AddLocalJarToModule(Assertions::class)
//@AddLocalJarToModule(Assertions::class)
@AddMavenDependencyToModule("org.assertj:assertj-core:3.15.0")
@DisplayNameGeneration(AbstractCajonTest.CutOffFixtureDisplayNameGenerator::class)
abstract class AbstractCajonTest {
protected fun executeQuickFixes(myFixture: JavaCodeInsightTestFixture, regex: Regex, expectedFixes: Int) {
val quickfixes = getQuickFixes(myFixture, regex, expectedFixes)
assertThat(quickfixes.groupBy { it.familyName }).hasSize(1)
quickfixes.forEach(myFixture::launchAction)
}
protected fun executeQuickFixesNoFamilyNameCheck(myFixture: JavaCodeInsightTestFixture, regex: Regex, expectedFixes: Int) {
val quickfixes = getQuickFixes(myFixture, regex, expectedFixes)
quickfixes.forEach(myFixture::launchAction)
}
protected fun getQuickFixes(myFixture: JavaCodeInsightTestFixture, regex: Regex, expectedFixes: Int): List<IntentionAction> {
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)
return quickfixes
}
protected fun assertHighlightings(myFixture: JavaCodeInsightTestFixture, count: Int, snippet: String) {
assertThat(myFixture.doHighlighting())
.areExactly(count, Condition({ it.description?.contains(snippet) ?: false }, "containing"))
}
class CutOffFixtureDisplayNameGenerator : DisplayNameGenerator.ReplaceUnderscores() {
@@ -13,7 +13,7 @@ internal class AssertThatBinaryExpressionInspectionTest : AbstractCajonTest() {
internal fun assertThat_of_binary_expression_can_be_moved_out(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatBinaryExpressionInspection::class.java)
myFixture.configureByFile("BinaryExpressionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Split binary expression out of assertThat()"), 149)
executeQuickFixes(myFixture, Regex.fromLiteral("Split binary expression out of assertThat()"), 161)
myFixture.checkResultByFile("BinaryExpressionAfter.java")
}
}
@@ -4,12 +4,13 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.cajon.AbstractCajonTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
@TestDataSubPath("inspections/CollectionMapExpression")
internal class AssertThatCollectionOrMapExpressionInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/CollectionMapExpression")
internal fun assertThat_with_certain_Collection_and_Map_methods(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatCollectionOrMapExpressionInspection::class.java)
myFixture.configureByFile("CollectionMapExpressionBefore.java")
@@ -28,4 +29,76 @@ internal class AssertThatCollectionOrMapExpressionInspectionTest : AbstractCajon
executeQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainKey() instead"), 4)
myFixture.checkResultByFile("CollectionMapExpressionAfter.java")
}
@Test
internal fun assertThat_with_certain_Collection_and_Map_methods_with_Null_values(@MyFixture myFixture: JavaCodeInsightTestFixture) {
val inspection = AssertThatCollectionOrMapExpressionInspection()
inspection.behaviorForMapValueEqualsNull = 3
myFixture.enableInspections(inspection)
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)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsEntry() instead"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainEntry() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsKey() instead"), 4)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainKey() instead"), 0)
myFixture.checkResultByFile("CollectionMapExpressionWithNullValuesAfter.java")
}
@Test
internal fun assertThat_with_certain_Collection_and_Map_methods_with_no_quickfixes_for_get_equals_null(@MyFixture myFixture: JavaCodeInsightTestFixture) {
val inspection = AssertThatCollectionOrMapExpressionInspection()
inspection.behaviorForMapValueEqualsNull = 0
myFixture.enableInspections(inspection)
myFixture.configureByFile("CollectionMapExpressionBefore.java")
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsEntry() instead"), 2)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainEntry() instead"), 2)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsKey() instead"), 4)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainKey() instead"), 0)
}
@Test
internal fun assertThat_with_certain_Collection_and_Map_methods_with_only_warnings_for_get_equals_null(@MyFixture myFixture: JavaCodeInsightTestFixture) {
val inspection = AssertThatCollectionOrMapExpressionInspection()
inspection.behaviorForMapValueEqualsNull = 1
myFixture.enableInspections(inspection)
myFixture.configureByFile("CollectionMapExpressionBefore.java")
val highlights = myFixture.doHighlighting()
.asSequence()
.filter { it.description == "Moving get() expression out of assertThat() would be more concise" }
.filter {
it.quickFixActionRanges?.any { innerit -> innerit.first.action.text.contains("Inspection 'Asserting a collection or map specific expression") } ?: true
}
.toList()
assertThat(highlights).hasSize(4)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsEntry() instead"), 2)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainEntry() instead"), 2)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsKey() instead"), 4)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainKey() instead"), 0)
}
@Test
internal fun assertThat_with_certain_Collection_and_Map_methods_with_both_quickfixes_for_get_equals_null(@MyFixture myFixture: JavaCodeInsightTestFixture) {
val inspection = AssertThatCollectionOrMapExpressionInspection()
inspection.behaviorForMapValueEqualsNull = 4
myFixture.enableInspections(inspection)
myFixture.configureByFile("CollectionMapExpressionBefore.java")
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsEntry() instead"), 2)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainKey() instead (regular map)"), 4)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsEntry(key, null) instead (degenerated map)"), 4)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainEntry() instead"), 2)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().containsKey() instead"), 4)
getQuickFixes(myFixture, Regex.fromLiteral("Remove get() of actual expression and use assertThat().doesNotContainKey() instead"), 0)
}
}
@@ -0,0 +1,24 @@
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 AssertThatComparableInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/Comparable")
internal fun assertThat_with_compareTo_method(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatComparableInspection::class.java)
myFixture.configureByFile("ComparableBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareTo() of actual expression and use assertThat().isEqualByComparingTo() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareTo() of actual expression and use assertThat().isNotEqualByComparingTo() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareTo() of actual expression and use assertThat().isGreaterThanOrEqualTo() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareTo() of actual expression and use assertThat().isGreaterThan() instead"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareTo() of actual expression and use assertThat().isLessThanOrEqualTo() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareTo() of actual expression and use assertThat().isLessThan() instead"), 4)
myFixture.checkResultByFile("ComparableAfter.java")
}
}
@@ -10,10 +10,14 @@ internal class AssertThatEnumerableIsEmptyInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/EnumerableIsEmpty")
internal fun assertThat_with_hasSize_zero_can_use_isEmpty(@MyFixture myFixture: JavaCodeInsightTestFixture) {
internal fun assertThat_with_hasSize_zero_and_similar_can_use_isEmpty(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatEnumerableIsEmptyInspection::class.java)
myFixture.configureByFile("EnumerableIsEmptyBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSize() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeLessThan() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeLessThanOrEqualTo() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeGreaterThan() with isNotEmpty()"), 6)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace hasSizeGreaterThanOrEqualTo() with isNotEmpty()"), 6)
myFixture.checkResultByFile("EnumerableIsEmptyAfter.java")
}
}
@@ -0,0 +1,38 @@
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 AssertThatFileExpressionInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/FileExpression")
internal fun assertThat_with_certain_File_methods(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatFileExpressionInspection::class.java)
myFixture.configureByFile("FileExpressionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Remove canRead() of actual expression and use assertThat().canRead() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove canWrite() of actual expression and use assertThat().canWrite() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove exists() of actual expression and use assertThat().exists() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove exists() of actual expression and use assertThat().doesNotExist() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isAbsolute() of actual expression and use assertThat().isAbsolute() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isAbsolute() of actual expression and use assertThat().isRelative() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isDirectory() of actual expression and use assertThat().isDirectory() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isFile() of actual expression and use assertThat().isFile() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove getName() of actual expression and use assertThat().hasName() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove getParent() of actual expression and use assertThat().hasNoParent() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove getParentFile() of actual expression and use assertThat().hasNoParent() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove getParent() of actual expression and use assertThat().hasParent() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove getParentFile() of actual expression and use assertThat().hasParent() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove listFiles() of actual expression and use assertThat().isEmptyDirectory() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove listFiles() of actual expression and use assertThat().isNotEmptyDirectory() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove list() of actual expression and use assertThat().isEmptyDirectory() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove list() of actual expression and use assertThat().isNotEmptyDirectory() instead"), 1)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove length() of actual expression and use assertThat().isEmpty() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove length() of actual expression and use assertThat().isNotEmpty() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove length() of actual expression and use assertThat().hasSize() instead"), 1)
myFixture.checkResultByFile("FileExpressionAfter.java")
}
}
@@ -31,8 +31,8 @@ internal class AssertThatGuavaOptionalInspectionTest : AbstractCajonTest() {
internal fun adds_missing_Guava_import_any_order(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java)
myFixture.configureByFile("WithoutPriorGuavaImportBefore.java")
executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 4)
executeQuickFixes(myFixture, Regex("Remove .*"), 3)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex(".*eplace .* with .*"), 4)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Remove .*"), 3)
myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java")
}
@@ -41,8 +41,8 @@ internal class AssertThatGuavaOptionalInspectionTest : AbstractCajonTest() {
myFixture.enableInspections(AssertThatGuavaOptionalInspection::class.java)
myFixture.configureByFile("WithoutPriorGuavaImportBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with Guava assertThat().isAbsent()"), 1)
executeQuickFixes(myFixture, Regex(".*eplace .* with .*"), 3)
executeQuickFixes(myFixture, Regex("Remove .*"), 3)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex(".*eplace .* with .*"), 3)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Remove .*"), 3)
myFixture.checkResultByFile("WithoutPriorGuavaImportAfter.java")
}
}
@@ -14,6 +14,8 @@ internal class AssertThatInvertedBooleanConditionInspectionTest : AbstractCajonT
myFixture.enableInspections(AssertThatInvertedBooleanConditionInspection::class.java)
myFixture.configureByFile("InvertedBooleanConditionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Invert condition in assertThat()"), 25)
executeQuickFixes(myFixture, Regex.fromLiteral("Invert condition in isEqualTo() and use isNotEqualTo() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Invert condition in isNotEqualTo() and use isEqualTo() instead"), 2)
myFixture.checkResultByFile("InvertedBooleanConditionAfter.java")
}
}
@@ -0,0 +1,21 @@
package de.platon42.intellij.plugins.cajon.inspections
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.cajon.AbstractCajonTest
import org.junit.jupiter.api.Test
internal class AssertThatIsZeroOneInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/IsZeroOne")
internal fun assertThat_with_isEqualTo_zero_or_one_can_use_isZero_or_isOne_plus_isNotZero(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatIsZeroOneInspection::class.java)
myFixture.configureByFile("IsZeroOneBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isZero()"), 10)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isOne()"), 10)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isNotEqualTo() with isNotZero()"), 10)
myFixture.checkResultByFile("IsZeroOneAfter.java")
}
}
@@ -0,0 +1,24 @@
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 AssertThatPathExpressionInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/PathExpression")
internal fun assertThat_with_certain_Path_methods(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatPathExpressionInspection::class.java)
myFixture.configureByFile("PathExpressionBefore.java")
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isAbsolute() of actual expression and use assertThat().isAbsolute() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isAbsolute() of actual expression and use assertThat().isRelative() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove startsWith() of actual expression and use assertThat().startsWithRaw() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove endsWith() of actual expression and use assertThat().endsWithRaw() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove getParent() of actual expression and use assertThat().hasNoParentRaw() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove getParent() of actual expression and use assertThat().hasParentRaw() instead"), 1)
myFixture.checkResultByFile("PathExpressionAfter.java")
}
}
@@ -4,8 +4,6 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.cajon.AbstractCajonTest
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.extrakting
import org.junit.jupiter.api.Test
internal class AssertThatSizeInspectionTest : AbstractCajonTest() {
@@ -15,7 +13,7 @@ internal class AssertThatSizeInspectionTest : AbstractCajonTest() {
internal fun assertThat_size_of_array_collection_or_map_can_be_simplified(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(AssertThatSizeInspection::class.java)
myFixture.configureByFile("SizeBefore.java")
assertThat(myFixture.doHighlighting()).extrakting { it.description }.containsOnlyOnce("Try to operate on the iterable itself rather than its size")
assertHighlightings(myFixture, 1, "Try to operate on the iterable itself rather than its size")
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isZero() with isEmpty()"), 5)
@@ -24,13 +22,13 @@ internal class AssertThatSizeInspectionTest : AbstractCajonTest() {
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isGreaterThanOrEqualTo() with isNotEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThan() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThanOrEqualTo() with isEmpty()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with hasSameSizeAs()"), 19)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with hasSize()"), 11)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with hasSameSizeAs()"), 15)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isEqualTo() with hasSize()"), 15)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isGreaterThan() with hasSizeGreaterThan()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isGreaterThanOrEqualTo() with hasSizeGreaterThanOrEqualTo()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThan() with hasSizeLessThan()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Replace isLessThanOrEqualTo() with hasSizeLessThanOrEqualTo()"), 5)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove size determination of expected expression and replace hasSize() with hasSameSizeAs()"), 21)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove size determination of expected expression and replace hasSize() with hasSameSizeAs()"), 17)
myFixture.checkResultByFile("SizeAfter.java")
}
}
@@ -20,6 +20,8 @@ internal class AssertThatStringExpressionInspectionTest : AbstractCajonTest() {
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().contains() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove startsWith() of actual expression and use assertThat().startsWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove endsWith() of actual expression and use assertThat().endsWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove matches() of actual expression and use assertThat().matches() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove matches() of actual expression and use assertThat().doesNotMatch() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove isEmpty() of actual expression and use assertThat().isNotEmpty() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove equals() of actual expression and use assertThat().isNotEqualTo() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove equalsIgnoreCase() of actual expression and use assertThat().isNotEqualToIgnoringCase() instead"), 2)
@@ -27,6 +29,13 @@ internal class AssertThatStringExpressionInspectionTest : AbstractCajonTest() {
executeQuickFixes(myFixture, Regex.fromLiteral("Remove contains() of actual expression and use assertThat().doesNotContain() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove startsWith() of actual expression and use assertThat().doesNotStartWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove endsWith() of actual expression and use assertThat().doesNotEndWith() instead"), 3)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareToIgnoreCase() of actual expression and use assertThat().isEqualToIgnoringCase() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove compareToIgnoreCase() of actual expression and use assertThat().isNotEqualToIgnoringCase() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove indexOf() of actual expression and use assertThat().startsWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove indexOf() of actual expression and use assertThat().doesNotStartWith() instead"), 2)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove indexOf() of actual expression and use assertThat().contains() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove indexOf() of actual expression and use assertThat().doesNotContain() instead"), 4)
executeQuickFixes(myFixture, Regex.fromLiteral("Remove trim() of actual expression and use assertThat().isNotBlank() instead"), 1)
myFixture.checkResultByFile("StringExpressionAfter.java")
}
}
@@ -0,0 +1,19 @@
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 BogusAssertionInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/BogusAssertion")
internal fun reports_bogus_assertions(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(BogusAssertionInspection::class.java)
myFixture.configureByFile("BogusAssertionBefore.java")
assertHighlightings(myFixture, 14 * 9 + 10 + 12 + 8, "Actual expression in assertThat() is the same as expected")
assertHighlightings(myFixture, 3, "Same actual and expected expression, but may be testing equals() or hashCode()")
}
}
@@ -16,9 +16,9 @@ internal class ImplicitAssertionInspectionTest : AbstractCajonTest() {
internal fun implicit_assertions_can_be_removed(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(ImplicitAssertionInspection::class.java)
myFixture.configureByFile("ImplicitAssertionBefore.java")
executeQuickFixes(myFixture, Regex("Delete implicit isNotNull\\(\\) covered by .*"), 101)
executeQuickFixes(myFixture, Regex("Delete implicit isNotEmpty\\(\\) covered by .*"), 17)
executeQuickFixes(myFixture, Regex("Delete implicit isPresent\\(\\) covered by .*"), 8)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Delete implicit isNotNull\\(\\) covered by .*"), 102)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Delete implicit isNotEmpty\\(\\) covered by .*"), 17)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Delete implicit isPresent\\(\\) covered by .*"), 8)
myFixture.checkResultByFile("ImplicitAssertionAfter.java")
}
}
@@ -17,8 +17,8 @@ internal class JUnitAssertToAssertJInspectionTest : AbstractCajonTest() {
internal fun junit_Assertions_can_be_converted_into_AssertJ(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(JUnitAssertToAssertJInspection::class.java)
myFixture.configureByFile("JUnitAssertToAssertJInspectionBefore.java")
executeQuickFixes(myFixture, Regex("Convert assert.*\\(\\) to assertThat\\(\\).*"), 48)
executeQuickFixes(myFixture, Regex("Convert assume.*\\(\\) to assumeThat\\(\\).*"), 7)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Convert assert.*\\(\\) to assertThat\\(\\).*"), 48)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Convert assume.*\\(\\) to assumeThat\\(\\).*"), 7)
myFixture.checkResultByFile("JUnitAssertToAssertJInspectionAfter.java")
}
}
@@ -0,0 +1,23 @@
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 TwistedAssertionInspectionTest : AbstractCajonTest() {
@Test
@TestDataSubPath("inspections/TwistedAssertion")
internal fun hint_twisted_actual_and_expected_and_provide_quickfix_where_possible(@MyFixture myFixture: JavaCodeInsightTestFixture) {
myFixture.enableInspections(TwistedAssertionInspection::class.java)
myFixture.configureByFile("TwistedAssertionBefore.java")
assertHighlightings(myFixture, 9, "Actual expression in assertThat() is a constant")
assertHighlightings(myFixture, 10, "Twisted actual and expected expressions")
executeQuickFixes(myFixture, Regex.fromLiteral("Swap actual and expected expressions in assertion"), 6)
executeQuickFixesNoFamilyNameCheck(myFixture, Regex("Replace .* by .* and swap actual and expected expressions"), 4)
myFixture.checkResultByFile("TwistedAssertionAfter.java")
}
}
@@ -189,6 +189,20 @@ public class BinaryExpression {
assertThat(stringAct).isNotNull();
assertThat(stringAct).isNotNull();
assertThat(stringAct).as("doh!").isNotNull();
assertThat(stringAct).isNotNull();
assertThat(stringAct).isNotNull();
assertThat(stringAct).isNull();
assertThat(stringAct).isNull();
assertThat(stringAct).isNull();
assertThat(stringAct).as("doh!").isNotNull();
assertThat(stringAct).isNotNull();
assertThat(stringAct).isNotNull();
assertThat(stringAct).isNull();
assertThat(stringAct).isNull();
assertThat(stringAct).isNull();
assertThat(null == null).isTrue();
assertThat(!false).isTrue();
@@ -189,6 +189,20 @@ public class BinaryExpression {
assertThat(null == stringAct).isEqualTo(false);
assertThat(null == stringAct).isNotEqualTo(true);
assertThat(stringAct != null).as("doh!").isTrue();
assertThat(stringAct != null).isEqualTo(true);
assertThat(stringAct != null).isNotEqualTo(false);
assertThat(stringAct != null).isFalse();
assertThat(stringAct != null).isEqualTo(false);
assertThat(stringAct != null).isNotEqualTo(true);
assertThat(null != stringAct).as("doh!").isTrue();
assertThat(null != stringAct).isEqualTo(true);
assertThat(null != stringAct).isNotEqualTo(false);
assertThat(null != stringAct).isFalse();
assertThat(null != stringAct).isEqualTo(false);
assertThat(null != stringAct).isNotEqualTo(true);
assertThat(null == null).isTrue();
assertThat(!false).isTrue();
@@ -0,0 +1,218 @@
import java.io.File;
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class BogusAssertions {
private void bogusAssertions() {
boolean[] boolarray = new boolean[10];
byte[] bytearray = new byte[10];
short[] shortarray = new short[10];
int[] intarray = new int[10];
long[] longarray = new long[10];
float[] floatarray = new float[10];
double[] doublearray = new double[10];
char[] chararray = new char[10];
Object[] objarray = new Object[10];
String string = "foo";
List<String> list = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
String bar = "bar";
assertThat(boolarray).isEqualTo(boolarray);
assertThat(boolarray).isSameAs(boolarray);
assertThat(boolarray).hasSameClassAs(boolarray);
assertThat(boolarray).hasSameHashCodeAs(boolarray);
assertThat(boolarray).hasSameSizeAs(boolarray);
assertThat(boolarray).contains(boolarray);
assertThat(boolarray).containsAnyOf(boolarray);
assertThat(boolarray).containsExactly(boolarray);
assertThat(boolarray).containsExactlyInAnyOrder(boolarray);
assertThat(boolarray).containsOnly(boolarray);
assertThat(boolarray).containsSequence(boolarray);
assertThat(boolarray).containsSubsequence(boolarray);
assertThat(boolarray).startsWith(boolarray);
assertThat(boolarray).endsWith(boolarray);
assertThat(bytearray).isEqualTo(bytearray);
assertThat(bytearray).isSameAs(bytearray);
assertThat(bytearray).hasSameClassAs(bytearray);
assertThat(bytearray).hasSameHashCodeAs(bytearray);
assertThat(bytearray).hasSameSizeAs(bytearray);
assertThat(bytearray).contains(bytearray);
assertThat(bytearray).containsAnyOf(bytearray);
assertThat(bytearray).containsExactly(bytearray);
assertThat(bytearray).containsExactlyInAnyOrder(bytearray);
assertThat(bytearray).containsOnly(bytearray);
assertThat(bytearray).containsSequence(bytearray);
assertThat(bytearray).containsSubsequence(bytearray);
assertThat(bytearray).startsWith(bytearray);
assertThat(bytearray).endsWith(bytearray);
assertThat(shortarray).isEqualTo(shortarray);
assertThat(shortarray).isSameAs(shortarray);
assertThat(shortarray).hasSameClassAs(shortarray);
assertThat(shortarray).hasSameHashCodeAs(shortarray);
assertThat(shortarray).hasSameSizeAs(shortarray);
assertThat(shortarray).contains(shortarray);
assertThat(shortarray).containsAnyOf(shortarray);
assertThat(shortarray).containsExactly(shortarray);
assertThat(shortarray).containsExactlyInAnyOrder(shortarray);
assertThat(shortarray).containsOnly(shortarray);
assertThat(shortarray).containsSequence(shortarray);
assertThat(shortarray).containsSubsequence(shortarray);
assertThat(shortarray).startsWith(shortarray);
assertThat(shortarray).endsWith(shortarray);
assertThat(intarray).isEqualTo(intarray);
assertThat(intarray).isSameAs(intarray);
assertThat(intarray).hasSameClassAs(intarray);
assertThat(intarray).hasSameHashCodeAs(intarray);
assertThat(intarray).hasSameSizeAs(intarray);
assertThat(intarray).contains(intarray);
assertThat(intarray).containsAnyOf(intarray);
assertThat(intarray).containsExactly(intarray);
assertThat(intarray).containsExactlyInAnyOrder(intarray);
assertThat(intarray).containsOnly(intarray);
assertThat(intarray).containsSequence(intarray);
assertThat(intarray).containsSubsequence(intarray);
assertThat(intarray).startsWith(intarray);
assertThat(intarray).endsWith(intarray);
assertThat(longarray).isEqualTo(longarray);
assertThat(longarray).isSameAs(longarray);
assertThat(longarray).hasSameClassAs(longarray);
assertThat(longarray).hasSameHashCodeAs(longarray);
assertThat(longarray).hasSameSizeAs(longarray);
assertThat(longarray).contains(longarray);
assertThat(longarray).containsAnyOf(longarray);
assertThat(longarray).containsExactly(longarray);
assertThat(longarray).containsExactlyInAnyOrder(longarray);
assertThat(longarray).containsOnly(longarray);
assertThat(longarray).containsSequence(longarray);
assertThat(longarray).containsSubsequence(longarray);
assertThat(longarray).startsWith(longarray);
assertThat(longarray).endsWith(longarray);
assertThat(floatarray).isEqualTo(floatarray);
assertThat(floatarray).isSameAs(floatarray);
assertThat(floatarray).hasSameClassAs(floatarray);
assertThat(floatarray).hasSameHashCodeAs(floatarray);
assertThat(floatarray).hasSameSizeAs(floatarray);
assertThat(floatarray).contains(floatarray);
assertThat(floatarray).containsAnyOf(floatarray);
assertThat(floatarray).containsExactly(floatarray);
assertThat(floatarray).containsExactlyInAnyOrder(floatarray);
assertThat(floatarray).containsOnly(floatarray);
assertThat(floatarray).containsSequence(floatarray);
assertThat(floatarray).containsSubsequence(floatarray);
assertThat(floatarray).startsWith(floatarray);
assertThat(floatarray).endsWith(floatarray);
assertThat(doublearray).isEqualTo(doublearray);
assertThat(doublearray).isSameAs(doublearray);
assertThat(doublearray).hasSameClassAs(doublearray);
assertThat(doublearray).hasSameHashCodeAs(doublearray);
assertThat(doublearray).hasSameSizeAs(doublearray);
assertThat(doublearray).contains(doublearray);
assertThat(doublearray).containsAnyOf(doublearray);
assertThat(doublearray).containsExactly(doublearray);
assertThat(doublearray).containsExactlyInAnyOrder(doublearray);
assertThat(doublearray).containsOnly(doublearray);
assertThat(doublearray).containsSequence(doublearray);
assertThat(doublearray).containsSubsequence(doublearray);
assertThat(doublearray).startsWith(doublearray);
assertThat(doublearray).endsWith(doublearray);
assertThat(chararray).isEqualTo(chararray);
assertThat(chararray).isSameAs(chararray);
assertThat(chararray).hasSameClassAs(chararray);
assertThat(chararray).hasSameHashCodeAs(chararray);
assertThat(chararray).hasSameSizeAs(chararray);
assertThat(chararray).contains(chararray);
assertThat(chararray).containsAnyOf(chararray);
assertThat(chararray).containsExactly(chararray);
assertThat(chararray).containsExactlyInAnyOrder(chararray);
assertThat(chararray).containsOnly(chararray);
assertThat(chararray).containsSequence(chararray);
assertThat(chararray).containsSubsequence(chararray);
assertThat(chararray).startsWith(chararray);
assertThat(chararray).endsWith(chararray);
assertThat(objarray).isEqualTo(objarray);
assertThat(objarray).isSameAs(objarray);
assertThat(objarray).hasSameClassAs(objarray);
assertThat(objarray).hasSameHashCodeAs(objarray);
assertThat(objarray).hasSameSizeAs(objarray);
assertThat(objarray).contains(objarray);
assertThat(objarray).containsAnyOf(objarray);
assertThat(objarray).containsExactly(objarray);
assertThat(objarray).containsExactlyInAnyOrder(objarray);
assertThat(objarray).containsOnly(objarray);
assertThat(objarray).containsSequence(objarray);
assertThat(objarray).containsSubsequence(objarray);
assertThat(objarray).startsWith(objarray);
assertThat(objarray).endsWith(objarray);
assertThat(string).as("foo").isEqualTo(string);
assertThat(string).as("foo").isSameAs(string);
assertThat(string).as("foo").hasSameClassAs(string);
assertThat(string).as("foo").hasSameHashCodeAs(string);
assertThat(string).as("foo").hasSameSizeAs(string);
assertThat(string).as("foo").isEqualToIgnoringCase(string);
assertThat(string).as("foo").containsSequence(string);
assertThat(string).as("foo").containsSubsequence(string);
assertThat(string).as("foo").startsWith(string);
assertThat(string).as("foo").endsWith(string);
assertThat(list).as("foo").isEqualTo(list);
assertThat(list).as("foo").isSameAs(list);
assertThat(list).as("foo").hasSameClassAs(list);
assertThat(list).as("foo").hasSameHashCodeAs(list);
assertThat(list).as("foo").hasSameSizeAs(list);
assertThat(list).as("foo").containsAll(list);
assertThat(list).as("foo").containsAnyElementsOf(list);
assertThat(list).as("foo").containsOnlyElementsOf(list);
assertThat(list).as("foo").containsExactlyElementsOf(list);
assertThat(list).as("foo").hasSameElementsAs(list);
assertThat(list).as("foo").containsSequence(list);
assertThat(list).as("foo").containsSubsequence(list);
assertThat(map).as("foo").isEqualTo(map);
assertThat(map).as("foo").isSameAs(map);
assertThat(map).as("foo").hasSameClassAs(map);
assertThat(map).as("foo").hasSameHashCodeAs(map);
assertThat(map).as("foo").hasSameSizeAs(map);
assertThat(map).as("foo").containsAllEntriesOf(map);
assertThat(map).as("foo").containsExactlyEntriesOf(map);
assertThat(map).as("foo").containsExactlyInAnyOrderEntriesOf(map);
assertThat(bar).isEqualTo(string);
assertThat(new Random().nextBoolean()).isEqualTo(new Random().nextBoolean());
assertThat(generateString()).isEqualTo(generateString());
int number = 4;
assertThat(number++).isEqualTo(number++);
assertThat(number++).isEqualTo(number++);
org.junit.Assert.assertThat(list, null);
fail("oh no!");
}
private void test_equals() {
assertThat("foo").isEqualTo("foo");
assertThat(new File("foo")).isEqualTo(new File("foo"));
}
private void test_HasHCode() {
assertThat("foo").hasSameHashCodeAs("foo");
}
private String generateString()
{
return "foo";
}
}
@@ -0,0 +1,63 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
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(keyValueMap).containsEntry("foo", 2);
assertThat(keyValueMap).doesNotContainEntry("foo", 3);
assertThat(keyValueMap).containsEntry("foo", null);
assertThat(keyValueMap).containsEntry("foo", null);
assertThat(keyValueMap).containsKey("foo");
assertThat(keyValueMap).containsKey("foo");
Map<String, String> stringStringMap = new HashMap<>();
assertThat(stringStringMap).containsEntry("foo", "bar");
assertThat(stringStringMap).doesNotContainEntry("foo", "bar");
assertThat(stringStringMap).containsEntry("foo", null);
assertThat(stringStringMap).containsEntry("foo", null);
assertThat(stringStringMap).containsKey("foo");
assertThat(stringStringMap).containsKey("foo");
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(stringList, null);
fail("oh no!");
}
}
@@ -0,0 +1,41 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class CompareTo {
private void comparable() {
String string = "string";
assertThat(string).isEqualByComparingTo("foo");
assertThat(string).isEqualByComparingTo("foo");
assertThat(string).isNotEqualByComparingTo("foo");
assertThat(string).isNotEqualByComparingTo("foo");
assertThat(string).isGreaterThanOrEqualTo("foo");
assertThat(string).isGreaterThanOrEqualTo("foo");
assertThat(string).isGreaterThanOrEqualTo("foo");
assertThat(string).isGreaterThanOrEqualTo("foo");
assertThat(string).isGreaterThan("foo");
assertThat(string).isGreaterThan("foo");
assertThat(string).isGreaterThan("foo");
assertThat(string).isGreaterThan("foo");
assertThat(string).isGreaterThan("foo");
assertThat(string).isLessThanOrEqualTo("foo");
assertThat(string).isLessThanOrEqualTo("foo");
assertThat(string).isLessThanOrEqualTo("foo");
assertThat(string).isLessThanOrEqualTo("foo");
assertThat(string).isLessThan("foo");
assertThat(string).isLessThan("foo");
assertThat(string).isLessThan("foo");
assertThat(string).isLessThan("foo");
assertThat(string.compareTo("foo")).isNotEqualTo(2);
assertThat(string.compareTo("foo")).isEqualTo(2);
org.junit.Assert.assertThat(string, null);
fail("oh no!");
}
}
@@ -0,0 +1,41 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class CompareTo {
private void comparable() {
String string = "string";
assertThat(string.compareTo("foo")).isEqualTo(0);
assertThat(string.compareTo("foo")).isZero();
assertThat(string.compareTo("foo")).isNotEqualTo(0);
assertThat(string.compareTo("foo")).isNotZero();
assertThat(string.compareTo("foo")).isNotEqualTo(-1);
assertThat(string.compareTo("foo")).isGreaterThanOrEqualTo(0);
assertThat(string.compareTo("foo")).isGreaterThan(-1);
assertThat(string.compareTo("foo")).isNotNegative();
assertThat(string.compareTo("foo")).isEqualTo(1);
assertThat(string.compareTo("foo")).isOne();
assertThat(string.compareTo("foo")).isGreaterThan(0);
assertThat(string.compareTo("foo")).isPositive();
assertThat(string.compareTo("foo")).isGreaterThanOrEqualTo(1);
assertThat(string.compareTo("foo")).isNotEqualTo(1);
assertThat(string.compareTo("foo")).isLessThanOrEqualTo(0);
assertThat(string.compareTo("foo")).isLessThan(1);
assertThat(string.compareTo("foo")).isNotPositive();
assertThat(string.compareTo("foo")).isEqualTo(-1);
assertThat(string.compareTo("foo")).isLessThan(0);
assertThat(string.compareTo("foo")).isNegative();
assertThat(string.compareTo("foo")).isLessThanOrEqualTo(-1);
assertThat(string.compareTo("foo")).isNotEqualTo(2);
assertThat(string.compareTo("foo")).isEqualTo(2);
org.junit.Assert.assertThat(string, null);
fail("oh no!");
}
}
@@ -16,7 +16,32 @@ public class EnumerableIsEmpty {
assertThat(new ArrayList<Long>()).as("etc").hasSize(1);
assertThat(new Long[1]).as("etc").hasSize(1);
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("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("string").as("foo").isNotEmpty();
assertThat(new StringBuilder()).as("bar").isNotEmpty();
assertThat(new ArrayList<Long>()).as("etc").isNotEmpty();
assertThat(new Long[1]).as("etc").isNotEmpty();
assertThat("string").as("foo").isNotEmpty();
assertThat(new StringBuilder()).as("bar").isNotEmpty();
assertThat(new ArrayList<Long>()).as("etc").isNotEmpty();
assertThat(new Long[1]).as("etc").isNotEmpty();
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").isEmpty();
assertThat("string").as("foo").hasSizeLessThanOrEqualTo(0).hasSameSizeAs("foo").isEmpty();
assertThat("string").as("foo").hasSizeLessThan(1).hasSameSizeAs("foo").isEmpty();
assertThat("string").as("foo").isNotEmpty().hasSameSizeAs("foo").isNotEmpty();
assertThat("string").as("foo").isNotEmpty().hasSameSizeAs("foo").isNotEmpty();
org.junit.Assert.assertThat("foo", null);
fail("oh no!");
@@ -16,7 +16,32 @@ public class EnumerableIsEmpty {
assertThat(new ArrayList<Long>()).as("etc").hasSize(1);
assertThat(new Long[1]).as("etc").hasSize(1);
assertThat("string").as("foo").hasSizeLessThanOrEqualTo(0);
assertThat(new StringBuilder()).as("bar").hasSizeLessThanOrEqualTo(0 + 0);
assertThat(new ArrayList<Long>()).as("etc").hasSizeLessThanOrEqualTo(10 / 100);
assertThat(new Long[1]).as("etc").hasSizeLessThanOrEqualTo(1 - 1);
assertThat("string").as("foo").hasSizeLessThan(1);
assertThat(new StringBuilder()).as("bar").hasSizeLessThan(0 + 1);
assertThat(new ArrayList<Long>()).as("etc").hasSizeLessThan(10 / 10);
assertThat(new Long[1]).as("etc").hasSizeLessThan(1 - 0);
assertThat("string").as("foo").hasSizeGreaterThan(0);
assertThat(new StringBuilder()).as("bar").hasSizeGreaterThan(0 + 0);
assertThat(new ArrayList<Long>()).as("etc").hasSizeGreaterThan(10 / 100);
assertThat(new Long[1]).as("etc").hasSizeGreaterThan(1 - 1);
assertThat("string").as("foo").hasSizeGreaterThanOrEqualTo(1);
assertThat(new StringBuilder()).as("bar").hasSizeGreaterThanOrEqualTo(0 + 1);
assertThat(new ArrayList<Long>()).as("etc").hasSizeGreaterThanOrEqualTo(10 / 10);
assertThat(new Long[1]).as("etc").hasSizeGreaterThanOrEqualTo(1 - 0);
assertThat("string").as("foo").hasSize(0).hasSameSizeAs("foo").hasSize(0);
assertThat("string").as("foo").hasSizeLessThanOrEqualTo(0).hasSameSizeAs("foo").hasSizeLessThanOrEqualTo(0);
assertThat("string").as("foo").hasSizeLessThan(1).hasSameSizeAs("foo").hasSizeLessThan(1);
assertThat("string").as("foo").hasSizeGreaterThan(0).hasSameSizeAs("foo").hasSizeGreaterThan(0);
assertThat("string").as("foo").hasSizeGreaterThanOrEqualTo(1).hasSameSizeAs("foo").hasSizeGreaterThanOrEqualTo(1);
org.junit.Assert.assertThat("foo", null);
fail("oh no!");
@@ -0,0 +1,106 @@
import java.io.File;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class FileExpression {
private void fileExpression() {
File file = new File("foo");
assertThat(file).as("foo").canRead();
assertThat(file).canRead();
assertThat(file).canRead();
assertThat(file.canRead()).as("foo").isEqualTo(false);
assertThat(file.canRead()).isNotEqualTo(true);
assertThat(file.canRead()).isFalse();
assertThat(file).as("foo").canWrite();
assertThat(file).canWrite();
assertThat(file).canWrite();
assertThat(file.canWrite()).as("foo").isEqualTo(false);
assertThat(file.canWrite()).isNotEqualTo(true);
assertThat(file.canWrite()).isFalse();
assertThat(file).as("foo").exists();
assertThat(file).exists();
assertThat(file).exists();
assertThat(file).as("foo").doesNotExist();
assertThat(file).doesNotExist();
assertThat(file).doesNotExist();
assertThat(file).as("foo").isAbsolute();
assertThat(file).isAbsolute();
assertThat(file).isAbsolute();
assertThat(file).as("foo").isRelative();
assertThat(file).isRelative();
assertThat(file).isRelative();
assertThat(file).as("foo").isDirectory();
assertThat(file).isDirectory();
assertThat(file).isDirectory();
assertThat(file.isDirectory()).as("foo").isEqualTo(false);
assertThat(file.isDirectory()).isNotEqualTo(true);
assertThat(file.isDirectory()).isFalse();
assertThat(file).as("foo").isFile();
assertThat(file).isFile();
assertThat(file).isFile();
assertThat(file.isFile()).as("foo").isEqualTo(false);
assertThat(file.isFile()).isNotEqualTo(true);
assertThat(file.isFile()).isFalse();
assertThat(file).hasName("foo");
assertThat(file.getName()).isNotEqualTo("foo");
assertThat(file).hasName(null);
assertThat(file.getName()).isNull();
assertThat(file.getName()).isNotEqualTo(null);
assertThat(file.getName()).isNotNull();
assertThat(file.getName()).isEmpty();
assertThat(file.getName()).isNotEmpty();
assertThat(file).hasParent("foo");
assertThat(file.getParent()).isNotEqualTo("foo");
assertThat(file).hasNoParent();
assertThat(file).hasNoParent();
assertThat(file.getParent()).isNotEqualTo(null);
assertThat(file.getParent()).isNotNull();
assertThat(file.getParent()).isEmpty();
assertThat(file.getParent()).isNotEmpty();
assertThat(file).hasParent(new File("foo"));
assertThat(file.getParentFile()).isNotEqualTo(new File("foo"));
assertThat(file).hasNoParent();
assertThat(file).hasNoParent();
assertThat(file.getParentFile()).isNotEqualTo(null);
assertThat(file.getParentFile()).isNotNull();
assertThat(file).isEmpty();
assertThat(file).isEmpty();
assertThat(file).isNotEmpty();
assertThat(file).isNotEmpty();
assertThat(file).hasSize(2);
assertThat(file.listFiles()).isNull();
assertThat(file.listFiles()).isNullOrEmpty();
assertThat(file).isEmptyDirectory();
assertThat(file).isNotEmptyDirectory();
assertThat(file.listFiles(f -> f.canExecute())).isNull();
assertThat(file.listFiles(f -> f.canExecute())).isNullOrEmpty();
assertThat(file.listFiles(f -> f.canExecute())).isEmpty();
assertThat(file.listFiles(f -> f.canExecute())).isNotEmpty();
assertThat(file.list()).isNull();
assertThat(file.list()).isNullOrEmpty();
assertThat(file).isEmptyDirectory();
assertThat(file).isNotEmptyDirectory();
assertThat(file.getName()).endsWith(".foo"); // could be turned into .hasExtension("foo"), but not always.
assertThat(file).as("foo").hasName("foo").as("bar").hasName("bar");
org.junit.Assert.assertThat(file, null);
fail("oh no!");
}
}
@@ -0,0 +1,106 @@
import java.io.File;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class FileExpression {
private void fileExpression() {
File file = new File("foo");
assertThat(file.canRead()).as("foo").isEqualTo(true);
assertThat(file.canRead()).isNotEqualTo(false);
assertThat(file.canRead()).isTrue();
assertThat(file.canRead()).as("foo").isEqualTo(false);
assertThat(file.canRead()).isNotEqualTo(true);
assertThat(file.canRead()).isFalse();
assertThat(file.canWrite()).as("foo").isEqualTo(true);
assertThat(file.canWrite()).isNotEqualTo(false);
assertThat(file.canWrite()).isTrue();
assertThat(file.canWrite()).as("foo").isEqualTo(false);
assertThat(file.canWrite()).isNotEqualTo(true);
assertThat(file.canWrite()).isFalse();
assertThat(file.exists()).as("foo").isEqualTo(true);
assertThat(file.exists()).isNotEqualTo(false);
assertThat(file.exists()).isTrue();
assertThat(file.exists()).as("foo").isEqualTo(false);
assertThat(file.exists()).isNotEqualTo(true);
assertThat(file.exists()).isFalse();
assertThat(file.isAbsolute()).as("foo").isEqualTo(true);
assertThat(file.isAbsolute()).isNotEqualTo(false);
assertThat(file.isAbsolute()).isTrue();
assertThat(file.isAbsolute()).as("foo").isEqualTo(false);
assertThat(file.isAbsolute()).isNotEqualTo(true);
assertThat(file.isAbsolute()).isFalse();
assertThat(file.isDirectory()).as("foo").isEqualTo(true);
assertThat(file.isDirectory()).isNotEqualTo(false);
assertThat(file.isDirectory()).isTrue();
assertThat(file.isDirectory()).as("foo").isEqualTo(false);
assertThat(file.isDirectory()).isNotEqualTo(true);
assertThat(file.isDirectory()).isFalse();
assertThat(file.isFile()).as("foo").isEqualTo(true);
assertThat(file.isFile()).isNotEqualTo(false);
assertThat(file.isFile()).isTrue();
assertThat(file.isFile()).as("foo").isEqualTo(false);
assertThat(file.isFile()).isNotEqualTo(true);
assertThat(file.isFile()).isFalse();
assertThat(file.getName()).isEqualTo("foo");
assertThat(file.getName()).isNotEqualTo("foo");
assertThat(file.getName()).isEqualTo(null);
assertThat(file.getName()).isNull();
assertThat(file.getName()).isNotEqualTo(null);
assertThat(file.getName()).isNotNull();
assertThat(file.getName()).isEmpty();
assertThat(file.getName()).isNotEmpty();
assertThat(file.getParent()).isEqualTo("foo");
assertThat(file.getParent()).isNotEqualTo("foo");
assertThat(file.getParent()).isEqualTo(null);
assertThat(file.getParent()).isNull();
assertThat(file.getParent()).isNotEqualTo(null);
assertThat(file.getParent()).isNotNull();
assertThat(file.getParent()).isEmpty();
assertThat(file.getParent()).isNotEmpty();
assertThat(file.getParentFile()).isEqualTo(new File("foo"));
assertThat(file.getParentFile()).isNotEqualTo(new File("foo"));
assertThat(file.getParentFile()).isEqualTo(null);
assertThat(file.getParentFile()).isNull();
assertThat(file.getParentFile()).isNotEqualTo(null);
assertThat(file.getParentFile()).isNotNull();
assertThat(file.length()).isEqualTo(0);
assertThat(file.length()).isZero();
assertThat(file.length()).isNotEqualTo(0);
assertThat(file.length()).isNotZero();
assertThat(file.length()).isEqualTo(2);
assertThat(file.listFiles()).isNull();
assertThat(file.listFiles()).isNullOrEmpty();
assertThat(file.listFiles()).isEmpty();
assertThat(file.listFiles()).isNotEmpty();
assertThat(file.listFiles(f -> f.canExecute())).isNull();
assertThat(file.listFiles(f -> f.canExecute())).isNullOrEmpty();
assertThat(file.listFiles(f -> f.canExecute())).isEmpty();
assertThat(file.listFiles(f -> f.canExecute())).isNotEmpty();
assertThat(file.list()).isNull();
assertThat(file.list()).isNullOrEmpty();
assertThat(file.list()).isEmpty();
assertThat(file.list()).isNotEmpty();
assertThat(file.getName()).endsWith(".foo"); // could be turned into .hasExtension("foo"), but not always.
assertThat(file.getName()).as("foo").isEqualTo("foo").as("bar").isEqualTo("bar");
org.junit.Assert.assertThat(file, null);
fail("oh no!");
}
}
@@ -73,6 +73,8 @@ public class GuavaOptional {
assertThat(opt.orNull()).as("foo").isEqualTo(null).isNotNull();
assertThat(Optional.of(new byte[] { 2, 3 }).get()).isEqualTo(new byte[] { 2, 3 }); // not working with assertj-guava 3.2.1
org.junit.Assert.assertThat(opt, null);
fail("oh no!");
}
@@ -73,6 +73,8 @@ public class GuavaOptional {
assertThat(opt.orNull()).as("foo").isEqualTo(null).isNotNull();
assertThat(Optional.of(new byte[] { 2, 3 }).get()).isEqualTo(new byte[] { 2, 3 }); // not working with assertj-guava 3.2.1
org.junit.Assert.assertThat(opt, null);
fail("oh no!");
}
@@ -153,6 +153,7 @@ public class ImplicitAssertion {
assertThat(list).areAtMost(1, stringCondition);
assertThat(list).areExactly(1, stringCondition);
assertThat(list).hasOnlyOneElementSatisfying(stringConsumer);
assertThat(list).singleElement(as(STRING)).isEqualTo(stringConsumer);
assertThat(list).haveAtLeastOne(stringCondition);
assertThat(list).haveAtLeast(1, stringCondition);
assertThat(list).haveAtMost(1, stringCondition);
@@ -229,6 +230,7 @@ public class ImplicitAssertion {
assertThat(list).isNotEmpty().areAtMost(1, stringCondition);
assertThat(list).isNotEmpty().areExactly(1, stringCondition);
assertThat(list).isNotEmpty().hasOnlyOneElementSatisfying(stringConsumer);
assertThat(list).isNotEmpty().singleElement(as(STRING)).isEqualTo(stringConsumer);
assertThat(list).haveAtLeastOne(stringCondition);
assertThat(list).isNotEmpty().haveAtLeast(1, stringCondition);
assertThat(list).isNotEmpty().haveAtMost(1, stringCondition);
@@ -153,6 +153,7 @@ public class ImplicitAssertion {
assertThat(list).isNotNull().areAtMost(1, stringCondition);
assertThat(list).isNotNull().areExactly(1, stringCondition);
assertThat(list).isNotNull().hasOnlyOneElementSatisfying(stringConsumer);
assertThat(list).isNotNull().singleElement(as(STRING)).isEqualTo(stringConsumer);
assertThat(list).isNotNull().haveAtLeastOne(stringCondition);
assertThat(list).isNotNull().haveAtLeast(1, stringCondition);
assertThat(list).isNotNull().haveAtMost(1, stringCondition);
@@ -229,6 +230,7 @@ public class ImplicitAssertion {
assertThat(list).isNotEmpty().areAtMost(1, stringCondition);
assertThat(list).isNotEmpty().areExactly(1, stringCondition);
assertThat(list).isNotEmpty().hasOnlyOneElementSatisfying(stringConsumer);
assertThat(list).isNotEmpty().singleElement(as(STRING)).isEqualTo(stringConsumer);
assertThat(list).isNotEmpty().haveAtLeastOne(stringCondition);
assertThat(list).isNotEmpty().haveAtLeast(1, stringCondition);
assertThat(list).isNotEmpty().haveAtMost(1, stringCondition);
@@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.fail;
public class InvertedBooleanCondition {
private void invertedBooleanCondition() {
private void invertedBooleanCondition(boolean primitiveVariable, Boolean objectVariable) {
boolean primitive = false;
Boolean object = Boolean.TRUE;
@@ -37,6 +37,23 @@ public class InvertedBooleanCondition {
assertThat(primitive).as("foo").isFalse().as("bar").isFalse();
assertThat(primitive).as("foo").isFalse().as("bar").isTrue();
assertThat(primitive).isNotEqualTo(primitiveVariable);
assertThat(primitive).isEqualTo(primitiveVariable);
assertThat(object).isNotEqualTo(primitiveVariable);
assertThat(object).isEqualTo(primitiveVariable);
assertThat(primitive).isEqualTo(!objectVariable); // not safe for null value
assertThat(primitive).isNotEqualTo(!objectVariable); // not safe for null value
assertThat(object).isEqualTo(!objectVariable); // not safe for null value
assertThat(object).isNotEqualTo(!objectVariable); // not safe for null value
assertThat(primitive).isNotEqualTo(primitiveVariable);
assertThat(primitive).isNotEqualTo(primitiveVariable);
assertThat(primitive).isEqualTo(!primitiveVariable && objectVariable);
org.junit.Assert.assertThat(object, null);
fail("oh no!");
}
@@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.fail;
public class InvertedBooleanCondition {
private void invertedBooleanCondition() {
private void invertedBooleanCondition(boolean primitiveVariable, Boolean objectVariable) {
boolean primitive = false;
Boolean object = Boolean.TRUE;
@@ -37,6 +37,23 @@ 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);
assertThat(primitive).isEqualTo(!primitiveVariable);
assertThat(primitive).isNotEqualTo(!primitiveVariable);
assertThat(object).isEqualTo(!primitiveVariable);
assertThat(object).isNotEqualTo(!primitiveVariable);
assertThat(primitive).isEqualTo(!objectVariable); // not safe for null value
assertThat(primitive).isNotEqualTo(!objectVariable); // not safe for null value
assertThat(object).isEqualTo(!objectVariable); // not safe for null value
assertThat(object).isNotEqualTo(!objectVariable); // not safe for null value
assertThat(primitive).isEqualTo((!primitiveVariable));
assertThat(primitive).isEqualTo(!(primitiveVariable));
assertThat(primitive).isEqualTo(!primitiveVariable && objectVariable);
org.junit.Assert.assertThat(object, null);
fail("oh no!");
}
@@ -0,0 +1,67 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class IsZeroOne {
private void isZeroOne() {
short shortValue = 0;
int intValue = 0;
long longValue = 0L;
float floatValue = 0.0f;
double doubleValue = 0.0;
assertThat(shortValue).as("foo").isZero();
assertThat(shortValue).isZero();
assertThat(shortValue).as("foo").isOne();
assertThat(shortValue).isOne();
assertThat(shortValue).as("foo").isNotZero();
assertThat(shortValue).isNotZero();
assertThat(shortValue).as("foo").isNotEqualTo(1);
assertThat(shortValue).isNotEqualTo(0 + 1);
assertThat(intValue).as("foo").isZero();
assertThat(intValue).isZero();
assertThat(intValue).as("foo").isOne();
assertThat(intValue).isOne();
assertThat(intValue).as("foo").isNotZero();
assertThat(intValue).isNotZero();
assertThat(intValue).as("foo").isNotEqualTo(1);
assertThat(intValue).isNotEqualTo(0 + 1);
assertThat(longValue).as("foo").isZero();
assertThat(longValue).isZero();
assertThat(longValue).as("foo").isOne();
assertThat(longValue).isOne();
assertThat(longValue).as("foo").isNotZero();
assertThat(longValue).isNotZero();
assertThat(longValue).as("foo").isNotEqualTo(1L);
assertThat(longValue).isNotEqualTo(0L + 1L);
assertThat(floatValue).as("foo").isZero();
assertThat(floatValue).isZero();
assertThat(floatValue).as("foo").isOne();
assertThat(floatValue).isOne();
assertThat(floatValue).as("foo").isNotZero();
assertThat(floatValue).isNotZero();
assertThat(floatValue).as("foo").isNotEqualTo(1.0f);
assertThat(floatValue).isNotEqualTo(0.0f + 1.0f);
assertThat(doubleValue).as("foo").isZero();
assertThat(doubleValue).isZero();
assertThat(doubleValue).as("foo").isOne();
assertThat(doubleValue).isOne();
assertThat(doubleValue).as("foo").isNotZero();
assertThat(doubleValue).isNotZero();
assertThat(doubleValue).as("foo").isNotEqualTo(1.0);
assertThat(doubleValue).isNotEqualTo(0.0 + 1.0);
assertThat(intValue).as("foo").isEqualTo(2);
fail("oh no!");
}
}
@@ -0,0 +1,67 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class IsZeroOne {
private void isZeroOne() {
short shortValue = 0;
int intValue = 0;
long longValue = 0L;
float floatValue = 0.0f;
double doubleValue = 0.0;
assertThat(shortValue).as("foo").isEqualTo(0);
assertThat(shortValue).isEqualTo(1 - 1);
assertThat(shortValue).as("foo").isEqualTo(1);
assertThat(shortValue).isEqualTo(0 + 1);
assertThat(shortValue).as("foo").isNotEqualTo(0);
assertThat(shortValue).isNotEqualTo(1 - 1);
assertThat(shortValue).as("foo").isNotEqualTo(1);
assertThat(shortValue).isNotEqualTo(0 + 1);
assertThat(intValue).as("foo").isEqualTo(0);
assertThat(intValue).isEqualTo(1 - 1);
assertThat(intValue).as("foo").isEqualTo(1);
assertThat(intValue).isEqualTo(0 + 1);
assertThat(intValue).as("foo").isNotEqualTo(0);
assertThat(intValue).isNotEqualTo(1 - 1);
assertThat(intValue).as("foo").isNotEqualTo(1);
assertThat(intValue).isNotEqualTo(0 + 1);
assertThat(longValue).as("foo").isEqualTo(0L);
assertThat(longValue).isEqualTo(1L - 1L);
assertThat(longValue).as("foo").isEqualTo(1L);
assertThat(longValue).isEqualTo(0L + 1L);
assertThat(longValue).as("foo").isNotEqualTo(0L);
assertThat(longValue).isNotEqualTo(1L - 1L);
assertThat(longValue).as("foo").isNotEqualTo(1L);
assertThat(longValue).isNotEqualTo(0L + 1L);
assertThat(floatValue).as("foo").isEqualTo(0.0f);
assertThat(floatValue).isEqualTo(1.0f - 1.0f);
assertThat(floatValue).as("foo").isEqualTo(1.0f);
assertThat(floatValue).isEqualTo(0.0f + 1.0f);
assertThat(floatValue).as("foo").isNotEqualTo(0.0f);
assertThat(floatValue).isNotEqualTo(1.0f - 1.0f);
assertThat(floatValue).as("foo").isNotEqualTo(1.0f);
assertThat(floatValue).isNotEqualTo(0.0f + 1.0f);
assertThat(doubleValue).as("foo").isEqualTo(0.0);
assertThat(doubleValue).isEqualTo(1.0 - 1.0);
assertThat(doubleValue).as("foo").isEqualTo(1.0);
assertThat(doubleValue).isEqualTo(0.0 + 1.0);
assertThat(doubleValue).as("foo").isNotEqualTo(0.0);
assertThat(doubleValue).isNotEqualTo(1.0 - 1.0);
assertThat(doubleValue).as("foo").isNotEqualTo(1.0);
assertThat(doubleValue).isNotEqualTo(0.0 + 1.0);
assertThat(intValue).as("foo").isEqualTo(2);
fail("oh no!");
}
}
@@ -66,6 +66,9 @@ public class JoinStatements {
assertThat(list.get(--i)).isEqualTo("foo");
assertThat(list.get(--i)).isEqualTo("foo");
assertThat(list).filteredOn("foo", "foo").contains("narf");
assertThat(list).filteredOn("bar", "bar").contains("puit");
org.junit.Assert.assertThat(list, null);
fail("oh no!");
}
@@ -63,6 +63,9 @@ public class JoinStatements {
assertThat(list.get(--i)).isEqualTo("foo");
assertThat(list.get(--i)).isEqualTo("foo");
assertThat(list).filteredOn("foo", "foo").contains("narf");
assertThat(list).filteredOn("bar", "bar").contains("puit");
org.junit.Assert.assertThat(list, null);
fail("oh no!");
}
@@ -0,0 +1,126 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class PathExpression {
private void pathExpression() {
Path path = Paths.get("foo");
Path otherPath = Paths.get("bar");
assertThat(path).as("foo").isAbsolute();
assertThat(path).isAbsolute();
assertThat(path).isAbsolute();
assertThat(path).as("foo").isRelative();
assertThat(path).isRelative();
assertThat(path).isRelative();
assertThat(path).hasParentRaw(otherPath);
assertThat(path.getParent()).isNotEqualTo(otherPath);
assertThat(path).hasNoParentRaw();
assertThat(path).hasNoParentRaw();
assertThat(path.getParent()).isNotEqualTo(null);
assertThat(path.getParent()).isNotNull();
assertThat(path).as("foo").startsWithRaw(otherPath);
assertThat(path).startsWithRaw(otherPath);
assertThat(path).startsWithRaw(otherPath);
assertThat(path.startsWith(otherPath)).as("foo").isEqualTo(false);
assertThat(path.startsWith(otherPath)).isNotEqualTo(true);
assertThat(path.startsWith(otherPath)).isFalse();
assertThat(path.startsWith("otherPath")).as("foo").isEqualTo(true);
assertThat(path.startsWith("otherPath")).isNotEqualTo(false);
assertThat(path.startsWith("otherPath")).isTrue();
assertThat(path.startsWith("otherPath")).as("foo").isEqualTo(false);
assertThat(path.startsWith("otherPath")).isNotEqualTo(true);
assertThat(path.startsWith("otherPath")).isFalse();
assertThat(path).as("foo").endsWithRaw(otherPath);
assertThat(path).endsWithRaw(otherPath);
assertThat(path).endsWithRaw(otherPath);
assertThat(path.endsWith(otherPath)).as("foo").isEqualTo(false);
assertThat(path.endsWith(otherPath)).isNotEqualTo(true);
assertThat(path.endsWith(otherPath)).isFalse();
assertThat(path.endsWith("otherPath")).as("foo").isEqualTo(true);
assertThat(path.endsWith("otherPath")).isNotEqualTo(false);
assertThat(path.endsWith("otherPath")).isTrue();
assertThat(path.endsWith("otherPath")).as("foo").isEqualTo(false);
assertThat(path.endsWith("otherPath")).isNotEqualTo(true);
assertThat(path.endsWith("otherPath")).isFalse();
assertThat(Files.isReadable(path)).as("foo").isEqualTo(true);
assertThat(Files.isReadable(path)).isNotEqualTo(false);
assertThat(Files.isReadable(path)).isTrue();
assertThat(Files.isReadable(path)).as("foo").isEqualTo(false);
assertThat(Files.isReadable(path)).isNotEqualTo(true);
assertThat(Files.isReadable(path)).isFalse();
assertThat(Files.isWritable(path)).as("foo").isEqualTo(true);
assertThat(Files.isWritable(path)).isNotEqualTo(false);
assertThat(Files.isWritable(path)).isTrue();
assertThat(Files.isWritable(path)).as("foo").isEqualTo(false);
assertThat(Files.isWritable(path)).isNotEqualTo(true);
assertThat(Files.isWritable(path)).isFalse();
assertThat(Files.isExecutable(path)).as("foo").isEqualTo(true);
assertThat(Files.isExecutable(path)).isNotEqualTo(false);
assertThat(Files.isExecutable(path)).isTrue();
assertThat(Files.isExecutable(path)).as("foo").isEqualTo(false);
assertThat(Files.isExecutable(path)).isNotEqualTo(true);
assertThat(Files.isExecutable(path)).isFalse();
assertThat(Files.isDirectory(path)).as("foo").isEqualTo(true);
assertThat(Files.isDirectory(path)).isNotEqualTo(false);
assertThat(Files.isDirectory(path)).isTrue();
assertThat(Files.isDirectory(path)).as("foo").isEqualTo(false);
assertThat(Files.isDirectory(path)).isNotEqualTo(true);
assertThat(Files.isDirectory(path)).isFalse();
assertThat(Files.isRegularFile(path)).as("foo").isEqualTo(true);
assertThat(Files.isRegularFile(path)).isNotEqualTo(false);
assertThat(Files.isRegularFile(path)).isTrue();
assertThat(Files.isRegularFile(path)).as("foo").isEqualTo(false);
assertThat(Files.isRegularFile(path)).isNotEqualTo(true);
assertThat(Files.isRegularFile(path)).isFalse();
assertThat(Files.isSymbolicLink(path)).as("foo").isEqualTo(true);
assertThat(Files.isSymbolicLink(path)).isNotEqualTo(false);
assertThat(Files.isSymbolicLink(path)).isTrue();
assertThat(Files.isSymbolicLink(path)).as("foo").isEqualTo(false);
assertThat(Files.isSymbolicLink(path)).isNotEqualTo(true);
assertThat(Files.isSymbolicLink(path)).isFalse();
assertThat(Files.exists(path)).as("foo").isEqualTo(true);
assertThat(Files.exists(path)).isNotEqualTo(false);
assertThat(Files.exists(path)).isTrue();
assertThat(Files.exists(path)).as("foo").isEqualTo(false);
assertThat(Files.exists(path)).isNotEqualTo(true);
assertThat(Files.exists(path)).isFalse();
assertThat(Files.notExists(path)).as("foo").isEqualTo(true);
assertThat(Files.notExists(path)).isNotEqualTo(false);
assertThat(Files.notExists(path)).isTrue();
assertThat(Files.notExists(path)).as("foo").isEqualTo(false);
assertThat(Files.notExists(path)).isNotEqualTo(true);
assertThat(Files.notExists(path)).isFalse();
assertThat(Files.list(path)).isEmpty();
assertThat(Files.list(path)).isNotEmpty();
assertThat(Files.readAllBytes(path)).isEqualTo(new byte[1]);
assertThat(Files.readAllLines(path)).containsExactly("foo");
assertThat(Files.lines(path)).containsExactly("foo");
assertThat(path.getName()).endsWith(".foo"); // could be turned into .hasExtension("foo"), but not always.
assertThat(path.getName()).as("foo").isEqualTo("foo").as("bar").isEqualTo("bar");
org.junit.Assert.assertThat(path, null);
fail("oh no!");
}
}
@@ -0,0 +1,126 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class PathExpression {
private void pathExpression() {
Path path = Paths.get("foo");
Path otherPath = Paths.get("bar");
assertThat(path.isAbsolute()).as("foo").isEqualTo(true);
assertThat(path.isAbsolute()).isNotEqualTo(false);
assertThat(path.isAbsolute()).isTrue();
assertThat(path.isAbsolute()).as("foo").isEqualTo(false);
assertThat(path.isAbsolute()).isNotEqualTo(true);
assertThat(path.isAbsolute()).isFalse();
assertThat(path.getParent()).isEqualTo(otherPath);
assertThat(path.getParent()).isNotEqualTo(otherPath);
assertThat(path.getParent()).isEqualTo(null);
assertThat(path.getParent()).isNull();
assertThat(path.getParent()).isNotEqualTo(null);
assertThat(path.getParent()).isNotNull();
assertThat(path.startsWith(otherPath)).as("foo").isEqualTo(true);
assertThat(path.startsWith(otherPath)).isNotEqualTo(false);
assertThat(path.startsWith(otherPath)).isTrue();
assertThat(path.startsWith(otherPath)).as("foo").isEqualTo(false);
assertThat(path.startsWith(otherPath)).isNotEqualTo(true);
assertThat(path.startsWith(otherPath)).isFalse();
assertThat(path.startsWith("otherPath")).as("foo").isEqualTo(true);
assertThat(path.startsWith("otherPath")).isNotEqualTo(false);
assertThat(path.startsWith("otherPath")).isTrue();
assertThat(path.startsWith("otherPath")).as("foo").isEqualTo(false);
assertThat(path.startsWith("otherPath")).isNotEqualTo(true);
assertThat(path.startsWith("otherPath")).isFalse();
assertThat(path.endsWith(otherPath)).as("foo").isEqualTo(true);
assertThat(path.endsWith(otherPath)).isNotEqualTo(false);
assertThat(path.endsWith(otherPath)).isTrue();
assertThat(path.endsWith(otherPath)).as("foo").isEqualTo(false);
assertThat(path.endsWith(otherPath)).isNotEqualTo(true);
assertThat(path.endsWith(otherPath)).isFalse();
assertThat(path.endsWith("otherPath")).as("foo").isEqualTo(true);
assertThat(path.endsWith("otherPath")).isNotEqualTo(false);
assertThat(path.endsWith("otherPath")).isTrue();
assertThat(path.endsWith("otherPath")).as("foo").isEqualTo(false);
assertThat(path.endsWith("otherPath")).isNotEqualTo(true);
assertThat(path.endsWith("otherPath")).isFalse();
assertThat(Files.isReadable(path)).as("foo").isEqualTo(true);
assertThat(Files.isReadable(path)).isNotEqualTo(false);
assertThat(Files.isReadable(path)).isTrue();
assertThat(Files.isReadable(path)).as("foo").isEqualTo(false);
assertThat(Files.isReadable(path)).isNotEqualTo(true);
assertThat(Files.isReadable(path)).isFalse();
assertThat(Files.isWritable(path)).as("foo").isEqualTo(true);
assertThat(Files.isWritable(path)).isNotEqualTo(false);
assertThat(Files.isWritable(path)).isTrue();
assertThat(Files.isWritable(path)).as("foo").isEqualTo(false);
assertThat(Files.isWritable(path)).isNotEqualTo(true);
assertThat(Files.isWritable(path)).isFalse();
assertThat(Files.isExecutable(path)).as("foo").isEqualTo(true);
assertThat(Files.isExecutable(path)).isNotEqualTo(false);
assertThat(Files.isExecutable(path)).isTrue();
assertThat(Files.isExecutable(path)).as("foo").isEqualTo(false);
assertThat(Files.isExecutable(path)).isNotEqualTo(true);
assertThat(Files.isExecutable(path)).isFalse();
assertThat(Files.isDirectory(path)).as("foo").isEqualTo(true);
assertThat(Files.isDirectory(path)).isNotEqualTo(false);
assertThat(Files.isDirectory(path)).isTrue();
assertThat(Files.isDirectory(path)).as("foo").isEqualTo(false);
assertThat(Files.isDirectory(path)).isNotEqualTo(true);
assertThat(Files.isDirectory(path)).isFalse();
assertThat(Files.isRegularFile(path)).as("foo").isEqualTo(true);
assertThat(Files.isRegularFile(path)).isNotEqualTo(false);
assertThat(Files.isRegularFile(path)).isTrue();
assertThat(Files.isRegularFile(path)).as("foo").isEqualTo(false);
assertThat(Files.isRegularFile(path)).isNotEqualTo(true);
assertThat(Files.isRegularFile(path)).isFalse();
assertThat(Files.isSymbolicLink(path)).as("foo").isEqualTo(true);
assertThat(Files.isSymbolicLink(path)).isNotEqualTo(false);
assertThat(Files.isSymbolicLink(path)).isTrue();
assertThat(Files.isSymbolicLink(path)).as("foo").isEqualTo(false);
assertThat(Files.isSymbolicLink(path)).isNotEqualTo(true);
assertThat(Files.isSymbolicLink(path)).isFalse();
assertThat(Files.exists(path)).as("foo").isEqualTo(true);
assertThat(Files.exists(path)).isNotEqualTo(false);
assertThat(Files.exists(path)).isTrue();
assertThat(Files.exists(path)).as("foo").isEqualTo(false);
assertThat(Files.exists(path)).isNotEqualTo(true);
assertThat(Files.exists(path)).isFalse();
assertThat(Files.notExists(path)).as("foo").isEqualTo(true);
assertThat(Files.notExists(path)).isNotEqualTo(false);
assertThat(Files.notExists(path)).isTrue();
assertThat(Files.notExists(path)).as("foo").isEqualTo(false);
assertThat(Files.notExists(path)).isNotEqualTo(true);
assertThat(Files.notExists(path)).isFalse();
assertThat(Files.list(path)).isEmpty();
assertThat(Files.list(path)).isNotEmpty();
assertThat(Files.readAllBytes(path)).isEqualTo(new byte[1]);
assertThat(Files.readAllLines(path)).containsExactly("foo");
assertThat(Files.lines(path)).containsExactly("foo");
assertThat(path.getName()).endsWith(".foo"); // could be turned into .hasExtension("foo"), but not always.
assertThat(path.getName()).as("foo").isEqualTo("foo").as("bar").isEqualTo("bar");
org.junit.Assert.assertThat(path, null);
fail("oh no!");
}
}
@@ -26,9 +26,9 @@ public class Size {
assertThat(list).isEmpty();
assertThat(list).hasSameSizeAs(otherList);
assertThat(list).hasSameSizeAs(array);
assertThat(list).hasSize(string.length());
assertThat(list).hasSize(stringBuilder.length());
assertThat(list).hasSameSizeAs(map);
assertThat(list).hasSize(string.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(list).hasSize(stringBuilder.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(list).hasSize(map.size()); // does currently not support hasSameSizeAs() in assertj
assertThat(list).hasSize(1);
assertThat(list).hasSizeGreaterThan(otherList.size() * 2);
assertThat(list).hasSizeGreaterThanOrEqualTo(otherList.size() * 2);
@@ -36,9 +36,9 @@ public class Size {
assertThat(list).hasSizeLessThanOrEqualTo(otherList.size() * 2);
assertThat(list).hasSameSizeAs(otherList);
assertThat(list).hasSameSizeAs(array);
assertThat(list).hasSize(string.length());
assertThat(list).hasSize(stringBuilder.length());
assertThat(list).hasSameSizeAs(map);
assertThat(list).hasSize(string.length()); // currently unsupported in assertj
assertThat(list).hasSize(stringBuilder.length()); // currently unsupported in assertj
assertThat(list).hasSize(map.size()); // currently unsupported in assertj
assertThat(array).isEmpty();
assertThat(array).isEmpty();
@@ -49,9 +49,9 @@ public class Size {
assertThat(array).isEmpty();
assertThat(array).hasSameSizeAs(list);
assertThat(array).hasSameSizeAs(otherArray);
assertThat(array).hasSize(string.length());
assertThat(array).hasSize(stringBuilder.length());
assertThat(array).hasSameSizeAs(map);
assertThat(array).hasSize(string.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(array).hasSize(stringBuilder.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(array).hasSize(map.size()); // does currently not support hasSameSizeAs() in assertj
assertThat(array).hasSize(1);
assertThat(array).hasSizeGreaterThan(otherArray.length - 1);
assertThat(array).hasSizeGreaterThanOrEqualTo(otherArray.length + 1);
@@ -59,9 +59,9 @@ public class Size {
assertThat(array).hasSizeLessThanOrEqualTo(1 - otherArray.length);
assertThat(array).hasSameSizeAs(list);
assertThat(array).hasSameSizeAs(otherArray);
assertThat(array).hasSize(string.length());
assertThat(array).hasSize(stringBuilder.length());
assertThat(array).hasSameSizeAs(map);
assertThat(array).hasSize(string.length()); // currently unsupported in assertj
assertThat(array).hasSize(stringBuilder.length()); // currently unsupported in assertj
assertThat(array).hasSize(map.size()); // currently unsupported in assertj
assertThat(string).isEmpty();
assertThat(string).isEmpty();
@@ -74,7 +74,7 @@ public class Size {
assertThat(string).hasSameSizeAs(array);
assertThat(string).hasSameSizeAs(string);
assertThat(string).hasSameSizeAs(stringBuilder);
assertThat(string).hasSameSizeAs(map);
assertThat(string).hasSize(map.size()); // currently unsupported in assertj
assertThat(string).hasSize(1);
assertThat(string).hasSizeGreaterThan(array.length - 1);
assertThat(string).hasSizeGreaterThanOrEqualTo(array.length + 1);
@@ -84,7 +84,7 @@ public class Size {
assertThat(string).hasSameSizeAs(array);
assertThat(string).hasSameSizeAs(string);
assertThat(string).hasSameSizeAs(stringBuilder);
assertThat(string).hasSameSizeAs(map);
assertThat(string).hasSize(map.size()); // currently unsupported in assertj
assertThat(stringBuilder).isEmpty();
assertThat(stringBuilder).isEmpty();
@@ -97,7 +97,7 @@ public class Size {
assertThat(stringBuilder).hasSameSizeAs(array);
assertThat(stringBuilder).hasSameSizeAs(string);
assertThat(stringBuilder).hasSameSizeAs(stringBuilder);
assertThat(stringBuilder).hasSameSizeAs(map);
assertThat(stringBuilder).hasSize(map.size()); // does currently not support hasSameSizeAs() in assertj
assertThat(stringBuilder).hasSize(1);
assertThat(stringBuilder).hasSizeGreaterThan(array.length - 1);
assertThat(stringBuilder).hasSizeGreaterThanOrEqualTo(array.length + 1);
@@ -107,7 +107,7 @@ public class Size {
assertThat(stringBuilder).hasSameSizeAs(array);
assertThat(stringBuilder).hasSameSizeAs(string);
assertThat(stringBuilder).hasSameSizeAs(stringBuilder);
assertThat(stringBuilder).hasSameSizeAs(map);
assertThat(stringBuilder).hasSize(map.size()); // currently unsupported in assertj
assertThat(map).isEmpty();
assertThat(map).isEmpty();
@@ -118,8 +118,8 @@ public class Size {
assertThat(map).isEmpty();
assertThat(map).hasSameSizeAs(list);
assertThat(map).hasSameSizeAs(array);
assertThat(map).hasSize(string.length());
assertThat(map).hasSize(stringBuilder.length());
assertThat(map).hasSize(string.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(map).hasSize(stringBuilder.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(map).hasSameSizeAs(otherMap);
assertThat(map).hasSize(1);
assertThat(map).hasSizeGreaterThan(array.length - 1);
@@ -128,8 +128,8 @@ public class Size {
assertThat(map).hasSizeLessThanOrEqualTo(1 - array.length);
assertThat(map).hasSameSizeAs(list);
assertThat(map).hasSameSizeAs(array);
assertThat(map).hasSize(string.length());
assertThat(map).hasSize(stringBuilder.length());
assertThat(map).hasSize(string.length()); // currently unsupported in assertj
assertThat(map).hasSize(stringBuilder.length()); // currently unsupported in assertj
assertThat(map).hasSameSizeAs(otherMap);
assertThat(stringBuilder.length()).as("foo").isEqualTo(0).isZero().as("bar").isNotZero().isEqualTo(10);
@@ -26,9 +26,9 @@ public class Size {
assertThat(list.size()).isLessThanOrEqualTo(0);
assertThat(list.size()).isEqualTo(otherList.size());
assertThat(list.size()).isEqualTo(array.length);
assertThat(list.size()).isEqualTo(string.length());
assertThat(list.size()).isEqualTo(stringBuilder.length());
assertThat(list.size()).isEqualTo(map.size());
assertThat(list.size()).isEqualTo(string.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(list.size()).isEqualTo(stringBuilder.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(list.size()).isEqualTo(map.size()); // does currently not support hasSameSizeAs() in assertj
assertThat(list.size()).isEqualTo(1);
assertThat(list.size()).isGreaterThan(otherList.size() * 2);
assertThat(list.size()).isGreaterThanOrEqualTo(otherList.size() * 2);
@@ -36,9 +36,9 @@ public class Size {
assertThat(list.size()).isLessThanOrEqualTo(otherList.size() * 2);
assertThat(list).hasSize(otherList.size());
assertThat(list).hasSize(array.length);
assertThat(list).hasSize(string.length());
assertThat(list).hasSize(stringBuilder.length());
assertThat(list).hasSize(map.size());
assertThat(list).hasSize(string.length()); // currently unsupported in assertj
assertThat(list).hasSize(stringBuilder.length()); // currently unsupported in assertj
assertThat(list).hasSize(map.size()); // currently unsupported in assertj
assertThat(array.length).isEqualTo(0);
assertThat(array.length).isZero();
@@ -49,9 +49,9 @@ public class Size {
assertThat(array.length).isLessThanOrEqualTo(0);
assertThat(array.length).isEqualTo(list.size());
assertThat(array.length).isEqualTo(otherArray.length);
assertThat(array.length).isEqualTo(string.length());
assertThat(array.length).isEqualTo(stringBuilder.length());
assertThat(array.length).isEqualTo(map.size());
assertThat(array.length).isEqualTo(string.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(array.length).isEqualTo(stringBuilder.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(array.length).isEqualTo(map.size()); // does currently not support hasSameSizeAs() in assertj
assertThat(array.length).isEqualTo(1);
assertThat(array.length).isGreaterThan(otherArray.length - 1);
assertThat(array.length).isGreaterThanOrEqualTo(otherArray.length + 1);
@@ -59,9 +59,9 @@ public class Size {
assertThat(array.length).isLessThanOrEqualTo(1 - otherArray.length);
assertThat(array).hasSize(list.size());
assertThat(array).hasSize(otherArray.length);
assertThat(array).hasSize(string.length());
assertThat(array).hasSize(stringBuilder.length());
assertThat(array).hasSize(map.size());
assertThat(array).hasSize(string.length()); // currently unsupported in assertj
assertThat(array).hasSize(stringBuilder.length()); // currently unsupported in assertj
assertThat(array).hasSize(map.size()); // currently unsupported in assertj
assertThat(string.length()).isEqualTo(0);
assertThat(string.length()).isZero();
@@ -74,7 +74,7 @@ public class Size {
assertThat(string.length()).isEqualTo(array.length);
assertThat(string.length()).isEqualTo(string.length());
assertThat(string.length()).isEqualTo(stringBuilder.length());
assertThat(string.length()).isEqualTo(map.size());
assertThat(string.length()).isEqualTo(map.size()); // currently unsupported in assertj
assertThat(string.length()).isEqualTo(1);
assertThat(string.length()).isGreaterThan(array.length - 1);
assertThat(string.length()).isGreaterThanOrEqualTo(array.length + 1);
@@ -84,7 +84,7 @@ public class Size {
assertThat(string).hasSize(array.length);
assertThat(string).hasSize(string.length());
assertThat(string).hasSize(stringBuilder.length());
assertThat(string).hasSize(map.size());
assertThat(string).hasSize(map.size()); // currently unsupported in assertj
assertThat(stringBuilder.length()).isEqualTo(0);
assertThat(stringBuilder.length()).isZero();
@@ -97,7 +97,7 @@ public class Size {
assertThat(stringBuilder.length()).isEqualTo(array.length);
assertThat(stringBuilder.length()).isEqualTo(string.length());
assertThat(stringBuilder.length()).isEqualTo(stringBuilder.length());
assertThat(stringBuilder.length()).isEqualTo(map.size());
assertThat(stringBuilder.length()).isEqualTo(map.size()); // does currently not support hasSameSizeAs() in assertj
assertThat(stringBuilder.length()).isEqualTo(1);
assertThat(stringBuilder.length()).isGreaterThan(array.length - 1);
assertThat(stringBuilder.length()).isGreaterThanOrEqualTo(array.length + 1);
@@ -107,7 +107,7 @@ public class Size {
assertThat(stringBuilder).hasSize(array.length);
assertThat(stringBuilder).hasSize(string.length());
assertThat(stringBuilder).hasSize(stringBuilder.length());
assertThat(stringBuilder).hasSize(map.size());
assertThat(stringBuilder).hasSize(map.size()); // currently unsupported in assertj
assertThat(map.size()).isEqualTo(0);
assertThat(map.size()).isZero();
@@ -118,8 +118,8 @@ public class Size {
assertThat(map.size()).isLessThanOrEqualTo(0);
assertThat(map.size()).isEqualTo(list.size());
assertThat(map.size()).isEqualTo(array.length);
assertThat(map.size()).isEqualTo(string.length());
assertThat(map.size()).isEqualTo(stringBuilder.length());
assertThat(map.size()).isEqualTo(string.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(map.size()).isEqualTo(stringBuilder.length()); // does currently not support hasSameSizeAs() in assertj
assertThat(map.size()).isEqualTo(otherMap.size());
assertThat(map.size()).isEqualTo(1);
assertThat(map.size()).isGreaterThan(array.length - 1);
@@ -128,8 +128,8 @@ public class Size {
assertThat(map.size()).isLessThanOrEqualTo(1 - array.length);
assertThat(map).hasSize(list.size());
assertThat(map).hasSize(array.length);
assertThat(map).hasSize(string.length());
assertThat(map).hasSize(stringBuilder.length());
assertThat(map).hasSize(string.length()); // currently unsupported in assertj
assertThat(map).hasSize(stringBuilder.length()); // currently unsupported in assertj
assertThat(map).hasSize(otherMap.size());
assertThat(stringBuilder.length()).as("foo").isEqualTo(0).isZero().as("bar").isNotZero().isEqualTo(10);
@@ -26,6 +26,8 @@ public class StringExpression {
assertThat(string).startsWith("foo");
assertThat(string).endsWith("foo");
assertThat(string).endsWith("foo");
assertThat(string).matches("foo");
assertThat(string).matches("foo");
assertThat(string).as("foo").isNotEmpty();
assertThat(string).isNotEmpty();
@@ -46,11 +48,43 @@ public class StringExpression {
assertThat(string).doesNotStartWith("foo");
assertThat(string).doesNotEndWith("foo");
assertThat(string).doesNotEndWith("foo");
assertThat(string).doesNotMatch("foo");
assertThat(string).doesNotMatch("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();
assertThat(string).isEqualToIgnoringCase("foo");
assertThat(string).isEqualToIgnoringCase("foo");
assertThat(string.compareToIgnoreCase("foo")).isEqualTo(1);
assertThat(string.compareToIgnoreCase("foo")).isLessThan(0);
assertThat(string).isNotEqualToIgnoringCase("foo");
assertThat(string).isNotEqualToIgnoringCase("foo");
assertThat(string.compareToIgnoreCase("foo")).isNotEqualTo(1);
assertThat(string.compareToIgnoreCase("foo")).isGreaterThan(0);
assertThat(string).startsWith("foo");
assertThat(string).doesNotStartWith("foo");
assertThat(string).startsWith("foo");
assertThat(string.indexOf("foo")).isEqualTo(1);
assertThat(string).doesNotContain("foo");
assertThat(string).doesNotStartWith("foo");
assertThat(string.indexOf("foo")).isNotEqualTo(1);
assertThat(string).contains("foo");
assertThat(string).doesNotContain("foo");
assertThat(string).doesNotContain("foo");
assertThat(string).contains("foo");
assertThat(string).contains("foo");
assertThat(string).doesNotContain("foo");
assertThat(string.indexOf("foo")).isPositive();
assertThat(string).contains("foo");
assertThat(string.indexOf("foo")).isNotPositive();
assertThat(string.trim()).isEmpty(); // would turn into isJavaBlank(), which is deprecated. Should be isNotNull().isBlank() then...
assertThat(string).isNotBlank();
org.junit.Assert.assertThat(string, null);
fail("oh no!");
}
@@ -26,6 +26,8 @@ public class StringExpression {
assertThat(string.startsWith("foo")).isTrue();
assertThat(string.endsWith("foo")).isEqualTo(true);
assertThat(string.endsWith("foo")).isTrue();
assertThat(string.matches("foo")).isEqualTo(true);
assertThat(string.matches("foo")).isTrue();
assertThat(string.isEmpty()).as("foo").isEqualTo(false);
assertThat(string.isEmpty()).isNotEqualTo(true);
@@ -46,11 +48,43 @@ public class StringExpression {
assertThat(string.startsWith("foo")).isFalse();
assertThat(string.endsWith("foo")).isEqualTo(false);
assertThat(string.endsWith("foo")).isFalse();
assertThat(string.matches("foo")).isEqualTo(false);
assertThat(string.matches("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();
assertThat(string.compareToIgnoreCase("foo")).isEqualTo(0);
assertThat(string.compareToIgnoreCase("foo")).isZero();
assertThat(string.compareToIgnoreCase("foo")).isEqualTo(1);
assertThat(string.compareToIgnoreCase("foo")).isLessThan(0);
assertThat(string.compareToIgnoreCase("foo")).isNotEqualTo(0);
assertThat(string.compareToIgnoreCase("foo")).isNotZero();
assertThat(string.compareToIgnoreCase("foo")).isNotEqualTo(1);
assertThat(string.compareToIgnoreCase("foo")).isGreaterThan(0);
assertThat(string.indexOf("foo")).isZero();
assertThat(string.indexOf("foo")).isNotZero();
assertThat(string.indexOf("foo")).isEqualTo(0);
assertThat(string.indexOf("foo")).isEqualTo(1);
assertThat(string.indexOf("foo")).isEqualTo(-1);
assertThat(string.indexOf("foo")).isNotEqualTo(0);
assertThat(string.indexOf("foo")).isNotEqualTo(1);
assertThat(string.indexOf("foo")).isNotEqualTo(-1);
assertThat(string.indexOf("foo")).isLessThan(0);
assertThat(string.indexOf("foo")).isLessThanOrEqualTo(-1);
assertThat(string.indexOf("foo")).isGreaterThan(-1);
assertThat(string.indexOf("foo")).isGreaterThanOrEqualTo(0);
assertThat(string.indexOf("foo")).isNegative();
assertThat(string.indexOf("foo")).isPositive();
assertThat(string.indexOf("foo")).isNotNegative();
assertThat(string.indexOf("foo")).isNotPositive();
assertThat(string.trim()).isEmpty(); // would turn into isJavaBlank(), which is deprecated. Should be isNotNull().isBlank() then...
assertThat(string.trim()).isNotEmpty();
org.junit.Assert.assertThat(string, null);
fail("oh no!");
}
@@ -0,0 +1,50 @@
import java.util.*;
import java.util.regex.Pattern;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class TwistedAssertions {
private static final int SOME_CONST = 10;
private static final String SOME_CONST_STRING = "bar";
private void twistedAssertions() {
List<String> list = new ArrayList<>();
String foo = "foo";
String bar = "bar";
int number = 4;
assertThat(number).as("foo").isEqualTo(5 + 2);
assertThat(number).as("foo").isNotEqualTo(8);
assertThat(number).as("foo").isLessThanOrEqualTo(5 * 2);
assertThat(number + 1).as("foo").isLessThan(4 + (1 - 2));
assertThat(number * 2).as("foo").isGreaterThanOrEqualTo(3);
assertThat(number / 2).as("foo").isGreaterThan(2 + SOME_CONST);
assertThat(foo).as("foo").isEqualTo("foo");
assertThat(foo).as("foo").isSameAs(SOME_CONST_STRING);
assertThat(foo).as("foo").isNotEqualTo("bar");
assertThat(foo).as("foo").isNotSameAs("bar");
assertThat("bar").as("foo").startsWith(foo);
assertThat("foo").as("foo").endsWith(foo);
assertThat(bar).isEqualTo(foo);
assertThat(4).isEqualTo(number).isNotEqualTo(number * 2);
assertThat(4).usingDefaultComparator().isGreaterThanOrEqualTo(number);
assertThat(4).usingRecursiveComparison().isGreaterThanOrEqualTo(number);
assertThat(4).usingComparator(Comparator.reverseOrder()).isGreaterThanOrEqualTo(number);
assertThat(4).usingComparatorForFields().isGreaterThanOrEqualTo(number);
assertThat(4).usingComparatorForType(Integer::compare).isGreaterThanOrEqualTo(number);
assertThat(String.class).isEqualTo(Class.forName("java.lang.String"));
assertThat("XX").matches(Pattern.compile(".."));
assertThat("XX").matches(".."));
assertThat("XX").doesNotMatch(Pattern.compile(".."));
assertThat("XX").doesNotMatch(".."));
assertThat(SOME_CONST).isEqualTo(10);
org.junit.Assert.assertThat(list, null);
fail("oh no!");
}
}
@@ -0,0 +1,50 @@
import java.util.*;
import java.util.regex.Pattern;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class TwistedAssertions {
private static final int SOME_CONST = 10;
private static final String SOME_CONST_STRING = "bar";
private void twistedAssertions() {
List<String> list = new ArrayList<>();
String foo = "foo";
String bar = "bar";
int number = 4;
assertThat(5 + 2).as("foo").isEqualTo(number);
assertThat(8).as("foo").isNotEqualTo(number);
assertThat(5 * 2).as("foo").isGreaterThan(number);
assertThat(4 + (1 - 2)).as("foo").isGreaterThanOrEqualTo(number + 1);
assertThat(3).as("foo").isLessThan(number * 2);
assertThat(2 + SOME_CONST).as("foo").isLessThanOrEqualTo(number / 2);
assertThat("foo").as("foo").isEqualTo(foo);
assertThat(SOME_CONST_STRING).as("foo").isSameAs(foo);
assertThat("bar").as("foo").isNotEqualTo(foo);
assertThat("bar").as("foo").isNotSameAs(foo);
assertThat("bar").as("foo").startsWith(foo);
assertThat("foo").as("foo").endsWith(foo);
assertThat(bar).isEqualTo(foo);
assertThat(4).isEqualTo(number).isNotEqualTo(number * 2);
assertThat(4).usingDefaultComparator().isGreaterThanOrEqualTo(number);
assertThat(4).usingRecursiveComparison().isGreaterThanOrEqualTo(number);
assertThat(4).usingComparator(Comparator.reverseOrder()).isGreaterThanOrEqualTo(number);
assertThat(4).usingComparatorForFields().isGreaterThanOrEqualTo(number);
assertThat(4).usingComparatorForType(Integer::compare).isGreaterThanOrEqualTo(number);
assertThat(String.class).isEqualTo(Class.forName("java.lang.String"));
assertThat("XX").matches(Pattern.compile(".."));
assertThat("XX").matches(".."));
assertThat("XX").doesNotMatch(Pattern.compile(".."));
assertThat("XX").doesNotMatch(".."));
assertThat(SOME_CONST).isEqualTo(10);
org.junit.Assert.assertThat(list, null);
fail("oh no!");
}
}