mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 15:49:33 +00:00
Compare commits
1 Commits
maxsumrall
...
sschroever
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9910160c7 |
@@ -1,3 +1 @@
|
||||
--batch-mode
|
||||
--errors
|
||||
--strict-checksums
|
||||
--batch-mode --errors --strict-checksums
|
||||
|
||||
30
README.md
30
README.md
@@ -36,9 +36,7 @@ code_][picnic-blog-ep-post].
|
||||
### Installation
|
||||
|
||||
This library is built on top of [Error Prone][error-prone-orig-repo]. To use
|
||||
it, read the installation guide for Maven or Gradle below.
|
||||
|
||||
#### Maven
|
||||
it:
|
||||
|
||||
1. First, follow Error Prone's [installation
|
||||
guide][error-prone-installation-guide].
|
||||
@@ -96,31 +94,6 @@ it, read the installation guide for Maven or Gradle below.
|
||||
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:
|
||||
@@ -234,7 +207,6 @@ 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
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
<?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>
|
||||
@@ -1,103 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
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", "");
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -1,153 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"fullyQualifiedName": "pkg.MinimalBugChecker",
|
||||
"name": "MinimalBugChecker",
|
||||
"altNames": [],
|
||||
"link": "",
|
||||
"tags": [],
|
||||
"summary": "MinimalBugChecker summary",
|
||||
"explanation": "",
|
||||
"severityLevel": "ERROR",
|
||||
"canDisable": true,
|
||||
"suppressionAnnotations": [
|
||||
"java.lang.SuppressWarnings"
|
||||
]
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"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.8.1-SNAPSHOT</version>
|
||||
<version>0.7.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
@@ -39,14 +39,6 @@
|
||||
<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>
|
||||
@@ -146,10 +138,6 @@
|
||||
<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>
|
||||
@@ -225,11 +213,6 @@
|
||||
<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>
|
||||
@@ -243,7 +226,6 @@
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs combine.children="append">
|
||||
<arg>-Xplugin:RefasterRuleCompiler</arg>
|
||||
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -260,5 +242,11 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -9,6 +9,7 @@ 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;
|
||||
|
||||
@@ -24,11 +25,15 @@ 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.ConflictDetection;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} that flags non-canonical JUnit method declarations. */
|
||||
// XXX: Consider introducing a class-level check that enforces that test classes:
|
||||
@@ -85,7 +90,7 @@ public final class JUnitMethodDeclaration extends BugChecker implements MethodTr
|
||||
tryCanonicalizeMethodName(symbol)
|
||||
.ifPresent(
|
||||
newName ->
|
||||
ConflictDetection.findMethodRenameBlocker(symbol, newName, state)
|
||||
findMethodRenameBlocker(symbol, newName, state)
|
||||
.ifPresentOrElse(
|
||||
blocker -> reportMethodRenameBlocker(tree, blocker, state),
|
||||
() -> fixBuilder.merge(SuggestedFixes.renameMethod(tree, newName, state))));
|
||||
@@ -101,7 +106,61 @@ public final class JUnitMethodDeclaration extends BugChecker implements MethodTr
|
||||
.build());
|
||||
}
|
||||
|
||||
private static Optional<String> tryCanonicalizeMethodName(MethodSymbol symbol) {
|
||||
/**
|
||||
* 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) {
|
||||
return Optional.of(symbol.getQualifiedName().toString())
|
||||
.filter(name -> name.startsWith(TEST_PREFIX))
|
||||
.map(name -> name.substring(TEST_PREFIX.length()))
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -369,8 +369,7 @@ final class ReactorRules {
|
||||
static final class MonoIdentity<T> {
|
||||
@BeforeTemplate
|
||||
Mono<T> before(Mono<T> mono) {
|
||||
return Refaster.anyOf(
|
||||
mono.switchIfEmpty(Mono.empty()), mono.flux().next(), mono.flux().singleOrEmpty());
|
||||
return mono.switchIfEmpty(Mono.empty());
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
@@ -474,11 +473,6 @@ 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);
|
||||
|
||||
|
||||
@@ -3,16 +3,21 @@ 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.newInstance(AmbiguousJsonCreator.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"X", containsPattern("`JsonCreator.Mode` should be set for single-argument creators"))
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import com.fasterxml.jackson.annotation.JsonCreator;",
|
||||
@@ -113,7 +118,7 @@ final class AmbiguousJsonCreatorTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(AmbiguousJsonCreator.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.fasterxml.jackson.annotation.JsonCreator;",
|
||||
@@ -138,6 +143,6 @@ final class AmbiguousJsonCreatorTest {
|
||||
" return FOO;",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
.doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,14 @@ 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.newInstance(AssertJIsNull.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
@@ -33,7 +38,7 @@ final class AssertJIsNullTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(AssertJIsNull.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(AutowiredConstructor.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import com.google.errorprone.annotations.Immutable;",
|
||||
@@ -66,7 +71,7 @@ final class AutowiredConstructorTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(AutowiredConstructor.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"Container.java",
|
||||
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(CanonicalAnnotationSyntax.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
@@ -128,7 +133,7 @@ final class CanonicalAnnotationSyntaxTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
|
||||
@@ -8,9 +8,14 @@ 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.newInstance(CollectorMutability.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
@@ -62,7 +67,7 @@ final class CollectorMutabilityTest {
|
||||
|
||||
@Test
|
||||
void identificationWithoutGuavaOnClasspath() {
|
||||
CompilationTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
compilationTestHelper
|
||||
.withClasspath()
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
@@ -79,7 +84,7 @@ final class CollectorMutabilityTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
@@ -136,7 +141,7 @@ final class CollectorMutabilityTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
refactoringTestHelper
|
||||
.setFixChooser(SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(EmptyMethod.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
@@ -64,7 +69,7 @@ final class EmptyMethodTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"final class A {",
|
||||
|
||||
@@ -6,9 +6,15 @@ 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.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
@@ -57,7 +63,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.
|
||||
*/
|
||||
BugCheckerRefactoringTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
|
||||
@@ -4,9 +4,12 @@ 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.newInstance(ExplicitEnumOrdering.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.lang.annotation.RetentionPolicy.CLASS;",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
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;
|
||||
@@ -7,9 +9,14 @@ 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.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.function.BiFunction;",
|
||||
@@ -66,7 +73,7 @@ final class FluxFlatMapUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.FIRST)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
@@ -101,7 +108,7 @@ final class FluxFlatMapUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(FormatStringConcatenation.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
@@ -304,7 +309,7 @@ final class FormatStringConcatenationTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(FormatStringConcatenation.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
|
||||
@@ -7,9 +7,14 @@ 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.newInstance(IdentityConversion.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.errorprone.matchers.Matchers.instanceMethod;",
|
||||
@@ -179,7 +184,7 @@ final class IdentityConversionTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(IdentityConversion.class, getClass())
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.FIRST)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
@@ -286,7 +291,7 @@ final class IdentityConversionTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(IdentityConversion.class, getClass())
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ContiguousSet;",
|
||||
@@ -104,7 +109,7 @@ final class ImmutablesSortedSetComparatorTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
@@ -142,7 +147,7 @@ final class ImmutablesSortedSetComparatorTest {
|
||||
|
||||
@Test
|
||||
void replacementWithImportClash() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"MySpringService.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(IsInstanceLambdaUsage.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
@@ -41,7 +46,7 @@ final class IsInstanceLambdaUsageTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(IsInstanceLambdaUsage.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(JUnitClassModifiers.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
@@ -93,7 +98,7 @@ final class JUnitClassModifiersTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitClassModifiers.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(JUnitMethodDeclaration.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
@@ -340,7 +345,7 @@ final class JUnitMethodDeclarationTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitMethodDeclaration.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
|
||||
@@ -7,9 +7,22 @@ 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.newInstance(LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.math.RoundingMode.DOWN;",
|
||||
@@ -152,8 +165,7 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
// `CanonicalAnnotationSyntax` checker correct the situation in a subsequent run.
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.math.RoundingMode.DOWN;",
|
||||
@@ -234,11 +246,7 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
@Test
|
||||
void filtering() {
|
||||
/* Some violations are not flagged because they are not in- or excluded. */
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Includes=pkg.A.Foo,pkg.A.Bar",
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value"))
|
||||
restrictedCompilationTestHelper
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
|
||||
@@ -6,9 +6,15 @@ 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.newInstance(LexicographicalAnnotationListing.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.lang.annotation.ElementType;",
|
||||
@@ -127,7 +133,7 @@ final class LexicographicalAnnotationListingTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(LexicographicalAnnotationListing.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.lang.annotation.ElementType;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(MethodReferenceUsage.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.Streams;",
|
||||
@@ -318,7 +323,7 @@ final class MethodReferenceUsageTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(MethodReferenceUsage.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.Collections.emptyList;",
|
||||
|
||||
@@ -6,12 +6,16 @@ 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.newInstance(MissingRefasterAnnotation.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"X",
|
||||
containsPattern("The Refaster rule contains a method without any Refaster annotations"))
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.AfterTemplate;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(MockitoStubbing.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.mockito.ArgumentMatchers.eq;",
|
||||
@@ -50,7 +55,7 @@ final class MockitoStubbingTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(MockitoStubbing.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.mockito.ArgumentMatchers.eq;",
|
||||
|
||||
@@ -4,9 +4,12 @@ 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.newInstance(NestedOptionals.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Optional;",
|
||||
@@ -39,7 +42,7 @@ final class NestedOptionalsTest {
|
||||
|
||||
@Test
|
||||
void identificationOptionalTypeNotLoaded() {
|
||||
CompilationTestHelper.newInstance(NestedOptionals.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.time.Duration;",
|
||||
|
||||
@@ -7,9 +7,14 @@ 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.newInstance(NonEmptyMono.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
@@ -106,7 +111,7 @@ final class NonEmptyMonoTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(NonEmptyMono.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
|
||||
@@ -5,21 +5,22 @@ 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 {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
@Test
|
||||
void byteComparison() {
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -119,7 +120,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void intComparison() {
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -226,7 +227,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void longComparison() {
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -317,7 +318,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void floatComparison() {
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -385,7 +386,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void doubleComparison() {
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -460,7 +461,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void stringComparison() {
|
||||
CompilationTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -496,7 +497,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithPrimitiveVariants() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -576,7 +577,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithBoxedVariants() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -642,7 +643,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithPrimitiveVariantsUsingStaticImports() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.Comparator.comparing;",
|
||||
@@ -681,7 +682,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithBoxedVariantsUsingStaticImports() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.Comparator.comparingDouble;",
|
||||
@@ -722,7 +723,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithPrimitiveVariantsInComplexSyntacticalContext() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
@@ -754,7 +755,7 @@ final class PrimitiveComparisonTest {
|
||||
|
||||
@Test
|
||||
void replacementWithBoxedVariantsInComplexSyntacticalContext() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparison.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Comparator;",
|
||||
|
||||
@@ -12,6 +12,13 @@ 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() {
|
||||
@@ -409,10 +416,7 @@ final class RedundantStringConversionTest {
|
||||
|
||||
@Test
|
||||
void identificationOfCustomConversionMethod() {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)"))
|
||||
customizedCompilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.math.RoundingMode;",
|
||||
@@ -505,7 +509,7 @@ final class RedundantStringConversionTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(RefasterAnyOfUsage.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
@@ -33,7 +38,7 @@ final class RefasterAnyOfUsageTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterAnyOfUsage.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(RefasterRuleModifiers.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
@@ -131,7 +136,7 @@ final class RefasterRuleModifiersTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterRuleModifiers.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
|
||||
@@ -4,9 +4,12 @@ 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.newInstance(RequestMappingAnnotation.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.io.InputStream;",
|
||||
|
||||
@@ -4,9 +4,16 @@ import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class RequestParamTypeTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass());
|
||||
private final CompilationTestHelper restrictedCompilationTestHelper =
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
|
||||
.setArgs(
|
||||
"-XepOpt:RequestParamType:SupportedCustomTypes=com.google.common.collect.ImmutableSet,com.google.common.collect.ImmutableSortedMultiset");
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableBiMap;",
|
||||
@@ -63,9 +70,7 @@ final class RequestParamTypeTest {
|
||||
|
||||
@Test
|
||||
void identificationRestricted() {
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
|
||||
.setArgs(
|
||||
"-XepOpt:RequestParamType:SupportedCustomTypes=com.google.common.collect.ImmutableSet,com.google.common.collect.ImmutableSortedMultiset")
|
||||
restrictedCompilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableBiMap;",
|
||||
|
||||
@@ -7,9 +7,14 @@ 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.newInstance(ScheduledTransactionTrace.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.newrelic.api.agent.Trace;",
|
||||
@@ -41,7 +46,7 @@ final class ScheduledTransactionTraceTest {
|
||||
|
||||
@Test
|
||||
void identificationWithoutNewRelicAgentApiOnClasspath() {
|
||||
CompilationTestHelper.newInstance(ScheduledTransactionTrace.class, getClass())
|
||||
compilationTestHelper
|
||||
.withClasspath(Scheduled.class)
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
@@ -56,7 +61,7 @@ final class ScheduledTransactionTraceTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(ScheduledTransactionTrace.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.newrelic.api.agent.Trace;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(Slf4jLogStatement.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
@@ -91,7 +96,7 @@ final class Slf4jLogStatementTest {
|
||||
// XXX: Drop what's unused.
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(Slf4jLogStatement.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
|
||||
@@ -6,9 +6,14 @@ 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.newInstance(SpringMvcAnnotation.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.DELETE;",
|
||||
@@ -80,7 +85,7 @@ final class SpringMvcAnnotationTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(SpringMvcAnnotation.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PATCH;",
|
||||
|
||||
@@ -8,6 +8,11 @@ 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())
|
||||
@@ -28,7 +33,7 @@ final class StaticImportTest {
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
CompilationTestHelper.newInstance(StaticImport.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
@@ -113,7 +118,7 @@ final class StaticImportTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(StaticImport.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.function.Predicate.not;",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
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;
|
||||
@@ -7,9 +9,14 @@ 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.newInstance(StringCaseLocaleUsage.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.util.Locale.ROOT;",
|
||||
@@ -47,7 +54,7 @@ final class StringCaseLocaleUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringCaseLocaleUsage.class, getClass())
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.FIRST)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
@@ -86,7 +93,7 @@ final class StringCaseLocaleUsageTest {
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringCaseLocaleUsage.class, getClass())
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
|
||||
@@ -8,12 +8,17 @@ 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() {
|
||||
CompilationTestHelper.newInstance(StringJoin.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"valueOf", containsPattern("Prefer `String#valueOf` over `String#format`"))
|
||||
.expectErrorMessage("join", containsPattern("Prefer `String#join` over `String#format`"))
|
||||
compilationHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Formattable;",
|
||||
@@ -58,7 +63,7 @@ final class StringJoinTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringJoin.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
|
||||
@@ -4,9 +4,12 @@ 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() {
|
||||
CompilationTestHelper.newInstance(TimeZoneUsage.class, getClass())
|
||||
compilationHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.time.ZoneOffset.UTC;",
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,9 @@ 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();
|
||||
@@ -55,7 +58,7 @@ final class MethodMatcherFactoryTest {
|
||||
|
||||
@Test
|
||||
void matcher() {
|
||||
CompilationTestHelper.newInstance(MatchedMethodsFlagger.class, getClass())
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"com/example/A.java",
|
||||
"package com.example;",
|
||||
|
||||
@@ -49,7 +49,6 @@ final class RefasterRulesTest {
|
||||
ImmutableSortedMultisetRules.class,
|
||||
ImmutableSortedSetRules.class,
|
||||
IntStreamRules.class,
|
||||
JooqRules.class,
|
||||
JUnitRules.class,
|
||||
JUnitToAssertJRules.class,
|
||||
LongStreamRules.class,
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -116,11 +116,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<?>> testMonoIdentity() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just(1).switchIfEmpty(Mono.empty()),
|
||||
Mono.just(2).flux().next(),
|
||||
Mono.just(3).flux().singleOrEmpty(),
|
||||
Mono.<Void>empty().then());
|
||||
return ImmutableSet.of(Mono.just(1).switchIfEmpty(Mono.empty()), 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.just(2), Mono.just(3), Mono.<Void>empty());
|
||||
return ImmutableSet.of(Mono.just(1), 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((Object[]) null, null),
|
||||
(Runnable) () -> assertEqualsNoOrder(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((Object[]) null, null),
|
||||
(Runnable) () -> assertEqualsNoOrder(null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotEquals(new byte[0], null),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
|
||||
172
pom.xml
172
pom.xml
@@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
<version>0.7.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Picnic :: Error Prone Support</name>
|
||||
@@ -39,7 +39,6 @@
|
||||
</developers>
|
||||
|
||||
<modules>
|
||||
<module>documentation-support</module>
|
||||
<module>error-prone-contrib</module>
|
||||
<module>refaster-compiler</module>
|
||||
<module>refaster-runner</module>
|
||||
@@ -150,15 +149,15 @@
|
||||
<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-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.error-prone-orig>2.17.0</version.error-prone-orig>
|
||||
<version.error-prone-slf4j>0.1.17</version.error-prone-slf4j>
|
||||
<version.guava-beta-checker>1.0</version.guava-beta-checker>
|
||||
<version.jdk>11</version.jdk>
|
||||
<version.maven>3.8.7</version.maven>
|
||||
<version.mockito>5.1.1</version.mockito>
|
||||
<version.maven>3.8.6</version.maven>
|
||||
<version.mockito>4.11.0</version.mockito>
|
||||
<version.nopen-checker>1.0.1</version.nopen-checker>
|
||||
<version.nullaway>0.10.9</version.nullaway>
|
||||
<version.pitest-git>1.0.4</version.pitest-git>
|
||||
<version.nullaway>0.10.7</version.nullaway>
|
||||
<version.pitest-git>1.0.3</version.pitest-git>
|
||||
<version.surefire>2.22.2</version.surefire>
|
||||
</properties>
|
||||
|
||||
@@ -189,11 +188,6 @@
|
||||
<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>
|
||||
@@ -217,7 +211,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson</groupId>
|
||||
<artifactId>jackson-bom</artifactId>
|
||||
<version>2.14.2</version>
|
||||
<version>2.14.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -275,7 +269,7 @@
|
||||
<dependency>
|
||||
<groupId>com.newrelic.agent.java</groupId>
|
||||
<artifactId>newrelic-api</artifactId>
|
||||
<version>8.0.0</version>
|
||||
<version>7.11.1</version>
|
||||
</dependency>
|
||||
<!-- Specified as a workaround for
|
||||
https://github.com/mojohaus/versions-maven-plugin/issues/244. -->
|
||||
@@ -287,7 +281,7 @@
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
<version>2022.0.2</version>
|
||||
<version>2022.0.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -304,7 +298,7 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>2.2.8</version>
|
||||
<version>2.2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
@@ -328,11 +322,6 @@
|
||||
<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. -->
|
||||
@@ -349,14 +338,14 @@
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-bom</artifactId>
|
||||
<version>3.24.2</version>
|
||||
<version>3.24.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.30.0</version>
|
||||
<version>3.29.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
@@ -368,11 +357,6 @@
|
||||
<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>
|
||||
@@ -381,7 +365,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.9.2</version>
|
||||
<version>5.9.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -400,19 +384,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>5.3.25</version>
|
||||
<version>5.3.24</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<version>2.7.8</version>
|
||||
<version>2.7.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>7.7.1</version>
|
||||
<version>7.4.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
@@ -423,7 +407,7 @@
|
||||
<plugin>
|
||||
<groupId>com.github.ekryd.sortpom</groupId>
|
||||
<artifactId>sortpom-maven-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.2.0</version>
|
||||
<configuration>
|
||||
<createBackupFile>false</createBackupFile>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
@@ -538,7 +522,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.2.0</version>
|
||||
<configuration>
|
||||
<checkstyleRules>
|
||||
<!-- We only enable rules that are not enforced by
|
||||
@@ -726,9 +710,6 @@
|
||||
<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')]]" />
|
||||
@@ -788,12 +769,12 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>10.7.0</version>
|
||||
<version>10.6.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.nohttp</groupId>
|
||||
<artifactId>nohttp-checkstyle</artifactId>
|
||||
<version>0.0.11</version>
|
||||
<version>0.0.10</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -829,6 +810,11 @@
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<version>${version.error-prone}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_docgen_processor</artifactId>
|
||||
<version>${version.error-prone}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.google.auto.value</groupId>
|
||||
<artifactId>auto-value</artifactId>
|
||||
@@ -867,7 +853,6 @@
|
||||
</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>
|
||||
@@ -889,7 +874,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.4.0</version>
|
||||
<configuration>
|
||||
<!-- XXX: Drop `ignoreAllNonTestScoped` once
|
||||
https://issues.apache.org/jira/browse/MNG-6058 is
|
||||
@@ -904,7 +889,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<retryFailedDeploymentCount>3</retryFailedDeploymentCount>
|
||||
</configuration>
|
||||
@@ -912,41 +897,12 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.1.0</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>
|
||||
@@ -958,8 +914,8 @@
|
||||
<requireMavenVersion>
|
||||
<version>${version.maven}</version>
|
||||
</requireMavenVersion>
|
||||
<requireNoRepositories />
|
||||
<requirePluginVersions />
|
||||
<requireSameVersionsReactor />
|
||||
<requireUpperBoundDeps>
|
||||
<excludes>
|
||||
<!-- XXX:
|
||||
@@ -1138,6 +1094,37 @@
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<mainClass>com.google.errorprone.DocGenTool</mainClass>
|
||||
<arguments>
|
||||
<argument>-bug_patterns=${project.build.directory}/generated-sources/annotations/bugPatterns.txt</argument>
|
||||
<argument>-docs_repository=${project.build.directory}/generated-wiki/</argument>
|
||||
<argument>-explanations=${basedir}/src/main/docs/bugpattern/</argument>
|
||||
<argument>-target=external</argument>
|
||||
</arguments>
|
||||
<includePluginDependencies>true</includePluginDependencies>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_docgen</artifactId>
|
||||
<version>${version.error-prone}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-bugpattern-docs</id>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<phase>process-classes</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
@@ -1183,8 +1170,6 @@
|
||||
| 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>
|
||||
@@ -1290,7 +1275,7 @@
|
||||
<plugin>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-maven</artifactId>
|
||||
<version>1.11.0</version>
|
||||
<version>1.10.4</version>
|
||||
<configuration>
|
||||
<excludedClasses>
|
||||
<!-- AutoValue generated classes. -->
|
||||
@@ -1329,7 +1314,7 @@
|
||||
<dependency>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-junit5-plugin</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -1383,30 +1368,6 @@
|
||||
<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>
|
||||
@@ -1650,10 +1611,6 @@
|
||||
<!-- 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. -->
|
||||
@@ -1662,9 +1619,6 @@
|
||||
-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.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
<version>0.7.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.8.1-SNAPSHOT</version>
|
||||
<version>0.7.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-runner</artifactId>
|
||||
|
||||
16
refaster-runner/src/main/docs/bugpattern/Refaster.md
Normal file
16
refaster-runner/src/main/docs/bugpattern/Refaster.md
Normal file
@@ -0,0 +1,16 @@
|
||||
Error Prone's out-of-the-box support for the application of
|
||||
[Refaster][refaster] templates is somewhat cumbersome. Additionally, by default
|
||||
the focus of Refaster templates is on one-off code refactorings.
|
||||
|
||||
This plugin attempts to bring Refaster templates on equal footing with other
|
||||
Error Prone plugins by locating all Refaster templates on the classpath and
|
||||
reporing any match. The suggested changes can be applied using Error Prone's
|
||||
built-in [patch][patching] functionality.
|
||||
|
||||
XXX: Expand documentation. Mention:
|
||||
- The `refaster-resource-compiler`.
|
||||
- How checks can be restricted using the `NamePattern` flag (see the Javadoc)
|
||||
- An concrete patching example, with and without `NamePattern`.
|
||||
|
||||
[refaster]: https://errorprone.info/docs/refaster
|
||||
[patching]: https://errorprone.info/docs/patching
|
||||
@@ -161,7 +161,6 @@ 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,6 +50,12 @@ 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() {
|
||||
@@ -214,7 +220,7 @@ final class RefasterTest {
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(Refaster.class, getClass())
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
@@ -240,9 +246,7 @@ final class RefasterTest {
|
||||
|
||||
@Test
|
||||
void restrictedReplacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(Refaster.class, getClass())
|
||||
.setArgs(
|
||||
"-XepOpt:Refaster:NamePattern=.*\\$(StringOfSizeZeroVerboseRule|StringOfSizeTwoRule)$")
|
||||
restrictedRefactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
<version>0.7.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-support</artifactId>
|
||||
|
||||
@@ -77,7 +77,6 @@ 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,7 +171,6 @@ 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,7 +35,9 @@ 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(describeMatch(tree));
|
||||
state.reportMatch(
|
||||
Description.builder(tree, canonicalName(), null, defaultSeverity(), message())
|
||||
.build());
|
||||
}
|
||||
|
||||
return super.scan(tree, unused);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
<version>0.7.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-test-support</artifactId>
|
||||
|
||||
Reference in New Issue
Block a user