mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 15:49:33 +00:00
Compare commits
63 Commits
sbaars/PSM
...
maxsumrall
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56ed83bf49 | ||
|
|
575d494303 | ||
|
|
844ef84d55 | ||
|
|
29469cbbfd | ||
|
|
da9a6dd270 | ||
|
|
0cb03aa132 | ||
|
|
0f15070883 | ||
|
|
14b5fa1feb | ||
|
|
d1f513373f | ||
|
|
cd1593009b | ||
|
|
0d52414c04 | ||
|
|
a55ed9cea9 | ||
|
|
9b191f46aa | ||
|
|
6ea756f3ce | ||
|
|
adbcc4a94f | ||
|
|
0ed2788dbd | ||
|
|
04749ffcf5 | ||
|
|
37077bd03c | ||
|
|
4798f7cf5f | ||
|
|
ac285f0c50 | ||
|
|
1f3fb08082 | ||
|
|
9a397aa047 | ||
|
|
60e74332de | ||
|
|
3a94aad3b0 | ||
|
|
a5b5f43974 | ||
|
|
c212b9a171 | ||
|
|
499f922328 | ||
|
|
5720732b48 | ||
|
|
81ffd04fe4 | ||
|
|
b2f514f0a5 | ||
|
|
dad92b5fa6 | ||
|
|
6d699f75ad | ||
|
|
cad0c74dc0 | ||
|
|
a3a1f495f1 | ||
|
|
b2a646fc21 | ||
|
|
1194b0c83c | ||
|
|
82a07fde25 | ||
|
|
dec3220b5b | ||
|
|
79356ac553 | ||
|
|
f079c53914 | ||
|
|
8e24da907d | ||
|
|
3c89a1c80d | ||
|
|
9bd4b16001 | ||
|
|
6370452803 | ||
|
|
feb9abfa91 | ||
|
|
560f52bad0 | ||
|
|
2356c61314 | ||
|
|
9a9ef3c59d | ||
|
|
e9a1d54035 | ||
|
|
e9733f7426 | ||
|
|
534ebb62a1 | ||
|
|
1ed1e6cd03 | ||
|
|
85e3db6f0a | ||
|
|
6f4db8fc4d | ||
|
|
9d08e8fd4d | ||
|
|
9992ff49ce | ||
|
|
190b47870b | ||
|
|
becfcb5374 | ||
|
|
d45682143d | ||
|
|
4237732c5b | ||
|
|
d7c86c4854 | ||
|
|
e6e50717d3 | ||
|
|
834f9ae49b |
9
.github/workflows/build.yaml
vendored
9
.github/workflows/build.yaml
vendored
@@ -22,11 +22,10 @@ jobs:
|
||||
jdk: 17.0.4
|
||||
distribution: temurin
|
||||
experimental: false
|
||||
# XXX: Re-enable this build after upgrading to Error Prone 2.17.
|
||||
#- os: ubuntu-22.04
|
||||
# jdk: 20-ea
|
||||
# distribution: zulu
|
||||
# experimental: true
|
||||
- os: ubuntu-22.04
|
||||
jdk: 20-ea
|
||||
distribution: zulu
|
||||
experimental: true
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
steps:
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
--batch-mode --errors --strict-checksums
|
||||
--batch-mode
|
||||
--errors
|
||||
--strict-checksums
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-2022 Picnic Technologies BV
|
||||
Copyright (c) 2017-2023 Picnic Technologies BV
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
30
README.md
30
README.md
@@ -36,7 +36,9 @@ code_][picnic-blog-ep-post].
|
||||
### Installation
|
||||
|
||||
This library is built on top of [Error Prone][error-prone-orig-repo]. To use
|
||||
it:
|
||||
it, read the installation guide for Maven or Gradle below.
|
||||
|
||||
#### Maven
|
||||
|
||||
1. First, follow Error Prone's [installation
|
||||
guide][error-prone-installation-guide].
|
||||
@@ -94,6 +96,31 @@ it:
|
||||
Prone Support. Alternatively reference this project's `self-check` profile
|
||||
definition. -->
|
||||
|
||||
#### Gradle
|
||||
|
||||
1. First, follow the [installation guide]
|
||||
[error-prone-gradle-installation-guide] of the `gradle-errorprone-plugin`.
|
||||
2. Next, edit your `build.gradle` file to add one or more Error Prone Support
|
||||
modules:
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
// Error Prone itself.
|
||||
errorprone("com.google.errorprone:error_prone_core:${errorProneVersion}")
|
||||
// Error Prone Support's additional bug checkers.
|
||||
errorprone("tech.picnic.error-prone-support:error-prone-contrib:${errorProneSupportVersion}")
|
||||
// Error Prone Support's Refaster rules.
|
||||
errorprone("tech.picnic.error-prone-support:refaster-runner:${errorProneSupportVersion}")
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.errorprone.disableWarningsInGeneratedCode = true
|
||||
// Add other Error Prone flags here. See:
|
||||
// - https://github.com/tbroyer/gradle-errorprone-plugin#configuration
|
||||
// - https://errorprone.info/docs/flags
|
||||
}
|
||||
```
|
||||
|
||||
### Seeing it in action
|
||||
|
||||
Consider the following example code:
|
||||
@@ -207,6 +234,7 @@ guidelines][contributing].
|
||||
[error-prone-bugchecker]: https://github.com/google/error-prone/blob/master/check_api/src/main/java/com/google/errorprone/bugpatterns/BugChecker.java
|
||||
[error-prone-fork-jitpack]: https://jitpack.io/#PicnicSupermarket/error-prone
|
||||
[error-prone-fork-repo]: https://github.com/PicnicSupermarket/error-prone
|
||||
[error-prone-gradle-installation-guide]: https://github.com/tbroyer/gradle-errorprone-plugin
|
||||
[error-prone-installation-guide]: https://errorprone.info/docs/installation#maven
|
||||
[error-prone-orig-repo]: https://github.com/google/error-prone
|
||||
[error-prone-pull-3301]: https://github.com/google/error-prone/pull/3301
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
set -e -u -o pipefail
|
||||
|
||||
if [ "${#}" -gt 1 ]; then
|
||||
echo "Usage: ./$(basename "${0}") [PatchChecks]"
|
||||
echo "Usage: ${0} [PatchChecks]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
patchChecks=${1:-}
|
||||
|
||||
mvn clean test-compile fmt:format \
|
||||
-s "$(dirname "${0}")/settings.xml" \
|
||||
-T 1.0C \
|
||||
-Perror-prone \
|
||||
-Perror-prone-fork \
|
||||
|
||||
87
documentation-support/pom.xml
Normal file
87
documentation-support/pom.xml
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>documentation-support</artifactId>
|
||||
|
||||
<name>Picnic :: Error Prone Support :: Documentation Support</name>
|
||||
<description>Data extraction support for the purpose of documentation generation.</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto</groupId>
|
||||
<artifactId>auto-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.value</groupId>
|
||||
<artifactId>auto-value-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,103 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.auto.common.AnnotationMirrors;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.annotations.Immutable;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.tools.javac.code.Attribute;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import tech.picnic.errorprone.documentation.BugPatternExtractor.BugPatternDocumentation;
|
||||
|
||||
/**
|
||||
* An {@link Extractor} that describes how to extract data from a {@code @BugPattern} annotation.
|
||||
*/
|
||||
@Immutable
|
||||
final class BugPatternExtractor implements Extractor<BugPatternDocumentation> {
|
||||
@Override
|
||||
public BugPatternDocumentation extract(ClassTree tree, Context context) {
|
||||
ClassSymbol symbol = ASTHelpers.getSymbol(tree);
|
||||
BugPattern annotation = symbol.getAnnotation(BugPattern.class);
|
||||
requireNonNull(annotation, "BugPattern annotation must be present");
|
||||
|
||||
return new AutoValue_BugPatternExtractor_BugPatternDocumentation(
|
||||
symbol.getQualifiedName().toString(),
|
||||
annotation.name().isEmpty() ? tree.getSimpleName().toString() : annotation.name(),
|
||||
ImmutableList.copyOf(annotation.altNames()),
|
||||
annotation.link(),
|
||||
ImmutableList.copyOf(annotation.tags()),
|
||||
annotation.summary(),
|
||||
annotation.explanation(),
|
||||
annotation.severity(),
|
||||
annotation.disableable(),
|
||||
annotation.documentSuppression() ? getSuppressionAnnotations(tree) : ImmutableList.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract(ClassTree tree) {
|
||||
return ASTHelpers.hasDirectAnnotationWithSimpleName(tree, BugPattern.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully-qualified class names of suppression annotations specified by the {@link
|
||||
* BugPattern} annotation located on the given tree.
|
||||
*
|
||||
* @implNote This method cannot simply invoke {@link BugPattern#suppressionAnnotations()}, as that
|
||||
* will yield an "Attempt to access Class objects for TypeMirrors" exception.
|
||||
*/
|
||||
private static ImmutableList<String> getSuppressionAnnotations(ClassTree tree) {
|
||||
AnnotationTree annotationTree =
|
||||
ASTHelpers.getAnnotationWithSimpleName(
|
||||
ASTHelpers.getAnnotations(tree), BugPattern.class.getSimpleName());
|
||||
requireNonNull(annotationTree, "BugPattern annotation must be present");
|
||||
|
||||
Attribute.Array types =
|
||||
doCast(
|
||||
AnnotationMirrors.getAnnotationValue(
|
||||
ASTHelpers.getAnnotationMirror(annotationTree), "suppressionAnnotations"),
|
||||
Attribute.Array.class);
|
||||
|
||||
return types.getValue().stream()
|
||||
.map(v -> doCast(v, Attribute.Class.class).classType.toString())
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends AnnotationValue> T doCast(AnnotationValue value, Class<T> target) {
|
||||
verify(target.isInstance(value), "Value '%s' is not of type '%s'", value, target);
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class BugPatternDocumentation {
|
||||
abstract String fullyQualifiedName();
|
||||
|
||||
abstract String name();
|
||||
|
||||
abstract ImmutableList<String> altNames();
|
||||
|
||||
abstract String link();
|
||||
|
||||
abstract ImmutableList<String> tags();
|
||||
|
||||
abstract String summary();
|
||||
|
||||
abstract String explanation();
|
||||
|
||||
abstract SeverityLevel severityLevel();
|
||||
|
||||
abstract boolean canDisable();
|
||||
|
||||
abstract ImmutableList<String> suppressionAnnotations();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.Plugin;
|
||||
import com.sun.tools.javac.api.BasicJavacTask;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A compiler {@link Plugin} that analyzes and extracts relevant information for documentation
|
||||
* purposes from processed files.
|
||||
*/
|
||||
// XXX: Find a better name for this class; it doesn't generate documentation per se.
|
||||
@AutoService(Plugin.class)
|
||||
public final class DocumentationGenerator implements Plugin {
|
||||
@VisibleForTesting static final String OUTPUT_DIRECTORY_FLAG = "-XoutputDirectory";
|
||||
private static final Pattern OUTPUT_DIRECTORY_FLAG_PATTERN =
|
||||
Pattern.compile(Pattern.quote(OUTPUT_DIRECTORY_FLAG) + "=(.*)");
|
||||
|
||||
/** Instantiates a new {@link DocumentationGenerator} instance. */
|
||||
public DocumentationGenerator() {}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(JavacTask javacTask, String... args) {
|
||||
checkArgument(args.length == 1, "Precisely one path must be provided");
|
||||
|
||||
javacTask.addTaskListener(
|
||||
new DocumentationGeneratorTaskListener(
|
||||
((BasicJavacTask) javacTask).getContext(), getOutputPath(args[0])));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static Path getOutputPath(String pathArg) {
|
||||
Matcher matcher = OUTPUT_DIRECTORY_FLAG_PATTERN.matcher(pathArg);
|
||||
checkArgument(
|
||||
matcher.matches(), "'%s' must be of the form '%s=<value>'", pathArg, OUTPUT_DIRECTORY_FLAG);
|
||||
|
||||
String path = matcher.group(1);
|
||||
try {
|
||||
return Path.of(path);
|
||||
} catch (InvalidPathException e) {
|
||||
throw new IllegalArgumentException(String.format("Invalid path '%s'", path), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
import com.sun.source.util.TaskEvent.Kind;
|
||||
import com.sun.source.util.TaskListener;
|
||||
import com.sun.tools.javac.api.JavacTrees;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
/**
|
||||
* A {@link TaskListener} that identifies and extracts relevant content for documentation generation
|
||||
* and writes it to disk.
|
||||
*/
|
||||
// XXX: Find a better name for this class; it doesn't generate documentation per se.
|
||||
final class DocumentationGeneratorTaskListener implements TaskListener {
|
||||
private static final ObjectMapper OBJECT_MAPPER =
|
||||
new ObjectMapper().setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
|
||||
|
||||
private final Context context;
|
||||
private final Path docsPath;
|
||||
|
||||
DocumentationGeneratorTaskListener(Context context, Path path) {
|
||||
this.context = context;
|
||||
this.docsPath = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started(TaskEvent taskEvent) {
|
||||
if (taskEvent.getKind() == Kind.ANALYZE) {
|
||||
createDocsDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished(TaskEvent taskEvent) {
|
||||
if (taskEvent.getKind() != Kind.ANALYZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClassTree classTree = JavacTrees.instance(context).getTree(taskEvent.getTypeElement());
|
||||
JavaFileObject sourceFile = taskEvent.getSourceFile();
|
||||
if (classTree == null || sourceFile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ExtractorType.findMatchingType(classTree)
|
||||
.ifPresent(
|
||||
extractorType ->
|
||||
writeToFile(
|
||||
extractorType.getIdentifier(),
|
||||
getSimpleClassName(sourceFile.toUri()),
|
||||
extractorType.getExtractor().extract(classTree, context)));
|
||||
}
|
||||
|
||||
private void createDocsDirectory() {
|
||||
try {
|
||||
Files.createDirectories(docsPath);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Error while creating directory with path '%s'", docsPath), e);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void writeToFile(String identifier, String className, T data) {
|
||||
File file = docsPath.resolve(String.format("%s-%s.json", identifier, className)).toFile();
|
||||
|
||||
try (FileWriter fileWriter = new FileWriter(file, UTF_8)) {
|
||||
OBJECT_MAPPER.writeValue(fileWriter, data);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(String.format("Cannot write to file '%s'", file.getPath()), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSimpleClassName(URI path) {
|
||||
return Paths.get(path).getFileName().toString().replace(".java", "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import com.google.errorprone.annotations.Immutable;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
/**
|
||||
* Interface implemented by classes that define how to extract data of some type {@link T} from a
|
||||
* given {@link ClassTree}.
|
||||
*
|
||||
* @param <T> The type of data that is extracted.
|
||||
*/
|
||||
@Immutable
|
||||
interface Extractor<T> {
|
||||
/**
|
||||
* Extracts and returns an instance of {@link T} using the provided arguments.
|
||||
*
|
||||
* @param tree The {@link ClassTree} to analyze and from which to extract instances of {@link T}.
|
||||
* @param context The {@link Context} in which the current compilation takes place.
|
||||
* @return A non-null instance of {@link T}.
|
||||
*/
|
||||
// XXX: Drop `Context` parameter unless used.
|
||||
T extract(ClassTree tree, Context context);
|
||||
|
||||
/**
|
||||
* Tells whether this {@link Extractor} can extract documentation content from the given {@link
|
||||
* ClassTree}.
|
||||
*
|
||||
* @param tree The {@link ClassTree} of interest.
|
||||
* @return {@code true} iff data extraction is supported.
|
||||
*/
|
||||
boolean canExtract(ClassTree tree);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Optional;
|
||||
|
||||
/** An enumeration of {@link Extractor} types. */
|
||||
enum ExtractorType {
|
||||
BUG_PATTERN("bugpattern", new BugPatternExtractor());
|
||||
|
||||
private static final ImmutableSet<ExtractorType> TYPES =
|
||||
Sets.immutableEnumSet(EnumSet.allOf(ExtractorType.class));
|
||||
|
||||
private final String identifier;
|
||||
private final Extractor<?> extractor;
|
||||
|
||||
ExtractorType(String identifier, Extractor<?> extractor) {
|
||||
this.identifier = identifier;
|
||||
this.extractor = extractor;
|
||||
}
|
||||
|
||||
String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
Extractor<?> getExtractor() {
|
||||
return extractor;
|
||||
}
|
||||
|
||||
static Optional<ExtractorType> findMatchingType(ClassTree tree) {
|
||||
return TYPES.stream().filter(type -> type.getExtractor().canExtract(tree)).findFirst();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* A Java compiler plugin that extracts data from compiled classes, in support of the Error Prone
|
||||
* Support documentation.
|
||||
*/
|
||||
@com.google.errorprone.annotations.CheckReturnValue
|
||||
@org.jspecify.annotations.NullMarked
|
||||
package tech.picnic.errorprone.documentation;
|
||||
@@ -0,0 +1,153 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
final class BugPatternExtractorTest {
|
||||
@Test
|
||||
void noBugPattern(@TempDir Path outputDirectory) {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerWithoutAnnotation.java",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"public final class TestCheckerWithoutAnnotation extends BugChecker {}");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
|
||||
@Test
|
||||
void minimalBugPattern(@TempDir Path outputDirectory) throws IOException {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"MinimalBugChecker.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"@BugPattern(summary = \"MinimalBugChecker summary\", severity = SeverityLevel.ERROR)",
|
||||
"public final class MinimalBugChecker extends BugChecker {}");
|
||||
|
||||
verifyFileMatchesResource(
|
||||
outputDirectory,
|
||||
"bugpattern-MinimalBugChecker.json",
|
||||
"bugpattern-documentation-minimal.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void completeBugPattern(@TempDir Path outputDirectory) throws IOException {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"CompleteBugChecker.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"",
|
||||
"@BugPattern(",
|
||||
" name = \"OtherName\",",
|
||||
" summary = \"CompleteBugChecker summary\",",
|
||||
" linkType = BugPattern.LinkType.CUSTOM,",
|
||||
" link = \"https://error-prone.picnic.tech\",",
|
||||
" explanation = \"Example explanation\",",
|
||||
" severity = SeverityLevel.SUGGESTION,",
|
||||
" altNames = \"Check\",",
|
||||
" tags = BugPattern.StandardTags.SIMPLIFICATION,",
|
||||
" disableable = false,",
|
||||
" suppressionAnnotations = {BugPattern.class, Test.class})",
|
||||
"public final class CompleteBugChecker extends BugChecker {}");
|
||||
|
||||
verifyFileMatchesResource(
|
||||
outputDirectory,
|
||||
"bugpattern-CompleteBugChecker.json",
|
||||
"bugpattern-documentation-complete.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void undocumentedSuppressionBugPattern(@TempDir Path outputDirectory) throws IOException {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"UndocumentedSuppressionBugPattern.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"@BugPattern(",
|
||||
" summary = \"UndocumentedSuppressionBugPattern summary\",",
|
||||
" severity = SeverityLevel.WARNING,",
|
||||
" documentSuppression = false)",
|
||||
"public final class UndocumentedSuppressionBugPattern extends BugChecker {}");
|
||||
|
||||
verifyFileMatchesResource(
|
||||
outputDirectory,
|
||||
"bugpattern-UndocumentedSuppressionBugPattern.json",
|
||||
"bugpattern-documentation-undocumented-suppression.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void bugPatternAnnotationIsAbsent() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"TestChecker.java",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"// BUG: Diagnostic contains: Can extract: false",
|
||||
"public final class TestChecker extends BugChecker {}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
private static void verifyFileMatchesResource(
|
||||
Path outputDirectory, String fileName, String resourceName) throws IOException {
|
||||
assertThat(Files.readString(outputDirectory.resolve(fileName)))
|
||||
.isEqualToIgnoringWhitespace(getResource(resourceName));
|
||||
}
|
||||
|
||||
// XXX: Once we support only JDK 15+, drop this method in favour of including the resources as
|
||||
// text blocks in this class. (This also requires renaming the `verifyFileMatchesResource`
|
||||
// method.)
|
||||
private static String getResource(String resourceName) throws IOException {
|
||||
return Resources.toString(
|
||||
Resources.getResource(BugPatternExtractorTest.class, resourceName), UTF_8);
|
||||
}
|
||||
|
||||
/** A {@link BugChecker} that validates the {@link BugPatternExtractor}. */
|
||||
@BugPattern(summary = "Validates `BugPatternExtractor` extraction", severity = ERROR)
|
||||
public static final class TestChecker extends BugChecker implements ClassTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Description matchClass(ClassTree tree, VisitorState state) {
|
||||
BugPatternExtractor extractor = new BugPatternExtractor();
|
||||
|
||||
assertThatThrownBy(() -> extractor.extract(tree, state.context))
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.hasMessage("BugPattern annotation must be present");
|
||||
|
||||
return buildDescription(tree)
|
||||
.setMessage(String.format("Can extract: %s", extractor.canExtract(tree)))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.FileManagers;
|
||||
import com.google.errorprone.FileObjects;
|
||||
import com.sun.tools.javac.api.JavacTaskImpl;
|
||||
import com.sun.tools.javac.api.JavacTool;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import java.nio.file.Path;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
// XXX: Generalize and move this class so that it can also be used by `refaster-compiler`.
|
||||
// XXX: Add support for this class to the `ErrorProneTestHelperSourceFormat` check.
|
||||
public final class Compilation {
|
||||
private Compilation() {}
|
||||
|
||||
public static void compileWithDocumentationGenerator(
|
||||
Path outputDirectory, String fileName, String... lines) {
|
||||
compileWithDocumentationGenerator(outputDirectory.toAbsolutePath().toString(), fileName, lines);
|
||||
}
|
||||
|
||||
public static void compileWithDocumentationGenerator(
|
||||
String outputDirectory, String fileName, String... lines) {
|
||||
compile(
|
||||
ImmutableList.of("-Xplugin:DocumentationGenerator -XoutputDirectory=" + outputDirectory),
|
||||
FileObjects.forSourceLines(fileName, lines));
|
||||
}
|
||||
|
||||
private static void compile(ImmutableList<String> options, JavaFileObject javaFileObject) {
|
||||
JavacFileManager javacFileManager = FileManagers.testFileManager();
|
||||
JavaCompiler compiler = JavacTool.create();
|
||||
JavacTaskImpl task =
|
||||
(JavacTaskImpl)
|
||||
compiler.getTask(
|
||||
null,
|
||||
javacFileManager,
|
||||
null,
|
||||
options,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(javaFileObject));
|
||||
|
||||
task.call();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static java.nio.file.attribute.AclEntryPermission.ADD_SUBDIRECTORY;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.condition.OS.WINDOWS;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystemException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.AclEntry;
|
||||
import java.nio.file.attribute.AclFileAttributeView;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
final class DocumentationGeneratorTaskListenerTest {
|
||||
@EnabledOnOs(WINDOWS)
|
||||
@Test
|
||||
void readOnlyFileSystemWindows(@TempDir Path outputDirectory) throws IOException {
|
||||
AclFileAttributeView view =
|
||||
Files.getFileAttributeView(outputDirectory, AclFileAttributeView.class);
|
||||
view.setAcl(
|
||||
view.getAcl().stream()
|
||||
.map(
|
||||
entry ->
|
||||
AclEntry.newBuilder(entry)
|
||||
.setPermissions(
|
||||
Sets.difference(entry.permissions(), ImmutableSet.of(ADD_SUBDIRECTORY)))
|
||||
.build())
|
||||
.collect(toImmutableList()));
|
||||
|
||||
readOnlyFileSystemFailsToWrite(outputDirectory.resolve("nonexistent"));
|
||||
}
|
||||
|
||||
@DisabledOnOs(WINDOWS)
|
||||
@Test
|
||||
void readOnlyFileSystemNonWindows(@TempDir Path outputDirectory) {
|
||||
assertThat(outputDirectory.toFile().setWritable(false))
|
||||
.describedAs("Failed to make test directory unwritable")
|
||||
.isTrue();
|
||||
|
||||
readOnlyFileSystemFailsToWrite(outputDirectory.resolve("nonexistent"));
|
||||
}
|
||||
|
||||
private static void readOnlyFileSystemFailsToWrite(Path outputDirectory) {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory, "A.java", "class A {}"))
|
||||
.hasRootCauseInstanceOf(FileSystemException.class)
|
||||
.hasCauseInstanceOf(IllegalStateException.class)
|
||||
.hasMessageEndingWith("Error while creating directory with path '%s'", outputDirectory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noClassNoOutput(@TempDir Path outputDirectory) {
|
||||
Compilation.compileWithDocumentationGenerator(outputDirectory, "A.java", "package pkg;");
|
||||
|
||||
assertThat(outputDirectory).isEmptyDirectory();
|
||||
}
|
||||
|
||||
@Test
|
||||
void excessArguments(@TempDir Path outputDirectory) {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory.toAbsolutePath() + " extra-arg", "A.java", "package pkg;"))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Precisely one path must be provided");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static tech.picnic.errorprone.documentation.DocumentationGenerator.OUTPUT_DIRECTORY_FLAG;
|
||||
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
final class DocumentationGeneratorTest {
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"bar", "foo"})
|
||||
void getOutputPath(String path) {
|
||||
assertThat(DocumentationGenerator.getOutputPath(OUTPUT_DIRECTORY_FLAG + '=' + path))
|
||||
.isEqualTo(Path.of(path));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"", "-XoutputDirectory", "invalidOption=Test", "nothing"})
|
||||
void getOutputPathWithInvalidArgument(String pathArg) {
|
||||
assertThatThrownBy(() -> DocumentationGenerator.getOutputPath(pathArg))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("'%s' must be of the form '%s=<value>'", pathArg, OUTPUT_DIRECTORY_FLAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOutputPathWithInvalidPath() {
|
||||
String basePath = "path-with-null-char-\0";
|
||||
assertThatThrownBy(
|
||||
() -> DocumentationGenerator.getOutputPath(OUTPUT_DIRECTORY_FLAG + '=' + basePath))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasCauseInstanceOf(InvalidPathException.class)
|
||||
.hasMessageEndingWith("Invalid path '%s'", basePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"fullyQualifiedName": "pkg.CompleteBugChecker",
|
||||
"name": "OtherName",
|
||||
"altNames": [
|
||||
"Check"
|
||||
],
|
||||
"link": "https://error-prone.picnic.tech",
|
||||
"tags": [
|
||||
"Simplification"
|
||||
],
|
||||
"summary": "CompleteBugChecker summary",
|
||||
"explanation": "Example explanation",
|
||||
"severityLevel": "SUGGESTION",
|
||||
"canDisable": false,
|
||||
"suppressionAnnotations": [
|
||||
"com.google.errorprone.BugPattern",
|
||||
"org.junit.jupiter.api.Test"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"fullyQualifiedName": "pkg.MinimalBugChecker",
|
||||
"name": "MinimalBugChecker",
|
||||
"altNames": [],
|
||||
"link": "",
|
||||
"tags": [],
|
||||
"summary": "MinimalBugChecker summary",
|
||||
"explanation": "",
|
||||
"severityLevel": "ERROR",
|
||||
"canDisable": true,
|
||||
"suppressionAnnotations": [
|
||||
"java.lang.SuppressWarnings"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"fullyQualifiedName": "pkg.UndocumentedSuppressionBugPattern",
|
||||
"name": "UndocumentedSuppressionBugPattern",
|
||||
"altNames": [],
|
||||
"link": "",
|
||||
"tags": [],
|
||||
"summary": "UndocumentedSuppressionBugPattern summary",
|
||||
"explanation": "",
|
||||
"severityLevel": "WARNING",
|
||||
"canDisable": true,
|
||||
"suppressionAnnotations": []
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.6.1-SNAPSHOT</version>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
@@ -39,6 +39,14 @@
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>documentation-support</artifactId>
|
||||
<!-- This dependency is declared only as a hint to Maven that
|
||||
compilation depends on it; see the `maven-compiler-plugin`'s
|
||||
`annotationProcessorPaths` configuration below. -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-support</artifactId>
|
||||
@@ -138,6 +146,10 @@
|
||||
<artifactId>value-annotations</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
@@ -146,7 +158,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
@@ -213,6 +225,11 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths combine.children="append">
|
||||
<path>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>documentation-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-compiler</artifactId>
|
||||
@@ -226,6 +243,7 @@
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs combine.children="append">
|
||||
<arg>-Xplugin:RefasterRuleCompiler</arg>
|
||||
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@@ -9,7 +9,6 @@ import static com.google.errorprone.matchers.Matchers.hasModifier;
|
||||
import static com.google.errorprone.matchers.Matchers.not;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static tech.picnic.errorprone.bugpatterns.util.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
import static tech.picnic.errorprone.bugpatterns.util.JavaKeywords.isValidIdentifier;
|
||||
import static tech.picnic.errorprone.bugpatterns.util.MoreJUnitMatchers.SETUP_OR_TEARDOWN_METHOD;
|
||||
import static tech.picnic.errorprone.bugpatterns.util.MoreJUnitMatchers.TEST_METHOD;
|
||||
|
||||
@@ -25,15 +24,11 @@ import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.ImportTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
import tech.picnic.errorprone.bugpatterns.util.ConflictDetection;
|
||||
|
||||
/** A {@link BugChecker} that flags non-canonical JUnit method declarations. */
|
||||
// XXX: Consider introducing a class-level check that enforces that test classes:
|
||||
@@ -90,7 +85,7 @@ public final class JUnitMethodDeclaration extends BugChecker implements MethodTr
|
||||
tryCanonicalizeMethodName(symbol)
|
||||
.ifPresent(
|
||||
newName ->
|
||||
findMethodRenameBlocker(symbol, newName, state)
|
||||
ConflictDetection.findMethodRenameBlocker(symbol, newName, state)
|
||||
.ifPresentOrElse(
|
||||
blocker -> reportMethodRenameBlocker(tree, blocker, state),
|
||||
() -> fixBuilder.merge(SuggestedFixes.renameMethod(tree, newName, state))));
|
||||
@@ -106,61 +101,7 @@ public final class JUnitMethodDeclaration extends BugChecker implements MethodTr
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* If applicable, returns a human-readable argument against assigning the given name to an
|
||||
* existing method.
|
||||
*
|
||||
* <p>This method implements imperfect heuristics. Things it currently does not consider include
|
||||
* the following:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Whether the rename would merely introduce a method overload, rather than clashing with an
|
||||
* existing method declaration.
|
||||
* <li>Whether the rename would cause a method in a superclass to be overridden.
|
||||
* <li>Whether the rename would in fact clash with a static import. (It could be that a static
|
||||
* import of the same name is only referenced from lexical scopes in which the method under
|
||||
* consideration cannot be referenced directly.)
|
||||
* </ul>
|
||||
*/
|
||||
private static Optional<String> findMethodRenameBlocker(
|
||||
MethodSymbol method, String newName, VisitorState state) {
|
||||
if (isExistingMethodName(method.owner.type, newName, state)) {
|
||||
return Optional.of(
|
||||
String.format(
|
||||
"a method named `%s` is already defined in this class or a supertype", newName));
|
||||
}
|
||||
|
||||
if (isSimpleNameStaticallyImported(newName, state)) {
|
||||
return Optional.of(String.format("`%s` is already statically imported", newName));
|
||||
}
|
||||
|
||||
if (!isValidIdentifier(newName)) {
|
||||
return Optional.of(String.format("`%s` is not a valid identifier", newName));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static boolean isExistingMethodName(Type clazz, String name, VisitorState state) {
|
||||
return ASTHelpers.matchingMethods(state.getName(name), method -> true, clazz, state.getTypes())
|
||||
.findAny()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
private static boolean isSimpleNameStaticallyImported(String simpleName, VisitorState state) {
|
||||
return state.getPath().getCompilationUnit().getImports().stream()
|
||||
.filter(ImportTree::isStatic)
|
||||
.map(ImportTree::getQualifiedIdentifier)
|
||||
.map(tree -> getStaticImportSimpleName(tree, state))
|
||||
.anyMatch(simpleName::contentEquals);
|
||||
}
|
||||
|
||||
private static CharSequence getStaticImportSimpleName(Tree tree, VisitorState state) {
|
||||
String source = SourceCode.treeToString(tree, state);
|
||||
return source.subSequence(source.lastIndexOf('.') + 1, source.length());
|
||||
}
|
||||
|
||||
private static Optional<String> tryCanonicalizeMethodName(Symbol symbol) {
|
||||
private static Optional<String> tryCanonicalizeMethodName(MethodSymbol symbol) {
|
||||
return Optional.of(symbol.getQualifiedName().toString())
|
||||
.filter(name -> name.startsWith(TEST_PREFIX))
|
||||
.map(name -> name.substring(TEST_PREFIX.length()))
|
||||
|
||||
@@ -42,6 +42,7 @@ import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.bugpatterns.util.AnnotationAttributeMatcher;
|
||||
import tech.picnic.errorprone.bugpatterns.util.Flags;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
@@ -220,7 +221,7 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
|
||||
|
||||
private static ImmutableList<String> excludedAnnotations(ErrorProneFlags flags) {
|
||||
Set<String> exclusions = new HashSet<>();
|
||||
flags.getList(EXCLUDED_ANNOTATIONS_FLAG).ifPresent(exclusions::addAll);
|
||||
exclusions.addAll(Flags.getList(flags, EXCLUDED_ANNOTATIONS_FLAG));
|
||||
exclusions.addAll(BLACKLISTED_ANNOTATIONS);
|
||||
return ImmutableList.copyOf(exclusions);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.bugpatterns.util.Flags;
|
||||
import tech.picnic.errorprone.bugpatterns.util.MethodMatcherFactory;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
@@ -63,9 +64,8 @@ import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
public final class RedundantStringConversion extends BugChecker
|
||||
implements BinaryTreeMatcher, CompoundAssignmentTreeMatcher, MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String FLAG_PREFIX = "RedundantStringConversion:";
|
||||
private static final String EXTRA_STRING_CONVERSION_METHODS_FLAG =
|
||||
FLAG_PREFIX + "ExtraConversionMethods";
|
||||
"RedundantStringConversion:ExtraConversionMethods";
|
||||
|
||||
@SuppressWarnings("UnnecessaryLambda")
|
||||
private static final Matcher<ExpressionTree> ANY_EXPR = (t, s) -> true;
|
||||
@@ -374,10 +374,9 @@ public final class RedundantStringConversion extends BugChecker
|
||||
ErrorProneFlags flags) {
|
||||
// XXX: ErrorProneFlags#getList splits by comma, but method signatures may also contain commas.
|
||||
// For this class methods accepting more than one argument are not valid, but still: not nice.
|
||||
return flags
|
||||
.getList(EXTRA_STRING_CONVERSION_METHODS_FLAG)
|
||||
.map(new MethodMatcherFactory()::create)
|
||||
.map(m -> anyOf(WELL_KNOWN_STRING_CONVERSION_METHODS, m))
|
||||
.orElse(WELL_KNOWN_STRING_CONVERSION_METHODS);
|
||||
return anyOf(
|
||||
WELL_KNOWN_STRING_CONVERSION_METHODS,
|
||||
new MethodMatcherFactory()
|
||||
.create(Flags.getList(flags, EXTRA_STRING_CONVERSION_METHODS_FLAG)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
@@ -9,41 +10,72 @@ import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
import static com.google.errorprone.matchers.Matchers.not;
|
||||
import static tech.picnic.errorprone.bugpatterns.util.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.ErrorProneFlags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.suppliers.Suppliers;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import tech.picnic.errorprone.bugpatterns.util.Flags;
|
||||
|
||||
/** A {@link BugChecker} that flags {@code @RequestParam} parameters with an unsupported type. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "`@RequestParam` does not support `ImmutableCollection` and `ImmutableMap` subtypes",
|
||||
summary =
|
||||
"By default, `@RequestParam` does not support `ImmutableCollection` and `ImmutableMap` subtypes",
|
||||
link = BUG_PATTERNS_BASE_URL + "RequestParamType",
|
||||
linkType = CUSTOM,
|
||||
severity = ERROR,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class RequestParamType extends BugChecker implements VariableTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<VariableTree> HAS_UNSUPPORTED_REQUEST_PARAM =
|
||||
allOf(
|
||||
annotations(AT_LEAST_ONE, isType("org.springframework.web.bind.annotation.RequestParam")),
|
||||
anyOf(isSubtypeOf(ImmutableCollection.class), isSubtypeOf(ImmutableMap.class)));
|
||||
private static final String SUPPORTED_CUSTOM_TYPES_FLAG = "RequestParamType:SupportedCustomTypes";
|
||||
|
||||
/** Instantiates a new {@link RequestParamType} instance. */
|
||||
public RequestParamType() {}
|
||||
private final Matcher<VariableTree> hasUnsupportedRequestParamType;
|
||||
|
||||
/** Instantiates a default {@link RequestParamType} instance. */
|
||||
public RequestParamType() {
|
||||
this(ErrorProneFlags.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a customized {@link RequestParamType} instance.
|
||||
*
|
||||
* @param flags Any provided command line flags.
|
||||
*/
|
||||
public RequestParamType(ErrorProneFlags flags) {
|
||||
hasUnsupportedRequestParamType = hasUnsupportedRequestParamType(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description matchVariable(VariableTree tree, VisitorState state) {
|
||||
return HAS_UNSUPPORTED_REQUEST_PARAM.matches(tree, state)
|
||||
return hasUnsupportedRequestParamType.matches(tree, state)
|
||||
? describeMatch(tree)
|
||||
: Description.NO_MATCH;
|
||||
}
|
||||
|
||||
private static Matcher<VariableTree> hasUnsupportedRequestParamType(ErrorProneFlags flags) {
|
||||
return allOf(
|
||||
annotations(AT_LEAST_ONE, isType("org.springframework.web.bind.annotation.RequestParam")),
|
||||
anyOf(isSubtypeOf(ImmutableCollection.class), isSubtypeOf(ImmutableMap.class)),
|
||||
not(isSubtypeOfAny(Flags.getList(flags, SUPPORTED_CUSTOM_TYPES_FLAG))));
|
||||
}
|
||||
|
||||
private static Matcher<Tree> isSubtypeOfAny(ImmutableList<String> inclusions) {
|
||||
return anyOf(
|
||||
inclusions.stream()
|
||||
.map(inclusion -> isSubtypeOf(Suppliers.typeFromString(inclusion)))
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import static tech.picnic.errorprone.bugpatterns.util.JavaKeywords.isValidIdentifier;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.ImportTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.Optional;
|
||||
|
||||
/** A set of helper methods for detecting conflicts that would be caused when applying fixes. */
|
||||
public final class ConflictDetection {
|
||||
private ConflictDetection() {}
|
||||
|
||||
/**
|
||||
* If applicable, returns a human-readable argument against assigning the given name to an
|
||||
* existing method.
|
||||
*
|
||||
* <p>This method implements imperfect heuristics. Things it currently does not consider include
|
||||
* the following:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Whether the rename would merely introduce a method overload, rather than clashing with an
|
||||
* existing method declaration in its class or a supertype.
|
||||
* <li>Whether the rename would in fact clash with a static import. (It could be that a static
|
||||
* import of the same name is only referenced from lexical scopes in which the method under
|
||||
* consideration cannot be referenced directly.)
|
||||
* </ul>
|
||||
*
|
||||
* @param method The method considered for renaming.
|
||||
* @param newName The newly proposed name for the method.
|
||||
* @param state The {@link VisitorState} to use when searching for blockers.
|
||||
* @return A human-readable argument against assigning the proposed name to the given method, or
|
||||
* {@link Optional#empty()} if no blocker was found.
|
||||
*/
|
||||
public static Optional<String> findMethodRenameBlocker(
|
||||
MethodSymbol method, String newName, VisitorState state) {
|
||||
if (isExistingMethodName(method.owner.type, newName, state)) {
|
||||
return Optional.of(
|
||||
String.format(
|
||||
"a method named `%s` is already defined in this class or a supertype", newName));
|
||||
}
|
||||
|
||||
if (isSimpleNameStaticallyImported(newName, state)) {
|
||||
return Optional.of(String.format("`%s` is already statically imported", newName));
|
||||
}
|
||||
|
||||
if (!isValidIdentifier(newName)) {
|
||||
return Optional.of(String.format("`%s` is not a valid identifier", newName));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static boolean isExistingMethodName(Type clazz, String name, VisitorState state) {
|
||||
return ASTHelpers.matchingMethods(state.getName(name), method -> true, clazz, state.getTypes())
|
||||
.findAny()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
private static boolean isSimpleNameStaticallyImported(String simpleName, VisitorState state) {
|
||||
return state.getPath().getCompilationUnit().getImports().stream()
|
||||
.filter(ImportTree::isStatic)
|
||||
.map(ImportTree::getQualifiedIdentifier)
|
||||
.map(tree -> getStaticImportSimpleName(tree, state))
|
||||
.anyMatch(simpleName::contentEquals);
|
||||
}
|
||||
|
||||
private static CharSequence getStaticImportSimpleName(Tree tree, VisitorState state) {
|
||||
String source = SourceCode.treeToString(tree, state);
|
||||
return source.subSequence(source.lastIndexOf('.') + 1, source.length());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.ErrorProneFlags;
|
||||
|
||||
/** Helper methods for working with {@link ErrorProneFlags}. */
|
||||
public final class Flags {
|
||||
private Flags() {}
|
||||
|
||||
/**
|
||||
* Returns the list of (comma-separated) arguments passed using the given Error Prone flag.
|
||||
*
|
||||
* @param errorProneFlags The full set of flags provided.
|
||||
* @param name The name of the flag of interest.
|
||||
* @return A non-{@code null} list of provided arguments; this list is empty if the flag was not
|
||||
* provided, or if the flag's value is the empty string.
|
||||
*/
|
||||
public static ImmutableList<String> getList(ErrorProneFlags errorProneFlags, String name) {
|
||||
return errorProneFlags
|
||||
.getList(name)
|
||||
.map(ImmutableList::copyOf)
|
||||
.filter(flags -> !flags.equals(ImmutableList.of("")))
|
||||
.orElseGet(ImmutableList::of);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ final class AssertJOptionalRules {
|
||||
|
||||
static final class AssertThatOptional<T> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("NullAway")
|
||||
ObjectAssert<T> before(Optional<T> optional) {
|
||||
return assertThat(optional.orElseThrow());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,521 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.annotations.DoNotCall;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.function.Supplier;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.junit.jupiter.api.function.ThrowingSupplier;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/**
|
||||
* Refaster rules to replace JUnit assertions with AssertJ equivalents.
|
||||
*
|
||||
* <p>Note that, while both libraries throw an {@link AssertionError} in case of an assertion
|
||||
* failure, the exact subtype used generally differs.
|
||||
*/
|
||||
// XXX: Not all `org.assertj.core.api.Assertions` methods have an associated Refaster rule yet;
|
||||
// expand this class.
|
||||
// XXX: Introduce a `@Matcher` on `Executable` and `ThrowingSupplier` expressions, such that they
|
||||
// are only matched if they are also compatible with the `ThrowingCallable` functional interface.
|
||||
// When implementing such a matcher, note that expressions with a non-void return type such as
|
||||
// `() -> toString()` match both `ThrowingSupplier` and `ThrowingCallable`, but `() -> "constant"`
|
||||
// is only compatible with the former.
|
||||
@OnlineDocumentation
|
||||
final class JUnitToAssertJRules {
|
||||
private JUnitToAssertJRules() {}
|
||||
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(
|
||||
Assertions.class,
|
||||
assertDoesNotThrow(() -> null),
|
||||
assertInstanceOf(null, null),
|
||||
assertThrows(null, null),
|
||||
assertThrowsExactly(null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
(Runnable) () -> assertNotSame(null, null),
|
||||
(Runnable) () -> assertNull(null),
|
||||
(Runnable) () -> assertSame(null, null),
|
||||
(Runnable) () -> assertTrue(true));
|
||||
}
|
||||
|
||||
static final class ThrowNewAssertionError {
|
||||
@BeforeTemplate
|
||||
void before() {
|
||||
Assertions.fail();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@DoNotCall
|
||||
void after() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
static final class FailWithMessage<T> {
|
||||
@BeforeTemplate
|
||||
T before(String message) {
|
||||
return Assertions.fail(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
T after(String message) {
|
||||
return fail(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class FailWithMessageAndThrowable<T> {
|
||||
@BeforeTemplate
|
||||
T before(String message, Throwable throwable) {
|
||||
return Assertions.fail(message, throwable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
T after(String message, Throwable throwable) {
|
||||
return fail(message, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
static final class FailWithThrowable {
|
||||
@BeforeTemplate
|
||||
void before(Throwable throwable) {
|
||||
Assertions.fail(throwable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@DoNotCall
|
||||
void after(Throwable throwable) {
|
||||
throw new AssertionError(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsTrue {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual) {
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean actual) {
|
||||
assertThat(actual).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageStringIsTrue {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, String message) {
|
||||
assertTrue(actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean actual, String message) {
|
||||
assertThat(actual).withFailMessage(message).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageSupplierIsTrue {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, Supplier<String> supplier) {
|
||||
assertTrue(actual, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean actual, Supplier<String> supplier) {
|
||||
assertThat(actual).withFailMessage(supplier).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsFalse {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual) {
|
||||
assertFalse(actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean actual) {
|
||||
assertThat(actual).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageStringIsFalse {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, String message) {
|
||||
assertFalse(actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean actual, String message) {
|
||||
assertThat(actual).withFailMessage(message).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageSupplierIsFalse {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, Supplier<String> supplier) {
|
||||
assertFalse(actual, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean actual, Supplier<String> supplier) {
|
||||
assertThat(actual).withFailMessage(supplier).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsNull {
|
||||
@BeforeTemplate
|
||||
void before(Object actual) {
|
||||
assertNull(actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual) {
|
||||
assertThat(actual).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageStringIsNull {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, String message) {
|
||||
assertNull(actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, String message) {
|
||||
assertThat(actual).withFailMessage(message).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageSupplierIsNull {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Supplier<String> supplier) {
|
||||
assertNull(actual, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Supplier<String> supplier) {
|
||||
assertThat(actual).withFailMessage(supplier).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsNotNull {
|
||||
@BeforeTemplate
|
||||
void before(Object actual) {
|
||||
assertNotNull(actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual) {
|
||||
assertThat(actual).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageStringIsNotNull {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, String message) {
|
||||
assertNotNull(actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, String message) {
|
||||
assertThat(actual).withFailMessage(message).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageSupplierIsNotNull {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Supplier<String> supplier) {
|
||||
assertNotNull(actual, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Supplier<String> supplier) {
|
||||
assertThat(actual).withFailMessage(supplier).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsSameAs {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Object expected) {
|
||||
assertSame(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected) {
|
||||
assertThat(actual).isSameAs(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageStringIsSameAs {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Object expected, String message) {
|
||||
assertSame(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).isSameAs(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageSupplierIsSameAs {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Object expected, Supplier<String> supplier) {
|
||||
assertSame(expected, actual, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, Supplier<String> supplier) {
|
||||
assertThat(actual).withFailMessage(supplier).isSameAs(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsNotSameAs {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Object expected) {
|
||||
assertNotSame(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected) {
|
||||
assertThat(actual).isNotSameAs(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageStringIsNotSameAs {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Object expected, String message) {
|
||||
assertNotSame(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).isNotSameAs(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageSupplierIsNotSameAs {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Object expected, Supplier<String> supplier) {
|
||||
assertNotSame(expected, actual, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, Supplier<String> supplier) {
|
||||
assertThat(actual).withFailMessage(supplier).isNotSameAs(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIsExactlyInstanceOf<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, Class<T> clazz) {
|
||||
assertThrowsExactly(clazz, throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Class<T> clazz) {
|
||||
assertThatThrownBy(throwingCallable).isExactlyInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByWithFailMessageStringIsExactlyInstanceOf<
|
||||
T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, Class<T> clazz, String message) {
|
||||
assertThrowsExactly(clazz, throwingCallable, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Class<T> clazz, String message) {
|
||||
assertThatThrownBy(throwingCallable).withFailMessage(message).isExactlyInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByWithFailMessageSupplierIsExactlyInstanceOf<
|
||||
T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, Class<T> clazz, Supplier<String> supplier) {
|
||||
assertThrowsExactly(clazz, throwingCallable, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Class<T> clazz, Supplier<String> supplier) {
|
||||
assertThatThrownBy(throwingCallable).withFailMessage(supplier).isExactlyInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIsInstanceOf<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, Class<T> clazz) {
|
||||
assertThrows(clazz, throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Class<T> clazz) {
|
||||
assertThatThrownBy(throwingCallable).isInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByWithFailMessageStringIsInstanceOf<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, Class<T> clazz, String message) {
|
||||
assertThrows(clazz, throwingCallable, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Class<T> clazz, String message) {
|
||||
assertThatThrownBy(throwingCallable).withFailMessage(message).isInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByWithFailMessageSupplierIsInstanceOf<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, Class<T> clazz, Supplier<String> supplier) {
|
||||
assertThrows(clazz, throwingCallable, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Class<T> clazz, Supplier<String> supplier) {
|
||||
assertThatThrownBy(throwingCallable).withFailMessage(supplier).isInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatCodeDoesNotThrowAnyException {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable) {
|
||||
assertDoesNotThrow(throwingCallable);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(ThrowingSupplier<?> throwingCallable) {
|
||||
assertDoesNotThrow(throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable) {
|
||||
assertThatCode(throwingCallable).doesNotThrowAnyException();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatCodeWithFailMessageStringDoesNotThrowAnyException {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, String message) {
|
||||
assertDoesNotThrow(throwingCallable, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(ThrowingSupplier<?> throwingCallable, String message) {
|
||||
assertDoesNotThrow(throwingCallable, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, String message) {
|
||||
assertThatCode(throwingCallable).withFailMessage(message).doesNotThrowAnyException();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatCodeWithFailMessageSupplierDoesNotThrowAnyException {
|
||||
@BeforeTemplate
|
||||
void before(Executable throwingCallable, Supplier<String> supplier) {
|
||||
assertDoesNotThrow(throwingCallable, supplier);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(ThrowingSupplier<?> throwingCallable, Supplier<String> supplier) {
|
||||
assertDoesNotThrow(throwingCallable, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Supplier<String> supplier) {
|
||||
assertThatCode(throwingCallable).withFailMessage(supplier).doesNotThrowAnyException();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsInstanceOf<T> {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Class<T> clazz) {
|
||||
assertInstanceOf(clazz, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Class<T> clazz) {
|
||||
assertThat(actual).isInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageStringIsInstanceOf<T> {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Class<T> clazz, String message) {
|
||||
assertInstanceOf(clazz, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Class<T> clazz, String message) {
|
||||
assertThat(actual).withFailMessage(message).isInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatWithFailMessageSupplierIsInstanceOf<T> {
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Class<T> clazz, Supplier<String> supplier) {
|
||||
assertInstanceOf(clazz, actual, supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Class<T> clazz, Supplier<String> supplier) {
|
||||
assertThat(actual).withFailMessage(supplier).isInstanceOf(clazz);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.stream.Stream;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.ResultQuery;
|
||||
import tech.picnic.errorprone.refaster.annotation.Description;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@OnlineDocumentation
|
||||
final class JooqRules {
|
||||
private JooqRules() {}
|
||||
|
||||
/** Prefer eagerly fetching data over (lazy) streaming to avoid potentially leaking resources. */
|
||||
@Description(
|
||||
"Prefer eagerly fetching data over (lazy) streaming to avoid potentially leaking resources.")
|
||||
static final class ResultQueryFetchStream {
|
||||
@BeforeTemplate
|
||||
Stream<?> before(ResultQuery<? extends Record> resultQuery) {
|
||||
return resultQuery.stream();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Stream<?> after(ResultQuery<? extends Record> resultQuery) {
|
||||
return resultQuery.fetch().stream();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -43,6 +45,21 @@ final class MapRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Map#getOrDefault(Object, Object)} over more contrived alternatives. */
|
||||
// XXX: Note that `requireNonNullElse` throws an NPE if the second argument is `null`, while the
|
||||
// alternative does not.
|
||||
static final class MapGetOrDefault<K, V, T> {
|
||||
@BeforeTemplate
|
||||
V before(Map<K, V> map, T key, V defaultValue) {
|
||||
return requireNonNullElse(map.get(key), defaultValue);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
V after(Map<K, V> map, T key, V defaultValue) {
|
||||
return map.getOrDefault(key, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Map#isEmpty()} over more contrived alternatives. */
|
||||
static final class MapIsEmpty<K, V> {
|
||||
@BeforeTemplate
|
||||
|
||||
@@ -2,13 +2,17 @@ package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
import static java.util.Objects.requireNonNullElseGet;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
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.UseImportPolicy;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@@ -43,13 +47,18 @@ final class NullRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Objects#requireNonNullElse(Object, Object)} over the Guava alternative. */
|
||||
// XXX: This rule is not valid in case `second` is `@Nullable`: in that case the Guava variant
|
||||
// will return `null`, while the JDK variant will throw an NPE.
|
||||
/**
|
||||
* Prefer {@link Objects#requireNonNullElse(Object, Object)} over non-JDK or more contrived
|
||||
* alternatives.
|
||||
*/
|
||||
// XXX: This rule is not valid in case `second` is `@Nullable`: in that case the Guava and
|
||||
// `Optional` variants will return `null`, where the `requireNonNullElse` alternative will throw
|
||||
// an NPE.
|
||||
static final class RequireNonNullElse<T> {
|
||||
@BeforeTemplate
|
||||
T before(T first, T second) {
|
||||
return MoreObjects.firstNonNull(first, second);
|
||||
return Refaster.anyOf(
|
||||
MoreObjects.firstNonNull(first, second), Optional.ofNullable(first).orElse(second));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -59,6 +68,26 @@ final class NullRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link Objects#requireNonNullElseGet(Object, Supplier)} over more contrived
|
||||
* alternatives.
|
||||
*/
|
||||
// XXX: This rule is not valid in case `supplier` yields `@Nullable` values: in that case the
|
||||
// `Optional` variant will return `null`, where the `requireNonNullElseGet` alternative will throw
|
||||
// an NPE.
|
||||
static final class RequireNonNullElseGet<T, S extends T> {
|
||||
@BeforeTemplate
|
||||
T before(T object, Supplier<S> supplier) {
|
||||
return Optional.ofNullable(object).orElseGet(supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
T after(T object, Supplier<S> supplier) {
|
||||
return requireNonNullElseGet(object, supplier);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Objects#isNull(Object)} over the equivalent lambda function. */
|
||||
static final class IsNullFunction<T> {
|
||||
@BeforeTemplate
|
||||
|
||||
@@ -369,13 +369,11 @@ final class ReactorRules {
|
||||
static final class MonoIdentity<T> {
|
||||
@BeforeTemplate
|
||||
Mono<T> before(Mono<T> mono) {
|
||||
return mono.switchIfEmpty(Mono.empty());
|
||||
return Refaster.anyOf(
|
||||
mono.switchIfEmpty(Mono.empty()), mono.flux().next(), mono.flux().singleOrEmpty());
|
||||
}
|
||||
|
||||
// XXX: Review the suppression once NullAway has better support for generics. Keep an eye on
|
||||
// https://github.com/uber/NullAway/issues?q=is%3Aopen+generics.
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("NullAway" /* False positive. */)
|
||||
Mono<@Nullable Void> before2(Mono<@Nullable Void> mono) {
|
||||
return mono.then();
|
||||
}
|
||||
@@ -476,6 +474,11 @@ final class ReactorRules {
|
||||
* Flux}.
|
||||
*/
|
||||
abstract static class MonoFlatMapToFlux<T, S> {
|
||||
// XXX: It would be more expressive if this `@Placeholder` were replaced with a `Function<?
|
||||
// super T, ? extends Mono<? extends S>>` parameter, so that compatible non-lambda expression
|
||||
// arguments to `flatMapMany` are also matched. However, the type inferred for lambda and method
|
||||
// reference expressions passed to `flatMapMany` appears to always be `Function<T, Publisher<?
|
||||
// extends S>>`, which doesn't match. Find a solution.
|
||||
@Placeholder(allowsIdentity = true)
|
||||
abstract Mono<S> transformation(@MayOptionallyUse T value);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.Set;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.testng.Assert;
|
||||
import org.testng.Assert.ThrowingRunnable;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/**
|
||||
* Refaster rules that replace TestNG assertions with equivalent AssertJ assertions.
|
||||
@@ -72,6 +73,7 @@ import org.testng.Assert.ThrowingRunnable;
|
||||
// XXX: As-is these rules do not result in a complete migration:
|
||||
// - Expressions containing comments are skipped due to a limitation of Refaster.
|
||||
// - Assertions inside lambda expressions are also skipped. Unclear why.
|
||||
@OnlineDocumentation
|
||||
final class TestNGToAssertJRules {
|
||||
private TestNGToAssertJRules() {}
|
||||
|
||||
|
||||
@@ -3,21 +3,16 @@ package tech.picnic.errorprone.bugpatterns;
|
||||
import static com.google.common.base.Predicates.containsPattern;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class AmbiguousJsonCreatorTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(AmbiguousJsonCreator.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"X",
|
||||
containsPattern("`JsonCreator.Mode` should be set for single-argument creators"));
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(AmbiguousJsonCreator.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(AmbiguousJsonCreator.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"X", containsPattern("`JsonCreator.Mode` should be set for single-argument creators"))
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import com.fasterxml.jackson.annotation.JsonCreator;",
|
||||
@@ -118,7 +113,7 @@ final class AmbiguousJsonCreatorTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(AmbiguousJsonCreator.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.fasterxml.jackson.annotation.JsonCreator;",
|
||||
@@ -143,6 +138,6 @@ final class AmbiguousJsonCreatorTest {
|
||||
" return FOO;",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH);
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class AssertJIsNullTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(AssertJIsNull.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(AssertJIsNull.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(AssertJIsNull.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
@@ -38,7 +33,7 @@ final class AssertJIsNullTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(AssertJIsNull.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class AutowiredConstructorTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(AutowiredConstructor.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(AutowiredConstructor.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(AutowiredConstructor.class, getClass())
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import com.google.errorprone.annotations.Immutable;",
|
||||
@@ -71,7 +66,7 @@ final class AutowiredConstructorTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(AutowiredConstructor.class, getClass())
|
||||
.addInputLines(
|
||||
"Container.java",
|
||||
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class CanonicalAnnotationSyntaxTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass())
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
@@ -133,7 +128,7 @@ final class CanonicalAnnotationSyntaxTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass())
|
||||
.addInputLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
|
||||
@@ -8,14 +8,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class CollectorMutabilityTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(CollectorMutability.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(CollectorMutability.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
@@ -67,7 +62,7 @@ final class CollectorMutabilityTest {
|
||||
|
||||
@Test
|
||||
void identificationWithoutGuavaOnClasspath() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
.withClasspath()
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
@@ -84,7 +79,7 @@ final class CollectorMutabilityTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
@@ -141,7 +136,7 @@ final class CollectorMutabilityTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
.setFixChooser(SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class EmptyMethodTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
@@ -69,7 +64,7 @@ final class EmptyMethodTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"final class A {",
|
||||
|
||||
@@ -6,15 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ErrorProneTestHelperSourceFormatTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
ErrorProneTestHelperSourceFormat.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
@@ -63,7 +57,7 @@ final class ErrorProneTestHelperSourceFormatTest {
|
||||
* Verifies that import sorting and code formatting is performed unconditionally, while unused
|
||||
* imports are removed unless part of a `BugCheckerRefactoringTestHelper` expected output file.
|
||||
*/
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
|
||||
@@ -4,12 +4,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ExplicitEnumOrderingTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(ExplicitEnumOrdering.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(ExplicitEnumOrdering.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.lang.annotation.RetentionPolicy.CLASS;",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugCheckerRefactoringTestHelper.newInstance;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
@@ -9,14 +7,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class FluxFlatMapUsageTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(FluxFlatMapUsage.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
newInstance(FluxFlatMapUsage.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.function.BiFunction;",
|
||||
@@ -73,7 +66,7 @@ final class FluxFlatMapUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
.setFixChooser(FixChoosers.FIRST)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
@@ -108,7 +101,7 @@ final class FluxFlatMapUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class FormatStringConcatenationTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(FormatStringConcatenation.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(FormatStringConcatenation.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(FormatStringConcatenation.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
@@ -309,7 +304,7 @@ final class FormatStringConcatenationTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(FormatStringConcatenation.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
|
||||
@@ -7,14 +7,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class IdentityConversionTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(IdentityConversion.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(IdentityConversion.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(IdentityConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.errorprone.matchers.Matchers.instanceMethod;",
|
||||
@@ -184,7 +179,7 @@ final class IdentityConversionTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(IdentityConversion.class, getClass())
|
||||
.setFixChooser(FixChoosers.FIRST)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
@@ -291,7 +286,7 @@ final class IdentityConversionTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(IdentityConversion.class, getClass())
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ImmutablesSortedSetComparatorTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ContiguousSet;",
|
||||
@@ -109,7 +104,7 @@ final class ImmutablesSortedSetComparatorTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
@@ -147,7 +142,7 @@ final class ImmutablesSortedSetComparatorTest {
|
||||
|
||||
@Test
|
||||
void replacementWithImportClash() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
.addInputLines(
|
||||
"MySpringService.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class IsInstanceLambdaUsageTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(IsInstanceLambdaUsage.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(IsInstanceLambdaUsage.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(IsInstanceLambdaUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
@@ -46,7 +41,7 @@ final class IsInstanceLambdaUsageTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(IsInstanceLambdaUsage.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class JUnitClassModifiersTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(JUnitClassModifiers.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitClassModifiers.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(JUnitClassModifiers.class, getClass())
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
@@ -98,7 +93,7 @@ final class JUnitClassModifiersTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitClassModifiers.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class JUnitMethodDeclarationTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(JUnitMethodDeclaration.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitMethodDeclaration.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(JUnitMethodDeclaration.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
@@ -345,7 +340,7 @@ final class JUnitMethodDeclarationTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitMethodDeclaration.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
|
||||
@@ -7,22 +7,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class LexicographicalAnnotationAttributeListingTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(
|
||||
LexicographicalAnnotationAttributeListing.class, getClass());
|
||||
private final CompilationTestHelper restrictedCompilationTestHelper =
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Includes=pkg.A.Foo,pkg.A.Bar",
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value"));
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
LexicographicalAnnotationAttributeListing.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.math.RoundingMode.DOWN;",
|
||||
@@ -165,7 +152,8 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
// `CanonicalAnnotationSyntax` checker correct the situation in a subsequent run.
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.math.RoundingMode.DOWN;",
|
||||
@@ -246,7 +234,11 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
@Test
|
||||
void filtering() {
|
||||
/* Some violations are not flagged because they are not in- or excluded. */
|
||||
restrictedCompilationTestHelper
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Includes=pkg.A.Foo,pkg.A.Bar",
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value"))
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
|
||||
@@ -6,15 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class LexicographicalAnnotationListingTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationListing.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
LexicographicalAnnotationListing.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationListing.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.lang.annotation.ElementType;",
|
||||
@@ -133,7 +127,7 @@ final class LexicographicalAnnotationListingTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(LexicographicalAnnotationListing.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.lang.annotation.ElementType;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class MethodReferenceUsageTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(MethodReferenceUsage.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(MethodReferenceUsage.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(MethodReferenceUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.Streams;",
|
||||
@@ -323,7 +318,7 @@ final class MethodReferenceUsageTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(MethodReferenceUsage.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.Collections.emptyList;",
|
||||
|
||||
@@ -6,16 +6,12 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class MissingRefasterAnnotationTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(MissingRefasterAnnotation.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"X",
|
||||
containsPattern(
|
||||
"The Refaster rule contains a method without any Refaster annotations"));
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(MissingRefasterAnnotation.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"X",
|
||||
containsPattern("The Refaster rule contains a method without any Refaster annotations"))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.AfterTemplate;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class MockitoStubbingTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(MockitoStubbing.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(MockitoStubbing.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(MockitoStubbing.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.mockito.ArgumentMatchers.eq;",
|
||||
@@ -55,7 +50,7 @@ final class MockitoStubbingTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(MockitoStubbing.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.mockito.ArgumentMatchers.eq;",
|
||||
|
||||
@@ -4,12 +4,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class NestedOptionalsTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(NestedOptionals.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(NestedOptionals.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Optional;",
|
||||
@@ -42,7 +39,7 @@ final class NestedOptionalsTest {
|
||||
|
||||
@Test
|
||||
void identificationOptionalTypeNotLoaded() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(NestedOptionals.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.time.Duration;",
|
||||
|
||||
@@ -7,14 +7,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class NonEmptyMonoTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(NonEmptyMono.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(NonEmptyMono.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(NonEmptyMono.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
@@ -111,7 +106,7 @@ final class NonEmptyMonoTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(NonEmptyMono.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
|
||||
@@ -5,22 +5,21 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
// XXX: There are no tests for multiple replacements within the same expression:
|
||||
// - Error Prone doesn't currently support this, it seems.
|
||||
// - The `BugCheckerRefactoringTestHelper` throws an exception in this case.
|
||||
// - During actual compilation only the first replacement is applied.
|
||||
// XXX: Can we perhaps work-around this by describing the fixes in reverse order?
|
||||
final class PrimitiveComparisonTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass());
|
||||
|
||||
// XXX: There are no tests for multiple replacements within the same expression:
|
||||
// - Error Prone doesn't currently support this, it seems.
|
||||
// - The `BugCheckerRefactoringTestHelper` throws an exception in this case.
|
||||
// - During actual compilation only the first replacement is applied.
|
||||
// XXX: Can we perhaps work-around this by describing the fixes in reverse order?
|
||||
|
||||
// The logic for `char` and `short` is exactly analogous to the `byte` case.
|
||||
/**
|
||||
* Tests the identification of {@code byte} comparisons for which boxing can be avoided.
|
||||
*
|
||||
* @implNote The logic for {@code char} and {@code short} is exactly analogous to the {@code byte}
|
||||
* case.
|
||||
*/
|
||||
@Test
|
||||
void byteComparison() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -120,7 +119,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void intComparison() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -227,7 +226,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void longComparison() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -318,7 +317,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void floatComparison() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -386,7 +385,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void doubleComparison() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -461,7 +460,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void stringComparison() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -497,7 +496,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithPrimitiveVariants() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -577,7 +576,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithBoxedVariants() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -643,7 +642,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithPrimitiveVariantsUsingStaticImports() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.Comparator.comparing;",
|
||||
@@ -682,7 +681,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithBoxedVariantsUsingStaticImports() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.Comparator.comparingDouble;",
|
||||
@@ -723,7 +722,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithPrimitiveVariantsInComplexSyntacticalContext() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -755,7 +754,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithBoxedVariantsInComplexSyntacticalContext() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
|
||||
@@ -12,13 +12,6 @@ import org.junit.jupiter.api.Test;
|
||||
final class RedundantStringConversionTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass());
|
||||
private final CompilationTestHelper customizedCompilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)"));
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(RedundantStringConversion.class, getClass());
|
||||
|
||||
@Test
|
||||
void identificationOfIdentityTransformation() {
|
||||
@@ -416,7 +409,10 @@ final class RedundantStringConversionTest {
|
||||
|
||||
@Test
|
||||
void identificationOfCustomConversionMethod() {
|
||||
customizedCompilationTestHelper
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)"))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.math.RoundingMode;",
|
||||
@@ -509,7 +505,7 @@ final class RedundantStringConversionTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class RefasterAnyOfUsageTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RefasterAnyOfUsage.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterAnyOfUsage.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(RefasterAnyOfUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
@@ -38,7 +33,7 @@ final class RefasterAnyOfUsageTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterAnyOfUsage.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class RefasterRuleModifiersTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RefasterRuleModifiers.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterRuleModifiers.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(RefasterRuleModifiers.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
@@ -136,7 +131,7 @@ final class RefasterRuleModifiersTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterRuleModifiers.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
|
||||
@@ -4,12 +4,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class RequestMappingAnnotationTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RequestMappingAnnotation.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(RequestMappingAnnotation.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.io.InputStream;",
|
||||
|
||||
@@ -4,12 +4,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class RequestParamTypeTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableBiMap;",
|
||||
@@ -63,4 +60,55 @@ final class RequestParamTypeTest {
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void identificationRestricted() {
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
|
||||
.setArgs(
|
||||
"-XepOpt:RequestParamType:SupportedCustomTypes=com.google.common.collect.ImmutableSet,com.google.common.collect.ImmutableSortedMultiset")
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableBiMap;",
|
||||
"import com.google.common.collect.ImmutableCollection;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import com.google.common.collect.ImmutableMultiset;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.common.collect.ImmutableSortedMultiset;",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"import org.springframework.web.bind.annotation.GetMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestParam;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableCollection(@RequestParam ImmutableCollection<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableList(@RequestParam ImmutableList<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A immutableSet(@RequestParam ImmutableSet<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A immutableSortedSet(@RequestParam ImmutableSortedSet<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableMultiset(@RequestParam ImmutableMultiset<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A immutableSortedMultiset(@RequestParam ImmutableSortedMultiset<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableMap(@RequestParam ImmutableMap<String, String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableBiMap(@RequestParam ImmutableBiMap<String, String> param);",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,9 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
final class ScheduledTransactionTraceTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(ScheduledTransactionTrace.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(ScheduledTransactionTrace.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(ScheduledTransactionTrace.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.newrelic.api.agent.Trace;",
|
||||
@@ -46,7 +41,7 @@ final class ScheduledTransactionTraceTest {
|
||||
|
||||
@Test
|
||||
void identificationWithoutNewRelicAgentApiOnClasspath() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(ScheduledTransactionTrace.class, getClass())
|
||||
.withClasspath(Scheduled.class)
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
@@ -61,7 +56,7 @@ final class ScheduledTransactionTraceTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(ScheduledTransactionTrace.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.newrelic.api.agent.Trace;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class Slf4jLogStatementTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(Slf4jLogStatement.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(Slf4jLogStatement.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(Slf4jLogStatement.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
@@ -96,7 +91,7 @@ final class Slf4jLogStatementTest {
|
||||
// XXX: Drop what's unused.
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(Slf4jLogStatement.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
|
||||
@@ -6,14 +6,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class SpringMvcAnnotationTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(SpringMvcAnnotation.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(SpringMvcAnnotation.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(SpringMvcAnnotation.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.DELETE;",
|
||||
@@ -85,7 +80,7 @@ final class SpringMvcAnnotationTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(SpringMvcAnnotation.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PATCH;",
|
||||
|
||||
@@ -8,11 +8,6 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class StaticImportTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(StaticImport.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(StaticImport.class, getClass());
|
||||
|
||||
@Test
|
||||
void candidateMethodsAreNotRedundant() {
|
||||
assertThat(StaticImport.STATIC_IMPORT_CANDIDATE_MEMBERS.keySet())
|
||||
@@ -33,7 +28,7 @@ final class StaticImportTest {
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(StaticImport.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
@@ -118,7 +113,7 @@ final class StaticImportTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(StaticImport.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.function.Predicate.not;",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugCheckerRefactoringTestHelper.newInstance;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
@@ -9,14 +7,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class StringCaseLocaleUsageTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(StringCaseLocaleUsage.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
newInstance(StringCaseLocaleUsage.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(StringCaseLocaleUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.util.Locale.ROOT;",
|
||||
@@ -54,7 +47,7 @@ final class StringCaseLocaleUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringCaseLocaleUsage.class, getClass())
|
||||
.setFixChooser(FixChoosers.FIRST)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
@@ -93,7 +86,7 @@ final class StringCaseLocaleUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringCaseLocaleUsage.class, getClass())
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -8,17 +8,12 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class StringJoinTest {
|
||||
private final CompilationTestHelper compilationHelper =
|
||||
CompilationTestHelper.newInstance(StringJoin.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"valueOf", containsPattern("Prefer `String#valueOf` over `String#format`"))
|
||||
.expectErrorMessage("join", containsPattern("Prefer `String#join` over `String#format`"));
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringJoin.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationHelper
|
||||
CompilationTestHelper.newInstance(StringJoin.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"valueOf", containsPattern("Prefer `String#valueOf` over `String#format`"))
|
||||
.expectErrorMessage("join", containsPattern("Prefer `String#join` over `String#format`"))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Formattable;",
|
||||
@@ -63,7 +58,7 @@ final class StringJoinTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringJoin.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
|
||||
@@ -4,12 +4,9 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class TimeZoneUsageTest {
|
||||
private final CompilationTestHelper compilationHelper =
|
||||
CompilationTestHelper.newInstance(TimeZoneUsage.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationHelper
|
||||
CompilationTestHelper.newInstance(TimeZoneUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.time.ZoneOffset.UTC;",
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ConflictDetectionTest {
|
||||
@Test
|
||||
void matcher() {
|
||||
CompilationTestHelper.newInstance(RenameBlockerFlagger.class, getClass())
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import static pkg.A.B.method3t;",
|
||||
"",
|
||||
"import pkg.A.method4t;",
|
||||
"",
|
||||
"class A {",
|
||||
" void method1() {",
|
||||
" method3t();",
|
||||
" method4(method4t.class);",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: a method named `method2t` is already defined in this class or a",
|
||||
" // supertype",
|
||||
" void method2() {}",
|
||||
"",
|
||||
" void method2t() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: `method3t` is already statically imported",
|
||||
" void method3() {}",
|
||||
"",
|
||||
" void method4(Object o) {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: `int` is not a valid identifier",
|
||||
" void in() {}",
|
||||
"",
|
||||
" static class B {",
|
||||
" static void method3t() {}",
|
||||
" }",
|
||||
"",
|
||||
" class method4t {}",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that uses {@link ConflictDetection#findMethodRenameBlocker(MethodSymbol,
|
||||
* String, VisitorState)} to flag methods of which the name cannot be suffixed with a {@code t}.
|
||||
*/
|
||||
@BugPattern(summary = "Interacts with `ConflictDetection` for testing purposes", severity = ERROR)
|
||||
public static final class RenameBlockerFlagger extends BugChecker implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||
return ConflictDetection.findMethodRenameBlocker(
|
||||
ASTHelpers.getSymbol(tree), tree.getName() + "t", state)
|
||||
.map(blocker -> buildDescription(tree).setMessage(blocker).build())
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.ErrorProneOptions;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
final class FlagsTest {
|
||||
private static Stream<Arguments> getListTestCases() {
|
||||
/* { args, flag, expected } */
|
||||
return Stream.of(
|
||||
arguments(ImmutableList.of(), "Foo", ImmutableList.of()),
|
||||
arguments(ImmutableList.of("-XepOpt:Foo=bar,baz"), "Qux", ImmutableList.of()),
|
||||
arguments(ImmutableList.of("-XepOpt:Foo="), "Foo", ImmutableList.of()),
|
||||
arguments(ImmutableList.of("-XepOpt:Foo=bar"), "Foo", ImmutableList.of("bar")),
|
||||
arguments(ImmutableList.of("-XepOpt:Foo=bar,baz"), "Foo", ImmutableList.of("bar", "baz")),
|
||||
arguments(ImmutableList.of("-XepOpt:Foo=,"), "Foo", ImmutableList.of("", "")));
|
||||
}
|
||||
|
||||
@MethodSource("getListTestCases")
|
||||
@ParameterizedTest
|
||||
void getList(ImmutableList<String> args, String flag, ImmutableList<String> expected) {
|
||||
assertThat(Flags.getList(ErrorProneOptions.processArgs(args).getFlags(), flag))
|
||||
.containsExactlyElementsOf(expected);
|
||||
}
|
||||
}
|
||||
@@ -40,9 +40,6 @@ final class MethodMatcherFactoryTest {
|
||||
"com.example.A#m2(java.lang.String)",
|
||||
"com.example.sub.B#m3(int,int)"));
|
||||
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(MatchedMethodsFlagger.class, getClass());
|
||||
|
||||
@Test
|
||||
void createWithMalformedSignatures() {
|
||||
MethodMatcherFactory factory = new MethodMatcherFactory();
|
||||
@@ -58,7 +55,7 @@ final class MethodMatcherFactoryTest {
|
||||
|
||||
@Test
|
||||
void matcher() {
|
||||
compilationTestHelper
|
||||
CompilationTestHelper.newInstance(MatchedMethodsFlagger.class, getClass())
|
||||
.addSourceLines(
|
||||
"com/example/A.java",
|
||||
"package com.example;",
|
||||
|
||||
@@ -49,7 +49,9 @@ final class RefasterRulesTest {
|
||||
ImmutableSortedMultisetRules.class,
|
||||
ImmutableSortedSetRules.class,
|
||||
IntStreamRules.class,
|
||||
JooqRules.class,
|
||||
JUnitRules.class,
|
||||
JUnitToAssertJRules.class,
|
||||
LongStreamRules.class,
|
||||
MapEntryRules.class,
|
||||
MapRules.class,
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(
|
||||
Assertions.class,
|
||||
assertDoesNotThrow(() -> null),
|
||||
assertInstanceOf(null, null),
|
||||
assertThrows(null, null),
|
||||
assertThrowsExactly(null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
(Runnable) () -> assertNotSame(null, null),
|
||||
(Runnable) () -> assertNull(null),
|
||||
(Runnable) () -> assertSame(null, null),
|
||||
(Runnable) () -> assertTrue(true));
|
||||
}
|
||||
|
||||
void testThrowNewAssertionError() {
|
||||
Assertions.fail();
|
||||
}
|
||||
|
||||
Object testFailWithMessage() {
|
||||
return Assertions.fail("foo");
|
||||
}
|
||||
|
||||
Object testFailWithMessageAndThrowable() {
|
||||
return Assertions.fail("foo", new IllegalStateException());
|
||||
}
|
||||
|
||||
void testFailWithThrowable() {
|
||||
Assertions.fail(new IllegalStateException());
|
||||
}
|
||||
|
||||
void testAssertThatIsTrue() {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsTrue() {
|
||||
assertTrue(true, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsTrue() {
|
||||
assertTrue(true, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatIsFalse() {
|
||||
assertFalse(true);
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsFalse() {
|
||||
assertFalse(true, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsFalse() {
|
||||
assertFalse(true, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatIsNull() {
|
||||
assertNull(new Object());
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsNull() {
|
||||
assertNull(new Object(), "foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsNull() {
|
||||
assertNull(new Object(), () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatIsNotNull() {
|
||||
assertNotNull(new Object());
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsNotNull() {
|
||||
assertNotNull(new Object(), "foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsNotNull() {
|
||||
assertNotNull(new Object(), () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatIsSameAs() {
|
||||
assertSame("foo", "bar");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsSameAs() {
|
||||
assertSame("foo", "bar", "baz");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsSameAs() {
|
||||
assertSame("foo", "bar", () -> "baz");
|
||||
}
|
||||
|
||||
void testAssertThatIsNotSameAs() {
|
||||
assertNotSame("foo", "bar");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsNotSameAs() {
|
||||
assertNotSame("foo", "bar", "baz");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsNotSameAs() {
|
||||
assertNotSame("foo", "bar", () -> "baz");
|
||||
}
|
||||
|
||||
void testAssertThatThrownByIsExactlyInstanceOf() {
|
||||
assertThrowsExactly(IllegalStateException.class, () -> {});
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageStringIsExactlyInstanceOf() {
|
||||
assertThrowsExactly(IllegalStateException.class, () -> {}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageSupplierIsExactlyInstanceOf() {
|
||||
assertThrowsExactly(IllegalStateException.class, () -> {}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatThrownByIsInstanceOf() {
|
||||
assertThrows(IllegalStateException.class, () -> {});
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageStringIsInstanceOf() {
|
||||
assertThrows(IllegalStateException.class, () -> {}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageSupplierIsInstanceOf() {
|
||||
assertThrows(IllegalStateException.class, () -> {}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatCodeDoesNotThrowAnyException() {
|
||||
assertDoesNotThrow(() -> {});
|
||||
assertDoesNotThrow(() -> toString());
|
||||
}
|
||||
|
||||
void testAssertThatCodeWithFailMessageStringDoesNotThrowAnyException() {
|
||||
assertDoesNotThrow(() -> {}, "foo");
|
||||
assertDoesNotThrow(() -> toString(), "bar");
|
||||
}
|
||||
|
||||
void testAssertThatCodeWithFailMessageSupplierDoesNotThrowAnyException() {
|
||||
assertDoesNotThrow(() -> {}, () -> "foo");
|
||||
assertDoesNotThrow(() -> toString(), () -> "bar");
|
||||
}
|
||||
|
||||
void testAssertThatIsInstanceOf() {
|
||||
assertInstanceOf(Object.class, new Object());
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsInstanceOf() {
|
||||
assertInstanceOf(Object.class, new Object(), "foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsInstanceOf() {
|
||||
assertInstanceOf(Object.class, new Object(), () -> "foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(
|
||||
Assertions.class,
|
||||
assertDoesNotThrow(() -> null),
|
||||
assertInstanceOf(null, null),
|
||||
assertThrows(null, null),
|
||||
assertThrowsExactly(null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
(Runnable) () -> assertNotSame(null, null),
|
||||
(Runnable) () -> assertNull(null),
|
||||
(Runnable) () -> assertSame(null, null),
|
||||
(Runnable) () -> assertTrue(true));
|
||||
}
|
||||
|
||||
void testThrowNewAssertionError() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
Object testFailWithMessage() {
|
||||
return fail("foo");
|
||||
}
|
||||
|
||||
Object testFailWithMessageAndThrowable() {
|
||||
return fail("foo", new IllegalStateException());
|
||||
}
|
||||
|
||||
void testFailWithThrowable() {
|
||||
throw new AssertionError(new IllegalStateException());
|
||||
}
|
||||
|
||||
void testAssertThatIsTrue() {
|
||||
assertThat(true).isTrue();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsTrue() {
|
||||
assertThat(true).withFailMessage("foo").isTrue();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsTrue() {
|
||||
assertThat(true).withFailMessage(() -> "foo").isTrue();
|
||||
}
|
||||
|
||||
void testAssertThatIsFalse() {
|
||||
assertThat(true).isFalse();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsFalse() {
|
||||
assertThat(true).withFailMessage("foo").isFalse();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsFalse() {
|
||||
assertThat(true).withFailMessage(() -> "foo").isFalse();
|
||||
}
|
||||
|
||||
void testAssertThatIsNull() {
|
||||
assertThat(new Object()).isNull();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsNull() {
|
||||
assertThat(new Object()).withFailMessage("foo").isNull();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsNull() {
|
||||
assertThat(new Object()).withFailMessage(() -> "foo").isNull();
|
||||
}
|
||||
|
||||
void testAssertThatIsNotNull() {
|
||||
assertThat(new Object()).isNotNull();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsNotNull() {
|
||||
assertThat(new Object()).withFailMessage("foo").isNotNull();
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsNotNull() {
|
||||
assertThat(new Object()).withFailMessage(() -> "foo").isNotNull();
|
||||
}
|
||||
|
||||
void testAssertThatIsSameAs() {
|
||||
assertThat("bar").isSameAs("foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsSameAs() {
|
||||
assertThat("bar").withFailMessage("baz").isSameAs("foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsSameAs() {
|
||||
assertThat("bar").withFailMessage(() -> "baz").isSameAs("foo");
|
||||
}
|
||||
|
||||
void testAssertThatIsNotSameAs() {
|
||||
assertThat("bar").isNotSameAs("foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsNotSameAs() {
|
||||
assertThat("bar").withFailMessage("baz").isNotSameAs("foo");
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsNotSameAs() {
|
||||
assertThat("bar").withFailMessage(() -> "baz").isNotSameAs("foo");
|
||||
}
|
||||
|
||||
void testAssertThatThrownByIsExactlyInstanceOf() {
|
||||
assertThatThrownBy(() -> {}).isExactlyInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageStringIsExactlyInstanceOf() {
|
||||
assertThatThrownBy(() -> {})
|
||||
.withFailMessage("foo")
|
||||
.isExactlyInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageSupplierIsExactlyInstanceOf() {
|
||||
assertThatThrownBy(() -> {})
|
||||
.withFailMessage(() -> "foo")
|
||||
.isExactlyInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
void testAssertThatThrownByIsInstanceOf() {
|
||||
assertThatThrownBy(() -> {}).isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageStringIsInstanceOf() {
|
||||
assertThatThrownBy(() -> {}).withFailMessage("foo").isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
void testAssertThatThrownByWithFailMessageSupplierIsInstanceOf() {
|
||||
assertThatThrownBy(() -> {})
|
||||
.withFailMessage(() -> "foo")
|
||||
.isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
void testAssertThatCodeDoesNotThrowAnyException() {
|
||||
assertThatCode(() -> {}).doesNotThrowAnyException();
|
||||
assertThatCode(() -> toString()).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
void testAssertThatCodeWithFailMessageStringDoesNotThrowAnyException() {
|
||||
assertThatCode(() -> {}).withFailMessage("foo").doesNotThrowAnyException();
|
||||
assertThatCode(() -> toString()).withFailMessage("bar").doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
void testAssertThatCodeWithFailMessageSupplierDoesNotThrowAnyException() {
|
||||
assertThatCode(() -> {}).withFailMessage(() -> "foo").doesNotThrowAnyException();
|
||||
assertThatCode(() -> toString()).withFailMessage(() -> "bar").doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
void testAssertThatIsInstanceOf() {
|
||||
assertThat(new Object()).isInstanceOf(Object.class);
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageStringIsInstanceOf() {
|
||||
assertThat(new Object()).withFailMessage("foo").isInstanceOf(Object.class);
|
||||
}
|
||||
|
||||
void testAssertThatWithFailMessageSupplierIsInstanceOf() {
|
||||
assertThat(new Object()).withFailMessage(() -> "foo").isInstanceOf(Object.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.jooq.impl.DSL;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class JooqRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Stream<?> testResultQueryFetchStream() {
|
||||
return DSL.select().stream();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.jooq.impl.DSL;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class JooqRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Stream<?> testResultQueryFetchStream() {
|
||||
return DSL.select().fetch().stream();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.math.RoundingMode;
|
||||
@@ -11,7 +13,7 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
final class MapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(HashMap.class);
|
||||
return ImmutableSet.of(HashMap.class, requireNonNullElse(null, null));
|
||||
}
|
||||
|
||||
Map<RoundingMode, String> testCreateEnumMap() {
|
||||
@@ -22,6 +24,10 @@ final class MapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableMap.of(1, "foo").getOrDefault("bar", null);
|
||||
}
|
||||
|
||||
String testMapGetOrDefault() {
|
||||
return requireNonNullElse(ImmutableMap.of(1, "foo").get("bar"), "baz");
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testMapIsEmpty() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of("foo", 1).keySet().isEmpty(),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.math.RoundingMode;
|
||||
@@ -12,7 +14,7 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
final class MapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(HashMap.class);
|
||||
return ImmutableSet.of(HashMap.class, requireNonNullElse(null, null));
|
||||
}
|
||||
|
||||
Map<RoundingMode, String> testCreateEnumMap() {
|
||||
@@ -23,6 +25,10 @@ final class MapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableMap.of(1, "foo").get("bar");
|
||||
}
|
||||
|
||||
String testMapGetOrDefault() {
|
||||
return ImmutableMap.of(1, "foo").getOrDefault("bar", "baz");
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testMapIsEmpty() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of("foo", 1).isEmpty(),
|
||||
|
||||
@@ -3,13 +3,14 @@ package tech.picnic.errorprone.refasterrules;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(MoreObjects.class);
|
||||
return ImmutableSet.of(MoreObjects.class, Optional.class);
|
||||
}
|
||||
|
||||
boolean testIsNull() {
|
||||
@@ -20,8 +21,13 @@ final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Objects.nonNull("foo");
|
||||
}
|
||||
|
||||
String testRequireNonNullElse() {
|
||||
return MoreObjects.firstNonNull("foo", "bar");
|
||||
ImmutableSet<String> testRequireNonNullElse() {
|
||||
return ImmutableSet.of(
|
||||
MoreObjects.firstNonNull("foo", "bar"), Optional.ofNullable("baz").orElse("qux"));
|
||||
}
|
||||
|
||||
String testRequireNonNullElseGet() {
|
||||
return Optional.ofNullable("foo").orElseGet(() -> "bar");
|
||||
}
|
||||
|
||||
long testIsNullFunction() {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
import static java.util.Objects.requireNonNullElseGet;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(MoreObjects.class);
|
||||
return ImmutableSet.of(MoreObjects.class, Optional.class);
|
||||
}
|
||||
|
||||
boolean testIsNull() {
|
||||
@@ -22,8 +24,12 @@ final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return "foo" != null;
|
||||
}
|
||||
|
||||
String testRequireNonNullElse() {
|
||||
return requireNonNullElse("foo", "bar");
|
||||
ImmutableSet<String> testRequireNonNullElse() {
|
||||
return ImmutableSet.of(requireNonNullElse("foo", "bar"), requireNonNullElse("baz", "qux"));
|
||||
}
|
||||
|
||||
String testRequireNonNullElseGet() {
|
||||
return requireNonNullElseGet("foo", () -> "bar");
|
||||
}
|
||||
|
||||
long testIsNullFunction() {
|
||||
|
||||
@@ -116,7 +116,11 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<?>> testMonoIdentity() {
|
||||
return ImmutableSet.of(Mono.just(1).switchIfEmpty(Mono.empty()), Mono.<Void>empty().then());
|
||||
return ImmutableSet.of(
|
||||
Mono.just(1).switchIfEmpty(Mono.empty()),
|
||||
Mono.just(2).flux().next(),
|
||||
Mono.just(3).flux().singleOrEmpty(),
|
||||
Mono.<Void>empty().then());
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<Integer>> testFluxSwitchIfEmptyOfEmptyPublisher() {
|
||||
|
||||
@@ -121,7 +121,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<?>> testMonoIdentity() {
|
||||
return ImmutableSet.of(Mono.just(1), Mono.<Void>empty());
|
||||
return ImmutableSet.of(Mono.just(1), Mono.just(2), Mono.just(3), Mono.<Void>empty());
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<Integer>> testFluxSwitchIfEmptyOfEmptyPublisher() {
|
||||
|
||||
@@ -24,7 +24,7 @@ final class TestNGToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(
|
||||
(Runnable) () -> assertEquals(new byte[0], null),
|
||||
(Runnable) () -> assertEqualsNoOrder(null, null),
|
||||
(Runnable) () -> assertEqualsNoOrder((Object[]) null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotEquals(new byte[0], null),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
|
||||
@@ -29,7 +29,7 @@ final class TestNGToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
public ImmutableSet<?> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(
|
||||
(Runnable) () -> assertEquals(new byte[0], null),
|
||||
(Runnable) () -> assertEqualsNoOrder(null, null),
|
||||
(Runnable) () -> assertEqualsNoOrder((Object[]) null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotEquals(new byte[0], null),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
|
||||
150
pom.xml
150
pom.xml
@@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.6.1-SNAPSHOT</version>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Picnic :: Error Prone Support</name>
|
||||
@@ -39,6 +39,7 @@
|
||||
</developers>
|
||||
|
||||
<modules>
|
||||
<module>documentation-support</module>
|
||||
<module>error-prone-contrib</module>
|
||||
<module>refaster-compiler</module>
|
||||
<module>refaster-runner</module>
|
||||
@@ -148,16 +149,16 @@
|
||||
<version.auto-service>1.0.1</version.auto-service>
|
||||
<version.auto-value>1.10.1</version.auto-value>
|
||||
<version.error-prone>${version.error-prone-orig}</version.error-prone>
|
||||
<version.error-prone-fork>v${version.error-prone-orig}-picnic-2</version.error-prone-fork>
|
||||
<version.error-prone-orig>2.16</version.error-prone-orig>
|
||||
<version.error-prone-slf4j>0.1.16</version.error-prone-slf4j>
|
||||
<version.error-prone-fork>v${version.error-prone-orig}-picnic-1</version.error-prone-fork>
|
||||
<version.error-prone-orig>2.18.0</version.error-prone-orig>
|
||||
<version.error-prone-slf4j>0.1.18</version.error-prone-slf4j>
|
||||
<version.guava-beta-checker>1.0</version.guava-beta-checker>
|
||||
<version.jdk>11</version.jdk>
|
||||
<version.maven>3.8.6</version.maven>
|
||||
<version.mockito>4.11.0</version.mockito>
|
||||
<version.maven>3.8.7</version.maven>
|
||||
<version.mockito>5.1.1</version.mockito>
|
||||
<version.nopen-checker>1.0.1</version.nopen-checker>
|
||||
<version.nullaway>0.10.5</version.nullaway>
|
||||
<version.pitest-git>1.0.3</version.pitest-git>
|
||||
<version.nullaway>0.10.9</version.nullaway>
|
||||
<version.pitest-git>1.0.4</version.pitest-git>
|
||||
<version.surefire>2.22.2</version.surefire>
|
||||
</properties>
|
||||
|
||||
@@ -188,6 +189,11 @@
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<version>${version.error-prone}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>documentation-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-compiler</artifactId>
|
||||
@@ -211,7 +217,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson</groupId>
|
||||
<artifactId>jackson-bom</artifactId>
|
||||
<version>2.14.1</version>
|
||||
<version>2.14.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -269,7 +275,7 @@
|
||||
<dependency>
|
||||
<groupId>com.newrelic.agent.java</groupId>
|
||||
<artifactId>newrelic-api</artifactId>
|
||||
<version>7.11.1</version>
|
||||
<version>8.0.0</version>
|
||||
</dependency>
|
||||
<!-- Specified as a workaround for
|
||||
https://github.com/mojohaus/versions-maven-plugin/issues/244. -->
|
||||
@@ -281,7 +287,7 @@
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
<version>2022.0.1</version>
|
||||
<version>2022.0.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -298,7 +304,7 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>2.2.7</version>
|
||||
<version>2.2.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
@@ -322,6 +328,11 @@
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.13.0</version>
|
||||
</dependency>
|
||||
<!-- Specified so that Renovate will file Maven upgrade PRs, which
|
||||
subsequently will cause `maven-enforcer-plugin` to require that
|
||||
developers build the project using the latest Maven release. -->
|
||||
@@ -337,13 +348,15 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.23.1</version>
|
||||
<artifactId>assertj-bom</artifactId>
|
||||
<version>3.24.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.28.0</version>
|
||||
<version>3.30.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
@@ -355,6 +368,11 @@
|
||||
<artifactId>value-annotations</artifactId>
|
||||
<version>2.9.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
<version>3.16.14</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
@@ -363,7 +381,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.9.1</version>
|
||||
<version>5.9.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -382,19 +400,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>5.3.24</version>
|
||||
<version>5.3.25</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<version>2.7.7</version>
|
||||
<version>2.7.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>7.4.0</version>
|
||||
<version>7.7.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
@@ -405,7 +423,7 @@
|
||||
<plugin>
|
||||
<groupId>com.github.ekryd.sortpom</groupId>
|
||||
<artifactId>sortpom-maven-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.2.1</version>
|
||||
<configuration>
|
||||
<createBackupFile>false</createBackupFile>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
@@ -520,7 +538,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.2.1</version>
|
||||
<configuration>
|
||||
<checkstyleRules>
|
||||
<!-- We only enable rules that are not enforced by
|
||||
@@ -686,10 +704,6 @@
|
||||
<!-- Instead, please use
|
||||
`com.google.common.collect.Streams`. -->
|
||||
</property>
|
||||
<property name="illegalClasses" value="org\.junit\.jupiter\.api\.Assertions(\..*?)?">
|
||||
<!-- Instead, please use
|
||||
`org.assertj.core.api.Assertions`. -->
|
||||
</property>
|
||||
<property name="illegalClasses" value="org\.springframework\.stereotype\.(Component|Controller|Service)">
|
||||
<!-- We don't use Spring's
|
||||
component scanning, so `@Component`
|
||||
@@ -712,6 +726,9 @@
|
||||
<module name="InnerAssignment" />
|
||||
<module name="InvalidJavadocPosition" />
|
||||
<module name="JavadocBlockTagLocation" />
|
||||
<module name="JavadocStyle">
|
||||
<property name="checkEmptyJavadoc" value="true" />
|
||||
</module>
|
||||
<module name="LocalVariableName" />
|
||||
<module name="MatchXpath">
|
||||
<property name="query" value="//BLOCK_COMMENT_BEGIN[./COMMENT_CONTENT[contains(@text, '@author')]]" />
|
||||
@@ -771,12 +788,12 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>10.5.0</version>
|
||||
<version>10.7.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.nohttp</groupId>
|
||||
<artifactId>nohttp-checkstyle</artifactId>
|
||||
<version>0.0.10</version>
|
||||
<version>0.0.11</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -850,6 +867,7 @@
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
|
||||
@@ -871,7 +889,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<!-- XXX: Drop `ignoreAllNonTestScoped` once
|
||||
https://issues.apache.org/jira/browse/MNG-6058 is
|
||||
@@ -886,7 +904,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<retryFailedDeploymentCount>3</retryFailedDeploymentCount>
|
||||
</configuration>
|
||||
@@ -894,12 +912,41 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.1</version>
|
||||
<configuration>
|
||||
<fail>false</fail>
|
||||
<rules>
|
||||
<banCircularDependencies />
|
||||
<banDependencyManagementScope />
|
||||
<banDuplicateClasses>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>dataflow-errorprone</artifactId>
|
||||
<!-- This package is contained in
|
||||
Checker Framework's `checker-qual` and
|
||||
`dataflow-errorprone` modules. Error
|
||||
Prone requires the latter, while Guava
|
||||
pulls in the former. Since the package
|
||||
contains mostly annotations, this is
|
||||
not expected to cause trouble in
|
||||
practice. -->
|
||||
<ignoreClasses>
|
||||
<ignoreClass>org.checkerframework.dataflow.qual.*</ignoreClass>
|
||||
</ignoreClasses>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<findAllDuplicates>true</findAllDuplicates>
|
||||
</banDuplicateClasses>
|
||||
<banDuplicatePomDependencyVersions />
|
||||
<!-- XXX: Enable this rule once it no longer
|
||||
"downloads the internet". See
|
||||
https://issues.apache.org/jira/browse/MENFORCER-467.
|
||||
<banDynamicVersions />-->
|
||||
<dependencyConvergence />
|
||||
<enforceBytecodeVersion>
|
||||
<maxJdkVersion>${version.jdk}</maxJdkVersion>
|
||||
</enforceBytecodeVersion>
|
||||
<requireEncoding>
|
||||
<acceptAsciiSubset>true</acceptAsciiSubset>
|
||||
<encoding>ISO-8859-1</encoding>
|
||||
@@ -911,8 +958,8 @@
|
||||
<requireMavenVersion>
|
||||
<version>${version.maven}</version>
|
||||
</requireMavenVersion>
|
||||
<requireNoRepositories />
|
||||
<requirePluginVersions />
|
||||
<requireSameVersionsReactor />
|
||||
<requireUpperBoundDeps>
|
||||
<excludes>
|
||||
<!-- XXX:
|
||||
@@ -1136,6 +1183,8 @@
|
||||
| BSD 3-clause
|
||||
| BSD License 3
|
||||
| Eclipse Distribution License (New BSD License)
|
||||
| Eclipse Distribution License - v 1.0
|
||||
| EDL 1.0
|
||||
| New BSD License
|
||||
</licenseMerge>
|
||||
<licenseMerge>
|
||||
@@ -1241,7 +1290,7 @@
|
||||
<plugin>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-maven</artifactId>
|
||||
<version>1.10.3</version>
|
||||
<version>1.11.0</version>
|
||||
<configuration>
|
||||
<excludedClasses>
|
||||
<!-- AutoValue generated classes. -->
|
||||
@@ -1280,7 +1329,7 @@
|
||||
<dependency>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-junit5-plugin</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -1334,6 +1383,30 @@
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<configuration>
|
||||
<rules>
|
||||
<banDuplicateClasses>
|
||||
<!-- The original
|
||||
`error_prone_annotations` dependency
|
||||
contains the same classes as those
|
||||
provided by the corresponding Picnic
|
||||
Error Prone fork artifact. -->
|
||||
<dependencies combine.children="append">
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<ignoreClasses>
|
||||
<ignoreClass>*</ignoreClass>
|
||||
</ignoreClasses>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</banDuplicateClasses>
|
||||
</rules>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
@@ -1577,6 +1650,10 @@
|
||||
<!-- XXX: Enable this once we open-source
|
||||
this library. -->
|
||||
-Xep:BetaApi:OFF
|
||||
<!-- XXX: Enable once compatible with
|
||||
`UnnecessarilyVisible`. See
|
||||
https://github.com/google/error-prone/issues/3706. -->
|
||||
-Xep:InjectOnBugCheckers:OFF
|
||||
<!-- We don't target JDK 7. -->
|
||||
-Xep:Java7ApiChecker:OFF
|
||||
<!-- We don't target JDK 8. -->
|
||||
@@ -1585,6 +1662,9 @@
|
||||
-Xep:StaticOrDefaultInterfaceMethod:OFF
|
||||
<!-- We generally discourage `var` use. -->
|
||||
-Xep:Varifier:OFF
|
||||
<!-- Yoda conditions are not always more
|
||||
readable than the alternative. -->
|
||||
-Xep:YodaCondition:OFF
|
||||
-XepOpt:CheckReturnValue:CheckAllConstructors=true
|
||||
<!-- XXX: Enable once there are fewer
|
||||
false-positives.
|
||||
@@ -1594,6 +1674,10 @@
|
||||
-XepOpt:NullAway:AssertsEnabled=true
|
||||
-XepOpt:NullAway:CheckOptionalEmptiness=true
|
||||
-XepOpt:Nullness:Conservative=false
|
||||
<!-- XXX: Enable once this check respects
|
||||
the compilation source version. See
|
||||
https://github.com/google/error-prone/pull/3646.
|
||||
-XepOpt:StatementSwitchToExpressionSwitch:EnableDirectConversion=true -->
|
||||
<!-- Append additional custom arguments. -->
|
||||
${error-prone.patch-args}
|
||||
${error-prone.self-check-args}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.6.1-SNAPSHOT</version>
|
||||
<version>0.8.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.6.1-SNAPSHOT</version>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-runner</artifactId>
|
||||
|
||||
@@ -161,6 +161,7 @@ public final class Refaster extends BugChecker implements CompilationUnitTreeMat
|
||||
* that could cause {@link VisitorState#reportMatch(Description)}} to override the reported
|
||||
* severity).
|
||||
*/
|
||||
@SuppressWarnings("RestrictedApiChecker" /* We create a heavily customized `Description` here. */)
|
||||
private static Description augmentDescription(
|
||||
Description description, Optional<SeverityLevel> severityOverride) {
|
||||
return Description.builder(
|
||||
|
||||
@@ -50,12 +50,6 @@ final class RefasterTest {
|
||||
"\\[Refaster Rule\\] FooRules\\.ExtraGrouping\\.StringOfSizeThreeRule: "
|
||||
+ "A custom description about matching three-char strings\\s+.+\\s+"
|
||||
+ "\\(see https://example.com/custom\\)"));
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(Refaster.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper restrictedRefactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(Refaster.class, getClass())
|
||||
.setArgs(
|
||||
"-XepOpt:Refaster:NamePattern=.*\\$(StringOfSizeZeroVerboseRule|StringOfSizeTwoRule)$");
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
@@ -220,7 +214,7 @@ final class RefasterTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(Refaster.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
@@ -246,7 +240,9 @@ final class RefasterTest {
|
||||
|
||||
@Test
|
||||
void restrictedReplacement() {
|
||||
restrictedRefactoringTestHelper
|
||||
BugCheckerRefactoringTestHelper.newInstance(Refaster.class, getClass())
|
||||
.setArgs(
|
||||
"-XepOpt:Refaster:NamePattern=.*\\$(StringOfSizeZeroVerboseRule|StringOfSizeTwoRule)$")
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.6.1-SNAPSHOT</version>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-support</artifactId>
|
||||
|
||||
@@ -77,6 +77,7 @@ public abstract class AnnotatedCompositeCodeTransformer implements CodeTransform
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("RestrictedApiChecker" /* We create a heavily customized `Description` here. */)
|
||||
private Description augmentDescription(
|
||||
Description description, CodeTransformer delegate, Context context) {
|
||||
String shortCheckName = getShortCheckName(description.checkName);
|
||||
|
||||
@@ -171,6 +171,7 @@ final class AnnotatedCompositeCodeTransformerTest {
|
||||
return description(name, Optional.of(""), WARNING, "");
|
||||
}
|
||||
|
||||
@SuppressWarnings("RestrictedApiChecker" /* We create a heavily customized `Description` here. */)
|
||||
private static Description description(
|
||||
String name, Optional<String> link, SeverityLevel severityLevel, String message) {
|
||||
return Description.builder(DUMMY_POSITION, name, link.orElse(null), severityLevel, message)
|
||||
|
||||
@@ -35,9 +35,7 @@ abstract class AbstractMatcherTestChecker extends BugChecker implements Compilat
|
||||
@Override
|
||||
public @Nullable Void scan(Tree tree, @Nullable Void unused) {
|
||||
if (tree instanceof ExpressionTree && delegate.matches((ExpressionTree) tree, state)) {
|
||||
state.reportMatch(
|
||||
Description.builder(tree, canonicalName(), null, defaultSeverity(), message())
|
||||
.build());
|
||||
state.reportMatch(describeMatch(tree));
|
||||
}
|
||||
|
||||
return super.scan(tree, unused);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.6.1-SNAPSHOT</version>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-test-support</artifactId>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
set -e -u -o pipefail
|
||||
|
||||
if [ "${#}" -gt 1 ]; then
|
||||
echo "Usage: ./$(basename "${0}") [TargetTests]"
|
||||
echo "Usage: ${0} [TargetTests]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<img src="/assets/images/picnic-logo@2x.png" alt="Picnic Logo" id="logo"/>
|
||||
|
||||
<p>
|
||||
Copyright © 2017-2022 Picnic Technologies BV
|
||||
Copyright © 2017-2023 Picnic Technologies BV
|
||||
</p>
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 63 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 63 KiB |
Reference in New Issue
Block a user