mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Compare commits
13 Commits
v0.18.0
...
sschroever
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd9c248777 | ||
|
|
9954663bd5 | ||
|
|
f6e9dbb996 | ||
|
|
260021c961 | ||
|
|
ec54e79f3e | ||
|
|
4cbfdba521 | ||
|
|
d94f65a1f0 | ||
|
|
9afdf2ddf3 | ||
|
|
060c901479 | ||
|
|
1feee4f64a | ||
|
|
552ddf6a7d | ||
|
|
5d92c6c6ce | ||
|
|
fa8ca80040 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
||||
with:
|
||||
java-version: ${{ matrix.jdk }}
|
||||
java-distribution: ${{ matrix.distribution }}
|
||||
maven-version: 3.9.6
|
||||
maven-version: 3.9.8
|
||||
- name: Display build environment details
|
||||
run: mvn --version
|
||||
- name: Build project against vanilla Error Prone, compile Javadoc
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
with:
|
||||
java-version: 17.0.10
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.6
|
||||
maven-version: 3.9.8
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
with:
|
||||
|
||||
2
.github/workflows/pitest-analyze-pr.yml
vendored
2
.github/workflows/pitest-analyze-pr.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
checkout-fetch-depth: 2
|
||||
java-version: 17.0.10
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.6
|
||||
maven-version: 3.9.8
|
||||
- name: Run Pitest
|
||||
# By running with features `+GIT(from[HEAD~1]), +gitci`, Pitest only
|
||||
# analyzes lines changed in the associated pull request, as GitHub
|
||||
|
||||
2
.github/workflows/pitest-update-pr.yml
vendored
2
.github/workflows/pitest-update-pr.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
with:
|
||||
java-version: 17.0.10
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.6
|
||||
maven-version: 3.9.8
|
||||
- name: Download Pitest analysis artifact
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4
|
||||
with:
|
||||
|
||||
2
.github/workflows/run-integration-tests.yml
vendored
2
.github/workflows/run-integration-tests.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
|
||||
java-version: 17.0.10
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.6
|
||||
maven-version: 3.9.8
|
||||
- name: Install project to local Maven repository
|
||||
run: mvn -T1C install -DskipTests -Dverification.skip
|
||||
- name: Run integration test
|
||||
|
||||
2
.github/workflows/sonarcloud.yml
vendored
2
.github/workflows/sonarcloud.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
checkout-fetch-depth: 0
|
||||
java-version: 17.0.10
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.6
|
||||
maven-version: 3.9.8
|
||||
- name: Create missing `test` directory
|
||||
# XXX: Drop this step in favour of actually having a test.
|
||||
run: mkdir refaster-compiler/src/test
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>documentation-support</artifactId>
|
||||
|
||||
@@ -14,7 +14,6 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ServiceLoader;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
@@ -87,6 +86,6 @@ final class DocumentationGeneratorTaskListener implements TaskListener {
|
||||
}
|
||||
|
||||
private static String getSimpleClassName(URI path) {
|
||||
return Paths.get(path).getFileName().toString().replace(".java", "");
|
||||
return Path.of(path).getFileName().toString().replace(".java", "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
|
||||
@@ -51,6 +51,7 @@ import tech.picnic.errorprone.utils.SourceCode;
|
||||
// is effectively the identity operation.
|
||||
// XXX: Also flag nullary instance method invocations that represent an identity conversion, such as
|
||||
// `Boolean#booleanValue()`, `Byte#byteValue()` and friends.
|
||||
// XXX: Also flag redundant round-trip conversions such as `path.toFile().toPath()`.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Avoid or clarify identity conversions",
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
@@ -247,14 +248,46 @@ final class ComparatorRules {
|
||||
* Avoid unnecessary creation of a {@link Stream} to determine the minimum of a known collection
|
||||
* of values.
|
||||
*/
|
||||
static final class MinOfVarargs<T> {
|
||||
static final class MinOfArray<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
T before(@Repeated T value, Comparator<T> cmp) {
|
||||
T before(T[] array, Comparator<S> cmp) {
|
||||
return Arrays.stream(array).min(cmp).orElseThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
T after(T[] array, Comparator<S> cmp) {
|
||||
return Collections.min(Arrays.asList(array), cmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid unnecessary creation of a {@link Stream} to determine the minimum of a known collection
|
||||
* of values.
|
||||
*/
|
||||
static final class MinOfCollection<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
T before(Collection<T> collection, Comparator<S> cmp) {
|
||||
return collection.stream().min(cmp).orElseThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
T after(Collection<T> collection, Comparator<S> cmp) {
|
||||
return Collections.min(collection, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid unnecessary creation of a {@link Stream} to determine the minimum of a known collection
|
||||
* of values.
|
||||
*/
|
||||
static final class MinOfVarargs<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
T before(@Repeated T value, Comparator<S> cmp) {
|
||||
return Stream.of(Refaster.asVarargs(value)).min(cmp).orElseThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
T after(@Repeated T value, Comparator<T> cmp) {
|
||||
T after(@Repeated T value, Comparator<S> cmp) {
|
||||
return Collections.min(Arrays.asList(value), cmp);
|
||||
}
|
||||
}
|
||||
@@ -314,14 +347,46 @@ final class ComparatorRules {
|
||||
* Avoid unnecessary creation of a {@link Stream} to determine the maximum of a known collection
|
||||
* of values.
|
||||
*/
|
||||
static final class MaxOfVarargs<T> {
|
||||
static final class MaxOfArray<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
T before(@Repeated T value, Comparator<T> cmp) {
|
||||
T before(T[] array, Comparator<S> cmp) {
|
||||
return Arrays.stream(array).max(cmp).orElseThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
T after(T[] array, Comparator<S> cmp) {
|
||||
return Collections.max(Arrays.asList(array), cmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid unnecessary creation of a {@link Stream} to determine the maximum of a known collection
|
||||
* of values.
|
||||
*/
|
||||
static final class MaxOfCollection<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
T before(Collection<T> collection, Comparator<S> cmp) {
|
||||
return collection.stream().max(cmp).orElseThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
T after(Collection<T> collection, Comparator<S> cmp) {
|
||||
return Collections.max(collection, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid unnecessary creation of a {@link Stream} to determine the maximum of a known collection
|
||||
* of values.
|
||||
*/
|
||||
static final class MaxOfVarargs<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
T before(@Repeated T value, Comparator<S> cmp) {
|
||||
return Stream.of(Refaster.asVarargs(value)).max(cmp).orElseThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
T after(@Repeated T value, Comparator<T> cmp) {
|
||||
T after(@Repeated T value, Comparator<S> cmp) {
|
||||
return Collections.max(Arrays.asList(value), cmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,14 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@@ -18,6 +21,49 @@ import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
final class FileRules {
|
||||
private FileRules() {}
|
||||
|
||||
/** Prefer the more idiomatic {@link Path#of(URI)} over {@link Paths#get(URI)}. */
|
||||
static final class PathOfUri {
|
||||
@BeforeTemplate
|
||||
Path before(URI uri) {
|
||||
return Paths.get(uri);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Path after(URI uri) {
|
||||
return Path.of(uri);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer the more idiomatic {@link Path#of(String, String...)} over {@link Paths#get(String,
|
||||
* String...)}.
|
||||
*/
|
||||
static final class PathOfString {
|
||||
@BeforeTemplate
|
||||
Path before(String first, @Repeated String more) {
|
||||
return Paths.get(first, more);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Path after(String first, @Repeated String more) {
|
||||
return Path.of(first, more);
|
||||
}
|
||||
}
|
||||
|
||||
/** Avoid redundant conversions from {@link Path} to {@link File}. */
|
||||
// XXX: Review whether a rule such as this one is better handled by the `IdentityConversion` rule.
|
||||
static final class PathInstance {
|
||||
@BeforeTemplate
|
||||
Path before(Path path) {
|
||||
return path.toFile().toPath();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Path after(Path path) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Files#readString(Path, Charset)} over more contrived alternatives. */
|
||||
static final class FilesReadStringWithCharset {
|
||||
@BeforeTemplate
|
||||
@@ -50,7 +96,11 @@ final class FileRules {
|
||||
*/
|
||||
static final class FilesCreateTempFileToFile {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S5443" /* This violation will be rewritten. */)
|
||||
@SuppressWarnings({
|
||||
"FilesCreateTempFileInCustomDirectoryToFile" /* This is a more specific template. */,
|
||||
"java:S5443" /* This violation will be rewritten. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
File before(String prefix, String suffix) throws IOException {
|
||||
return Refaster.anyOf(
|
||||
File.createTempFile(prefix, suffix), File.createTempFile(prefix, suffix, null));
|
||||
@@ -63,4 +113,20 @@ final class FileRules {
|
||||
return Files.createTempFile(prefix, suffix).toFile();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link Files#createTempFile(Path, String, String, FileAttribute[])} over alternatives
|
||||
* that create files with more liberal permissions.
|
||||
*/
|
||||
static final class FilesCreateTempFileInCustomDirectoryToFile {
|
||||
@BeforeTemplate
|
||||
File before(File directory, String prefix, String suffix) throws IOException {
|
||||
return File.createTempFile(prefix, suffix, directory);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
File after(File directory, String prefix, String suffix) throws IOException {
|
||||
return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
@@ -11,6 +12,10 @@ import com.google.errorprone.refaster.annotation.MayOptionallyUse;
|
||||
import com.google.errorprone.refaster.annotation.NotMatches;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
@@ -27,6 +32,23 @@ import tech.picnic.errorprone.refaster.matchers.IsLikelyTrivialComputation;
|
||||
final class OptionalRules {
|
||||
private OptionalRules() {}
|
||||
|
||||
// XXX: Move or drop.
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface BeforeExample {}
|
||||
|
||||
// XXX: Move or drop.
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface AfterExample {}
|
||||
|
||||
// XXX: Move or drop.
|
||||
interface RefasterExpressionExamples<T> {
|
||||
ImmutableList<T> before();
|
||||
|
||||
ImmutableList<T> after();
|
||||
}
|
||||
|
||||
/** Prefer {@link Optional#empty()} over the more contrived alternative. */
|
||||
static final class OptionalEmpty<T> {
|
||||
@BeforeTemplate
|
||||
@@ -53,6 +75,40 @@ final class OptionalRules {
|
||||
Optional<T> after(T object) {
|
||||
return Optional.ofNullable(object);
|
||||
}
|
||||
|
||||
@BeforeExample
|
||||
@SuppressWarnings({
|
||||
"TernaryOperatorOptionalNegativeFiltering",
|
||||
"TernaryOperatorOptionalPositiveFiltering"
|
||||
} /* Special cases. */)
|
||||
ImmutableList<Optional<String>> input() {
|
||||
return ImmutableList.of(
|
||||
toString() == null ? Optional.empty() : Optional.of(toString()),
|
||||
toString() != null ? Optional.of(toString()) : Optional.empty());
|
||||
}
|
||||
|
||||
@AfterExample
|
||||
ImmutableList<Optional<String>> output() {
|
||||
return ImmutableList.of(Optional.ofNullable(toString()), Optional.ofNullable(toString()));
|
||||
}
|
||||
|
||||
static final class Examples implements RefasterExpressionExamples<Optional<String>> {
|
||||
@Override
|
||||
@SuppressWarnings({
|
||||
"TernaryOperatorOptionalNegativeFiltering",
|
||||
"TernaryOperatorOptionalPositiveFiltering"
|
||||
} /* Special cases. */)
|
||||
public ImmutableList<Optional<String>> before() {
|
||||
return ImmutableList.of(
|
||||
toString() == null ? Optional.empty() : Optional.of(toString()),
|
||||
toString() != null ? Optional.of(toString()) : Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<Optional<String>> after() {
|
||||
return ImmutableList.of(Optional.ofNullable(toString()), Optional.ofNullable(toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Optional#isEmpty()} over the more verbose alternative. */
|
||||
@@ -66,6 +122,16 @@ final class OptionalRules {
|
||||
boolean after(Optional<T> optional) {
|
||||
return optional.isEmpty();
|
||||
}
|
||||
|
||||
@BeforeExample
|
||||
ImmutableList<Boolean> input() {
|
||||
return ImmutableList.of(!Optional.empty().isPresent(), !Optional.of("foo").isPresent());
|
||||
}
|
||||
|
||||
@AfterExample
|
||||
ImmutableList<Boolean> output() {
|
||||
return ImmutableList.of(Optional.empty().isEmpty(), Optional.of("foo").isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Optional#isPresent()} over the inverted alternative. */
|
||||
@@ -79,6 +145,16 @@ final class OptionalRules {
|
||||
boolean after(Optional<T> optional) {
|
||||
return optional.isPresent();
|
||||
}
|
||||
|
||||
@BeforeExample
|
||||
ImmutableList<Boolean> input() {
|
||||
return ImmutableList.of(!Optional.empty().isEmpty(), !Optional.of("foo").isEmpty());
|
||||
}
|
||||
|
||||
@AfterExample
|
||||
ImmutableList<Boolean> output() {
|
||||
return ImmutableList.of(Optional.empty().isPresent(), Optional.of("foo").isPresent());
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Optional#orElseThrow()} over the less explicit {@link Optional#get()}. */
|
||||
|
||||
@@ -107,6 +107,14 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Comparator.<String>reverseOrder().compare("baz", "qux"));
|
||||
}
|
||||
|
||||
String testMinOfArray() {
|
||||
return Arrays.stream(new String[0]).min(naturalOrder()).orElseThrow();
|
||||
}
|
||||
|
||||
String testMinOfCollection() {
|
||||
return ImmutableSet.of("foo", "bar").stream().min(naturalOrder()).orElseThrow();
|
||||
}
|
||||
|
||||
int testMinOfVarargs() {
|
||||
return Stream.of(1, 2).min(naturalOrder()).orElseThrow();
|
||||
}
|
||||
@@ -135,6 +143,14 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Collections.min(ImmutableSet.of("a", "b"), (a, b) -> 1));
|
||||
}
|
||||
|
||||
String testMaxOfArray() {
|
||||
return Arrays.stream(new String[0]).max(naturalOrder()).orElseThrow();
|
||||
}
|
||||
|
||||
String testMaxOfCollection() {
|
||||
return ImmutableSet.of("foo", "bar").stream().max(naturalOrder()).orElseThrow();
|
||||
}
|
||||
|
||||
int testMaxOfVarargs() {
|
||||
return Stream.of(1, 2).max(naturalOrder()).orElseThrow();
|
||||
}
|
||||
|
||||
@@ -98,6 +98,14 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableSet.of("foo".compareTo("bar"), "qux".compareTo("baz"));
|
||||
}
|
||||
|
||||
String testMinOfArray() {
|
||||
return Collections.min(Arrays.asList(new String[0]), naturalOrder());
|
||||
}
|
||||
|
||||
String testMinOfCollection() {
|
||||
return Collections.min(ImmutableSet.of("foo", "bar"), naturalOrder());
|
||||
}
|
||||
|
||||
int testMinOfVarargs() {
|
||||
return Collections.min(Arrays.asList(1, 2), naturalOrder());
|
||||
}
|
||||
@@ -126,6 +134,14 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Comparators.min("a", "b", (a, b) -> 1));
|
||||
}
|
||||
|
||||
String testMaxOfArray() {
|
||||
return Collections.max(Arrays.asList(new String[0]), naturalOrder());
|
||||
}
|
||||
|
||||
String testMaxOfCollection() {
|
||||
return Collections.max(ImmutableSet.of("foo", "bar"), naturalOrder());
|
||||
}
|
||||
|
||||
int testMaxOfVarargs() {
|
||||
return Collections.max(Arrays.asList(1, 2), naturalOrder());
|
||||
}
|
||||
|
||||
@@ -3,12 +3,26 @@ package tech.picnic.errorprone.refasterrules;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Path testPathOfUri() {
|
||||
return Paths.get(URI.create("foo"));
|
||||
}
|
||||
|
||||
ImmutableSet<Path> testPathOfString() {
|
||||
return ImmutableSet.of(Paths.get("foo"), Paths.get("bar", "baz", "qux"));
|
||||
}
|
||||
|
||||
Path testPathInstance() {
|
||||
return Path.of("foo").toFile().toPath();
|
||||
}
|
||||
|
||||
String testFilesReadStringWithCharset() throws IOException {
|
||||
return new String(Files.readAllBytes(Paths.get("foo")), StandardCharsets.ISO_8859_1);
|
||||
}
|
||||
@@ -21,4 +35,8 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableSet.of(
|
||||
File.createTempFile("foo", "bar"), File.createTempFile("baz", "qux", null));
|
||||
}
|
||||
|
||||
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
|
||||
return File.createTempFile("foo", "bar", new File("baz"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,26 @@ package tech.picnic.errorprone.refasterrules;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Path testPathOfUri() {
|
||||
return Path.of(URI.create("foo"));
|
||||
}
|
||||
|
||||
ImmutableSet<Path> testPathOfString() {
|
||||
return ImmutableSet.of(Path.of("foo"), Path.of("bar", "baz", "qux"));
|
||||
}
|
||||
|
||||
Path testPathInstance() {
|
||||
return Path.of("foo");
|
||||
}
|
||||
|
||||
String testFilesReadStringWithCharset() throws IOException {
|
||||
return Files.readString(Paths.get("foo"), StandardCharsets.ISO_8859_1);
|
||||
}
|
||||
@@ -21,4 +35,8 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableSet.of(
|
||||
Files.createTempFile("foo", "bar").toFile(), Files.createTempFile("baz", "qux").toFile());
|
||||
}
|
||||
|
||||
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
|
||||
return Files.createTempFile(new File("baz").toPath(), "foo", "bar").toFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-experimental</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-guidelines</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-utils</artifactId>
|
||||
|
||||
20
pom.xml
20
pom.xml
@@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Picnic :: Error Prone Support</name>
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
<scm child.scm.developerConnection.inherit.append.path="false" child.scm.url.inherit.append.path="false">
|
||||
<developerConnection>scm:git:git@github.com:PicnicSupermarket/error-prone-support.git</developerConnection>
|
||||
<tag>v0.18.0</tag>
|
||||
<tag>HEAD</tag>
|
||||
<url>https://github.com/PicnicSupermarket/error-prone-support</url>
|
||||
</scm>
|
||||
<issueManagement>
|
||||
@@ -148,7 +148,7 @@
|
||||
<groupId.error-prone>com.google.errorprone</groupId.error-prone>
|
||||
<!-- The build timestamp is derived from the most recent commit
|
||||
timestamp in support of reproducible builds. -->
|
||||
<project.build.outputTimestamp>2024-08-11T13:04:41Z</project.build.outputTimestamp>
|
||||
<project.build.outputTimestamp>2024-08-11T13:05:54Z</project.build.outputTimestamp>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- Glob pattern identifying Refaster rule definition files. These
|
||||
Java classes don't contain "regular" code, and thus require special
|
||||
@@ -212,12 +212,12 @@
|
||||
<version.error-prone-slf4j>0.1.25</version.error-prone-slf4j>
|
||||
<version.guava-beta-checker>1.0</version.guava-beta-checker>
|
||||
<version.jdk>17</version.jdk>
|
||||
<version.maven>3.9.5</version.maven>
|
||||
<version.maven>3.9.8</version.maven>
|
||||
<version.mockito>5.12.0</version.mockito>
|
||||
<version.nopen-checker>1.0.1</version.nopen-checker>
|
||||
<version.nullaway>0.11.1</version.nullaway>
|
||||
<version.nullaway>0.11.2</version.nullaway>
|
||||
<version.pitest-git>1.1.4</version.pitest-git>
|
||||
<version.rewrite-templating>1.12.3</version.rewrite-templating>
|
||||
<version.rewrite-templating>1.13.0</version.rewrite-templating>
|
||||
<version.surefire>3.2.3</version.surefire>
|
||||
</properties>
|
||||
|
||||
@@ -360,7 +360,7 @@
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
<version>2023.0.8</version>
|
||||
<version>2023.0.9</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -412,7 +412,7 @@
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.14.18</version>
|
||||
<version>1.14.19</version>
|
||||
</dependency>
|
||||
<!-- Specified so that Renovate will file Maven upgrade PRs, which
|
||||
subsequently will cause `maven-enforcer-plugin` to require that
|
||||
@@ -457,7 +457,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.10.3</version>
|
||||
<version>5.11.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -1109,7 +1109,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<version>3.2.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-compiler</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-runner</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-support</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.18.0</version>
|
||||
<version>0.18.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-test-support</artifactId>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
|
||||
// XXX: Drop these annotations.
|
||||
@Disabled
|
||||
@SuppressWarnings("all")
|
||||
abstract class MyAbstractTest {
|
||||
@TestFactory
|
||||
Stream<DynamicTest> dynamicTests() {
|
||||
MatchInWrongMethodRules.class.getDeclaredClasses();
|
||||
|
||||
return Stream.of(
|
||||
DynamicTest.dynamicTest("A " + getClass(), () -> {}),
|
||||
DynamicTest.dynamicTest("A", () -> {}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.Extension;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.TestInstanceFactory;
|
||||
import org.junit.jupiter.api.extension.TestInstanceFactoryContext;
|
||||
import org.junit.jupiter.api.extension.TestInstantiationException;
|
||||
|
||||
// XXX: Drop these annotations.
|
||||
@Disabled
|
||||
@SuppressWarnings("all")
|
||||
public class MyTest extends MyAbstractTest {
|
||||
public static final class MyTestInstanceFactory implements TestInstanceFactory {
|
||||
@Override
|
||||
public Object createTestInstance(
|
||||
TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext)
|
||||
throws TestInstantiationException {
|
||||
return new MySubTest();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Name
|
||||
@Test
|
||||
void foo() {
|
||||
// Options:
|
||||
// 1. Add examples to the Refaster rule, generate the tests from those
|
||||
//
|
||||
// 2. Define as test, and use a custom test annotation, which:
|
||||
// - Generates the relevant test resources
|
||||
// - Executes them.
|
||||
// ^ Might be nicer to generate a subclass and use a `TestInstanceFactory` to instantiate that.
|
||||
// XXX: That turns out not to work.
|
||||
//
|
||||
// ^ Other option: provide super class that declares a `TestFactory` based on the subclass name.
|
||||
|
||||
}
|
||||
|
||||
// Extensions can be defined at any level. TBD how useful.
|
||||
// static final class MyExtension implements Extension, {
|
||||
//
|
||||
// }
|
||||
// @ExtendWith(MyExtension.class)
|
||||
|
||||
static class MySubTest extends MyTest {}
|
||||
|
||||
@TestFactory
|
||||
Stream<DynamicTest> dynamicTestsFromStreamInJava8() {
|
||||
|
||||
Function<String, String> resolver = s -> s;
|
||||
|
||||
List<String> domainNames =
|
||||
Arrays.asList("www.somedomain.com", "www.anotherdomain.com", "www.yetanotherdomain.com");
|
||||
List<String> outputList = Arrays.asList("154.174.10.56", "211.152.104.132", "178.144.120.156");
|
||||
|
||||
return domainNames.stream()
|
||||
.map(
|
||||
dom ->
|
||||
DynamicTest.dynamicTest(
|
||||
"Resolving: " + dom,
|
||||
() -> {
|
||||
int id = domainNames.indexOf(dom);
|
||||
|
||||
assertEquals(outputList.get(id), resolver.apply(dom));
|
||||
}));
|
||||
}
|
||||
|
||||
static final class PrimitiveOrReferenceEquality
|
||||
implements ExpressionTestCase<ImmutableSet<Boolean>> {
|
||||
public ImmutableSet<Boolean> before() {
|
||||
return ImmutableSet.of(
|
||||
RoundingMode.UP.equals(RoundingMode.DOWN),
|
||||
Objects.equals(RoundingMode.UP, RoundingMode.DOWN),
|
||||
!RoundingMode.UP.equals(RoundingMode.DOWN),
|
||||
!Objects.equals(RoundingMode.UP, RoundingMode.DOWN));
|
||||
}
|
||||
|
||||
public ImmutableSet<Boolean> after() {
|
||||
return ImmutableSet.of(
|
||||
RoundingMode.UP == RoundingMode.DOWN,
|
||||
RoundingMode.UP == RoundingMode.DOWN,
|
||||
RoundingMode.UP != RoundingMode.DOWN,
|
||||
RoundingMode.UP != RoundingMode.DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: This variant can verify that the values are equal.
|
||||
static final class PrimitiveOrReferenceEquality2 implements ExpressionTestCase2<Boolean> {
|
||||
public void before(Consumer<Boolean> sink) {
|
||||
sink.accept(RoundingMode.UP.equals(RoundingMode.DOWN));
|
||||
sink.accept(Objects.equals(RoundingMode.UP, RoundingMode.DOWN));
|
||||
sink.accept(!RoundingMode.UP.equals(RoundingMode.DOWN));
|
||||
sink.accept(!Objects.equals(RoundingMode.UP, RoundingMode.DOWN));
|
||||
}
|
||||
|
||||
public void after(Consumer<Boolean> sink) {
|
||||
sink.accept(RoundingMode.UP == RoundingMode.DOWN);
|
||||
sink.accept(RoundingMode.UP == RoundingMode.DOWN);
|
||||
sink.accept(RoundingMode.UP != RoundingMode.DOWN);
|
||||
sink.accept(RoundingMode.UP != RoundingMode.DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
// With this setup we could validate equality, and (in theory) even report the exact source in
|
||||
// case of an error.
|
||||
// @Test
|
||||
void primitiveOrReferenceEquality(BiConsumer<Boolean, Boolean> testCase) {
|
||||
testCase.accept(
|
||||
RoundingMode.UP.equals(RoundingMode.DOWN), RoundingMode.UP == RoundingMode.DOWN);
|
||||
testCase.accept(
|
||||
Objects.equals(RoundingMode.UP, RoundingMode.DOWN), RoundingMode.UP == RoundingMode.DOWN);
|
||||
testCase.accept(
|
||||
!RoundingMode.UP.equals(RoundingMode.DOWN), RoundingMode.UP != RoundingMode.DOWN);
|
||||
testCase.accept(
|
||||
!Objects.equals(RoundingMode.UP, RoundingMode.DOWN), RoundingMode.UP != RoundingMode.DOWN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// With this setup we could validate equality, and (in theory) even report the exact source in
|
||||
// case of an error.
|
||||
// @Test
|
||||
void primitiveOrReferenceEquality2(BiConsumer<Supplier<Boolean>, Supplier<Boolean>> testCase) {
|
||||
testCase.accept(
|
||||
() -> RoundingMode.UP.equals(RoundingMode.DOWN),
|
||||
() -> RoundingMode.UP == RoundingMode.DOWN);
|
||||
testCase.accept(
|
||||
() -> Objects.equals(RoundingMode.UP, RoundingMode.DOWN),
|
||||
() -> RoundingMode.UP == RoundingMode.DOWN);
|
||||
testCase.accept(
|
||||
() -> !RoundingMode.UP.equals(RoundingMode.DOWN),
|
||||
() -> RoundingMode.UP != RoundingMode.DOWN);
|
||||
testCase.accept(
|
||||
() -> !Objects.equals(RoundingMode.UP, RoundingMode.DOWN),
|
||||
() -> RoundingMode.UP != RoundingMode.DOWN);
|
||||
}
|
||||
|
||||
interface ExpressionTestCase<T> {
|
||||
T before();
|
||||
|
||||
T after();
|
||||
}
|
||||
|
||||
interface ExpressionTestCase2<T> {
|
||||
void before(Consumer<T> sink);
|
||||
|
||||
void after(Consumer<T> sink);
|
||||
}
|
||||
|
||||
// record ExpressionTestCaseX<T>(Supplier<T> before, Supplier<T> after);
|
||||
}
|
||||
@@ -1,6 +1,23 @@
|
||||
# An overview of Error Prone Support releases, along with compatible Error
|
||||
# Prone releases. This data was generated by `generate-version-compatibility-overview.sh`.
|
||||
releases:
|
||||
- version: 0.18.0
|
||||
compatible:
|
||||
- "2.30.0"
|
||||
- version: 0.17.0
|
||||
compatible:
|
||||
- "2.29.2"
|
||||
- "2.29.1"
|
||||
- "2.29.0"
|
||||
- "2.28.0"
|
||||
- "2.27.1"
|
||||
- "2.27.0"
|
||||
- "2.26.1"
|
||||
- "2.26.0"
|
||||
- "2.25.0"
|
||||
- "2.24.1"
|
||||
- "2.24.0"
|
||||
- "2.23.0"
|
||||
- version: 0.16.1
|
||||
compatible:
|
||||
- "2.29.2"
|
||||
|
||||
Reference in New Issue
Block a user