mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Compare commits
1 Commits
v0.19.0
...
sschroever
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
196edf9118 |
@@ -2,6 +2,7 @@ package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
@@ -17,7 +18,9 @@ import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.TestCases;
|
||||
|
||||
@@ -157,7 +160,7 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
|
||||
* is safe, because this code is guarded by an earlier call to `#getClassUnderTest(..)`,
|
||||
* which ensures that `tree` is part of a longer method invocation chain.
|
||||
*/
|
||||
MethodInvocationTree inputTree = (MethodInvocationTree) ASTHelpers.getReceiver(tree);
|
||||
MethodInvocationTree inputTree = (MethodInvocationTree) requireNonNull(ASTHelpers.getReceiver(tree));
|
||||
|
||||
String path = ASTHelpers.constValue(inputTree.getArguments().get(0), String.class);
|
||||
Optional<String> inputCode = getSourceCode(inputTree);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
@@ -46,7 +47,7 @@ public final class DocumentationGenerator implements Plugin {
|
||||
checkArgument(
|
||||
matcher.matches(), "'%s' must be of the form '%s=<value>'", pathArg, OUTPUT_DIRECTORY_FLAG);
|
||||
|
||||
String path = matcher.group(1);
|
||||
String path = requireNonNull(matcher.group(1), "Path must be present");
|
||||
try {
|
||||
return Path.of(path);
|
||||
} catch (InvalidPathException e) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
@@ -93,7 +94,7 @@ final class DocumentationGeneratorTaskListener implements TaskListener {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void writeToFile(String identifier, String className, T data) {
|
||||
private <T extends Object> 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)) {
|
||||
@@ -104,6 +105,8 @@ final class DocumentationGeneratorTaskListener implements TaskListener {
|
||||
}
|
||||
|
||||
private static String getSimpleClassName(URI path) {
|
||||
return Paths.get(path).getFileName().toString().replace(".java", "");
|
||||
return requireNonNull(Paths.get(path).getFileName(), "Path lacks filename")
|
||||
.toString()
|
||||
.replace(".java", "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ 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.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -53,22 +55,25 @@ public final class Compilation {
|
||||
}
|
||||
|
||||
private static void compile(ImmutableList<String> options, JavaFileObject javaFileObject) {
|
||||
JavacFileManager javacFileManager = FileManagers.testFileManager();
|
||||
JavaCompiler compiler = JavacTool.create();
|
||||
try (JavacFileManager javacFileManager = FileManagers.testFileManager()) {
|
||||
JavaCompiler compiler = JavacTool.create();
|
||||
|
||||
List<Diagnostic<?>> diagnostics = new ArrayList<>();
|
||||
JavacTaskImpl task =
|
||||
(JavacTaskImpl)
|
||||
compiler.getTask(
|
||||
null,
|
||||
javacFileManager,
|
||||
diagnostics::add,
|
||||
options,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(javaFileObject));
|
||||
List<Diagnostic<?>> diagnostics = new ArrayList<>();
|
||||
JavacTaskImpl task =
|
||||
(JavacTaskImpl)
|
||||
compiler.getTask(
|
||||
null,
|
||||
javacFileManager,
|
||||
diagnostics::add,
|
||||
options,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(javaFileObject));
|
||||
|
||||
Boolean result = task.call();
|
||||
assertThat(diagnostics).isEmpty();
|
||||
assertThat(result).isTrue();
|
||||
Boolean result = task.call();
|
||||
assertThat(diagnostics).isEmpty();
|
||||
assertThat(result).isTrue();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to close `JavaCompiler`", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +146,10 @@
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.immutables</groupId>
|
||||
<artifactId>value-annotations</artifactId>
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.sun.source.tree.ParenthesizedTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.source.util.SimpleTreeVisitor;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
@@ -208,7 +209,9 @@ public final class FormatStringConcatenation extends BugChecker
|
||||
}
|
||||
|
||||
private static boolean isStringTyped(ExpressionTree tree, VisitorState state) {
|
||||
return ASTHelpers.isSameType(ASTHelpers.getType(tree), state.getSymtab().stringType, state);
|
||||
// XXX: Open Error Prone PR to improve the `@Nullable` annotations on `ASTHelpers`.
|
||||
Type type = ASTHelpers.getType(tree);
|
||||
return type != null && ASTHelpers.isSameType(type, state.getSymtab().stringType, state);
|
||||
}
|
||||
|
||||
private static class ReplacementArgumentsConstructor
|
||||
|
||||
@@ -171,6 +171,9 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
return findMatchingSibling(tree, m -> m.getName().contentEquals(methodName), state);
|
||||
}
|
||||
|
||||
// XXX: File ticket for the `@SuppressWarnings`: the checker incorrectly claims that the predicate
|
||||
// only accepts `@InternedDistinct @SignatureBottom MethodTree` values (IIUC).
|
||||
@SuppressWarnings({"interning:argument", "signature:argument"})
|
||||
private static Optional<MethodTree> findMatchingSibling(
|
||||
MethodTree tree, Predicate<? super MethodTree> predicate, VisitorState state) {
|
||||
return state.findEnclosing(ClassTree.class).getMembers().stream()
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.sun.tools.javac.code.Type;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.Name;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags lambda expressions that can be replaced with method references.
|
||||
@@ -189,7 +190,12 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.of(diff == 0 ? Optional.empty() : Optional.of(expectedArguments.get(0)));
|
||||
// XXX: These type hints shouldn't be necessary; see
|
||||
// https://github.com/typetools/checker-framework/issues/4007.
|
||||
return Optional.of(
|
||||
diff == 0
|
||||
? Optional.<@NonNull Name>empty()
|
||||
: Optional.<@NonNull Name>of(expectedArguments.get(0)));
|
||||
}
|
||||
|
||||
private static ImmutableList<Name> getVariables(LambdaExpressionTree tree) {
|
||||
|
||||
@@ -45,6 +45,9 @@ public final class MethodMatcherFactory {
|
||||
// XXX: It seems parse errors are silently swallowed. Double-check; if true, file a ticket.
|
||||
// XXX: This (probably) doesn't work for methods with array type arguments; if true, implement a
|
||||
// fix.
|
||||
// XXX: The `nullness` warning suppression shouldn't be necessary. See
|
||||
// https://github.com/typetools/checker-framework/issues/4006.
|
||||
@SuppressWarnings("nullness:argument")
|
||||
private static Matcher<ExpressionTree> createMethodMatcher(CharSequence signature) {
|
||||
java.util.regex.Matcher m = METHOD_SIGNATURE.matcher(signature);
|
||||
checkArgument(m.matches(), "Not a valid method signature: %s", signature);
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractStringAssert;
|
||||
import org.checkerframework.checker.regex.qual.Regex;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@OnlineDocumentation
|
||||
@@ -71,26 +72,26 @@ final class AssertJStringRules {
|
||||
|
||||
static final class AssertThatMatches {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(String string, String regex) {
|
||||
AbstractAssert<?, ?> before(String string, @Regex String regex) {
|
||||
return assertThat(string.matches(regex)).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(String string, String regex) {
|
||||
AbstractAssert<?, ?> after(String string, @Regex String regex) {
|
||||
return assertThat(string).matches(regex);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoesNotMatch {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(String string, String regex) {
|
||||
AbstractAssert<?, ?> before(String string, @Regex String regex) {
|
||||
return assertThat(string.matches(regex)).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(String string, String regex) {
|
||||
AbstractAssert<?, ?> after(String string, @Regex String regex) {
|
||||
return assertThat(string).doesNotMatch(regex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.io.IOException;
|
||||
import org.assertj.core.api.AbstractObjectAssert;
|
||||
import org.assertj.core.api.AbstractThrowableAssert;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.checkerframework.checker.formatter.qual.FormatMethod;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/**
|
||||
@@ -591,6 +592,7 @@ final class AssertJThrowingCallableRules {
|
||||
// arguments to a wide range of format methods.
|
||||
static final class AbstractThrowableAssertHasMessage {
|
||||
@BeforeTemplate
|
||||
@FormatMethod
|
||||
AbstractThrowableAssert<?, ? extends Throwable> before(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
@@ -599,6 +601,7 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@FormatMethod
|
||||
AbstractThrowableAssert<?, ? extends Throwable> after(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
@@ -611,6 +614,7 @@ final class AssertJThrowingCallableRules {
|
||||
// arguments to a wide range of format methods.
|
||||
static final class AbstractThrowableAssertWithFailMessage {
|
||||
@BeforeTemplate
|
||||
@FormatMethod
|
||||
AbstractThrowableAssert<?, ? extends Throwable> before(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
@@ -619,6 +623,7 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@FormatMethod
|
||||
AbstractThrowableAssert<?, ? extends Throwable> after(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import org.checkerframework.checker.interning.qual.Interned;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/** Refaster rules related to expressions dealing with (in)equalities. */
|
||||
@@ -21,7 +22,7 @@ final class EqualityRules {
|
||||
|
||||
/** Prefer reference-based quality for enums. */
|
||||
// Primitive value comparisons are not listed, because Error Prone flags those out of the box.
|
||||
static final class PrimitiveOrReferenceEquality<T extends Enum<T>> {
|
||||
static final class PrimitiveOrReferenceEquality<T extends @Interned Enum<T>> {
|
||||
/**
|
||||
* Enums can be compared by reference. It is safe to do so even in the face of refactorings,
|
||||
* because if the type is ever converted to a non-enum, then Error-Prone will complain about any
|
||||
@@ -30,6 +31,7 @@ final class EqualityRules {
|
||||
// XXX: This Refaster rule is the topic of https://github.com/google/error-prone/issues/559. We
|
||||
// work around the issue by selecting the "largest replacements". See the `Refaster` check.
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("interning:unnecessary.equals" /* This violation will be rewritten. */)
|
||||
boolean before(T a, T b) {
|
||||
return Refaster.anyOf(a.equals(b), Objects.equals(a, b));
|
||||
}
|
||||
@@ -96,7 +98,7 @@ final class EqualityRules {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
boolean before(Object a, Object b) {
|
||||
boolean before(@Interned Object a, @Interned Object b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
@@ -127,7 +129,7 @@ final class EqualityRules {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
boolean before(Object a, Object b) {
|
||||
boolean before(@Interned Object a, @Interned Object b) {
|
||||
return !(a != b);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import org.checkerframework.checker.regex.qual.Regex;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/** Refaster rules related to code dealing with regular expressions. */
|
||||
@@ -34,12 +35,12 @@ final class PatternRules {
|
||||
/** Prefer {@link Pattern#asPredicate()} over non-JDK alternatives. */
|
||||
static final class PatternCompileAsPredicate {
|
||||
@BeforeTemplate
|
||||
Predicate<CharSequence> before(String pattern) {
|
||||
Predicate<CharSequence> before(@Regex String pattern) {
|
||||
return containsPattern(pattern);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Predicate<String> after(String pattern) {
|
||||
Predicate<String> after(@Regex String pattern) {
|
||||
return Pattern.compile(pattern).asPredicate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +452,11 @@ final class StreamRules {
|
||||
|
||||
static final class StreamMapToIntSum<T> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4266" /* This violation will be rewritten. */)
|
||||
@SuppressWarnings({
|
||||
"interning:return" /* Handle inference failure. */,
|
||||
"java:S4266" /* This violation will be rewritten. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
long before(Stream<T> stream, ToIntFunction<T> mapper) {
|
||||
return stream.collect(summingInt(mapper));
|
||||
}
|
||||
@@ -472,7 +476,11 @@ final class StreamRules {
|
||||
|
||||
static final class StreamMapToDoubleSum<T> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4266" /* This violation will be rewritten. */)
|
||||
@SuppressWarnings({
|
||||
"interning:return" /* Handle inference failure. */,
|
||||
"java:S4266" /* This violation will be rewritten. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
double before(Stream<T> stream, ToDoubleFunction<T> mapper) {
|
||||
return stream.collect(summingDouble(mapper));
|
||||
}
|
||||
@@ -492,7 +500,11 @@ final class StreamRules {
|
||||
|
||||
static final class StreamMapToLongSum<T> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4266" /* This violation will be rewritten. */)
|
||||
@SuppressWarnings({
|
||||
"interning:return" /* Handle inference failure. */,
|
||||
"java:S4266" /* This violation will be rewritten. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
long before(Stream<T> stream, ToLongFunction<T> mapper) {
|
||||
return stream.collect(summingLong(mapper));
|
||||
}
|
||||
@@ -548,7 +560,11 @@ final class StreamRules {
|
||||
|
||||
static final class StreamCount<T> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4266" /* This violation will be rewritten. */)
|
||||
@SuppressWarnings({
|
||||
"interning:return" /* Handle inference failure. */,
|
||||
"java:S4266" /* This violation will be rewritten. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
long before(Stream<T> stream) {
|
||||
return stream.collect(counting());
|
||||
}
|
||||
|
||||
102
pom.xml
102
pom.xml
@@ -203,6 +203,7 @@
|
||||
that need to be referenced only once should *not* be listed here. -->
|
||||
<version.auto-service>1.1.1</version.auto-service>
|
||||
<version.auto-value>1.10.4</version.auto-value>
|
||||
<version.checker-framework>3.42.0</version.checker-framework>
|
||||
<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.24.0</version.error-prone-orig>
|
||||
@@ -411,7 +412,17 @@
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.42.0</version>
|
||||
<version>${version.checker-framework}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-util</artifactId>
|
||||
<version>${version.checker-framework}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>dataflow-shaded</artifactId>
|
||||
<version>${version.checker-framework}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
@@ -481,6 +492,22 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<!-- These two dependencies are implicitly used by all submodules because
|
||||
the Checker Framework enriches the compiled code with inferred annotations. -->
|
||||
<!-- XXX: Move these if we decide to move the Checker Framework code to a
|
||||
separate profile. -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>dataflow-shaded</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
@@ -930,12 +957,54 @@
|
||||
<artifactId>errorprone-slf4j</artifactId>
|
||||
<version>${version.error-prone-slf4j}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker</artifactId>
|
||||
<version>${version.checker-framework}</version>
|
||||
</path>
|
||||
<!-- This dependency is listed explicitly because
|
||||
Auto Service depends on an older incompatible
|
||||
version of this artifact. -->
|
||||
<path>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>${version.checker-framework}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-errorprone</artifactId>
|
||||
<version>${version.mockito}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<annotationProcessors>
|
||||
<annotationProcessor>com.google.auto.service.processor.AutoServiceProcessor</annotationProcessor>
|
||||
<annotationProcessor>com.google.auto.value.processor.AutoAnnotationProcessor</annotationProcessor>
|
||||
<annotationProcessor>com.google.auto.value.processor.AutoValueProcessor</annotationProcessor>
|
||||
<annotationProcessor>org.checkerframework.checker.calledmethods.CalledMethodsChecker</annotationProcessor>
|
||||
<!-- XXX: This check seems to trigger some false
|
||||
positives.
|
||||
<annotationProcessor>org.checkerframework.checker.lock.LockChecker</annotationProcessor> -->
|
||||
<annotationProcessor>org.checkerframework.checker.formatter.FormatterChecker</annotationProcessor>
|
||||
<!-- XXX: This check triggers false positives, at
|
||||
least in part because it doesn't respect invariants
|
||||
guarded by `check{Argument,State}`.
|
||||
<annotationProcessor>org.checkerframework.checker.index.IndexChecker</annotationProcessor> -->
|
||||
<annotationProcessor>org.checkerframework.checker.interning.InterningChecker</annotationProcessor>
|
||||
<!-- XXX: Flag some good stuff, but also a bunch of
|
||||
false positives.
|
||||
<annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor> -->
|
||||
<!-- XXX: This checker also flags `Optional` fields
|
||||
and method method parameters. Consider introducing
|
||||
a derivative checker which _does_ allow this.
|
||||
<annotationProcessor>org.checkerframework.checker.optional.OptionalChecker</annotationProcessor> -->
|
||||
<annotationProcessor>org.checkerframework.checker.regex.RegexChecker</annotationProcessor>
|
||||
<!-- XXX: This check seems to trigger some false
|
||||
positives, with suppressions being reported as
|
||||
redundant.
|
||||
<annotationProcessor>org.checkerframework.checker.resourceleak.ResourceLeakChecker</annotationProcessor> -->
|
||||
<annotationProcessor>org.checkerframework.checker.signature.SignatureChecker</annotationProcessor>
|
||||
<annotationProcessor>org.checkerframework.common.initializedfields.InitializedFieldsChecker</annotationProcessor>
|
||||
</annotationProcessors>
|
||||
<compilerArgs>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
|
||||
@@ -944,10 +1013,41 @@
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
|
||||
<arg>-AskipDefs=\.Auto(Annotation|Value)_</arg>
|
||||
<!-- XXX: This prevents the nullness checker from
|
||||
flagging nullable arguments to `requireNonull`.
|
||||
Review this approach. -->
|
||||
<arg>-AskipUses=^java\.util\.Objects$</arg>
|
||||
<!-- XXX: This flag triggers a crash.
|
||||
<arg>-AcheckCastElementType</arg>-->
|
||||
<arg>-AcheckPurityAnnotations</arg>
|
||||
<arg>-AconcurrentSemantics</arg>
|
||||
<!-- XXX: This flag triggers a crash.
|
||||
<arg>-AconservativeUninferredTypeArguments</arg>-->
|
||||
<arg>-AignoreRawTypeArguments=false</arg>
|
||||
<!-- XXX: Odd impact on arrays; review.
|
||||
<arg>-AinvariantArrays</arg>-->
|
||||
<arg>-AresolveReflection</arg>
|
||||
<arg>-AshowSuppressWarningsStrings</arg>
|
||||
<arg>-AwarnRedundantAnnotations</arg>
|
||||
<arg>-AwarnUnneededSuppressions</arg>
|
||||
<arg>-ArequirePrefixInWarningSuppressions</arg>
|
||||
<arg>-AshowPrefixInWarningMessages</arg>
|
||||
<!-- XXX: Ponder.
|
||||
<arg>-AsuggestPureMethods</arg> -->
|
||||
<!-- XXX: Seemingly redundant null checks may be
|
||||
necessary when interacting with an unannotated,
|
||||
partially annotated or incorrectly annotated API.
|
||||
So ideally we specify
|
||||
`-Alint=all,-redundantNullComparison` or
|
||||
`-Alint=all -ANullnessChecker_lint=-redundantNullComparison`,
|
||||
but neither of these options has the desired
|
||||
effect. -->
|
||||
<arg>-Xmaxerrs</arg>
|
||||
<arg>10000</arg>
|
||||
<arg>-Xmaxwarns</arg>
|
||||
<arg>10000</arg>
|
||||
<!-- XXX: Move <arg>-Awarn</arg>-->
|
||||
</compilerArgs>
|
||||
<parameters>true</parameters>
|
||||
<source>${version.jdk}</source>
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.sun.tools.javac.util.Name;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Map;
|
||||
@@ -145,7 +146,8 @@ final class RefasterRuleCompilerTaskListener implements TaskListener {
|
||||
|
||||
private static void outputCodeTransformer(CodeTransformer codeTransformer, FileObject target)
|
||||
throws IOException {
|
||||
try (ObjectOutput output = new ObjectOutputStream(target.openOutputStream())) {
|
||||
try (OutputStream stream = target.openOutputStream();
|
||||
ObjectOutput output = new ObjectOutputStream(stream)) {
|
||||
output.writeObject(codeTransformer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,10 @@
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
|
||||
@@ -42,6 +42,7 @@ import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import org.checkerframework.checker.regex.util.RegexUtil;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags code that can be simplified using Refaster rules located on the
|
||||
@@ -210,7 +211,7 @@ public final class Refaster extends BugChecker implements CompilationUnitTreeMat
|
||||
return CompositeCodeTransformer.compose(
|
||||
flags
|
||||
.get(INCLUDED_RULES_PATTERN_FLAG)
|
||||
.map(Pattern::compile)
|
||||
.map(pattern -> Pattern.compile(RegexUtil.asRegex(pattern)))
|
||||
.<ImmutableCollection<CodeTransformer>>map(
|
||||
nameFilter -> filterCodeTransformers(allTransformers, nameFilter))
|
||||
.orElseGet(allTransformers::values));
|
||||
|
||||
@@ -178,6 +178,7 @@ final class RefasterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"regex:argument", "regex:group.count"})
|
||||
private static ImmutableList<SeverityLevel> extractRefasterSeverities(
|
||||
String fileName, String message) {
|
||||
return Pattern.compile(
|
||||
|
||||
@@ -56,6 +56,7 @@ import java.util.stream.Stream;
|
||||
// XXX: Also recognize empty builders and `emptyBuilder.build()` invocations.
|
||||
public final class IsEmpty implements Matcher<ExpressionTree> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Integer ZERO = 0;
|
||||
private static final Pattern EMPTY_INSTANCE_FACTORY_METHOD_PATTERN = Pattern.compile("empty.*");
|
||||
private static final Matcher<Tree> EMPTY_COLLECTION_CONSTRUCTOR_ARGUMENT =
|
||||
anyOf(isPrimitiveType(), isSubtypeOf(Comparator.class));
|
||||
@@ -145,7 +146,7 @@ public final class IsEmpty implements Matcher<ExpressionTree> {
|
||||
|
||||
NewArrayTree newArray = (NewArrayTree) tree;
|
||||
return (!newArray.getDimensions().isEmpty()
|
||||
&& ASTHelpers.constValue(newArray.getDimensions().get(0), Integer.class) == 0)
|
||||
&& ZERO.equals(ASTHelpers.constValue(newArray.getDimensions().get(0), Integer.class)))
|
||||
|| (newArray.getInitializers() != null && newArray.getInitializers().isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import org.checkerframework.checker.mustcall.qual.MustCall;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
@@ -149,7 +150,7 @@ final class AnnotatedCompositeCodeTransformerTest {
|
||||
ImmutableSet<? extends Annotation> annotations,
|
||||
Context expectedContext,
|
||||
Description returnedDescription) {
|
||||
CodeTransformer codeTransformer = mock();
|
||||
@MustCall CodeTransformer codeTransformer = mock();
|
||||
|
||||
when(codeTransformer.annotations()).thenReturn(indexAnnotations(annotations));
|
||||
doAnswer(
|
||||
@@ -183,7 +184,7 @@ final class AnnotatedCompositeCodeTransformerTest {
|
||||
private static Context context() {
|
||||
// XXX: Use `ErrorProneOptions#processArgs` to test the
|
||||
// `AnnotatedCompositeCodeTransformer#overrideSeverity` logic.
|
||||
Context context = mock();
|
||||
@MustCall Context context = mock();
|
||||
when(context.get(ErrorProneOptions.class)).thenReturn(ErrorProneOptions.empty());
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,9 @@ abstract class AbstractMatcherTestChecker extends BugChecker implements Compilat
|
||||
@Override
|
||||
public Description matchCompilationUnit(CompilationUnitTree compilationUnit, VisitorState state) {
|
||||
new TreePathScanner<@Nullable Void, @Nullable Void>() {
|
||||
// XXX: Update `TreePathScanner#scan` stub to declare its first parameter `@Nullable`.
|
||||
@Override
|
||||
@SuppressWarnings("nullness:argument")
|
||||
public @Nullable Void scan(@Nullable Tree tree, @Nullable Void unused) {
|
||||
if (tree instanceof ExpressionTree) {
|
||||
TreePath path = new TreePath(getCurrentPath(), tree);
|
||||
|
||||
@@ -55,6 +55,12 @@ final class IsEmptyTest {
|
||||
" return new int[][] {{0}};",
|
||||
" }",
|
||||
"",
|
||||
" // XXX: Renumber the methods below.",
|
||||
" int[] negative5X() {",
|
||||
" int i = hashCode();",
|
||||
" return new int[i];",
|
||||
" }",
|
||||
"",
|
||||
" Random negative5() {",
|
||||
" return new Random();",
|
||||
" }",
|
||||
|
||||
Reference in New Issue
Block a user