mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 15:49:33 +00:00
Compare commits
34 Commits
website
...
junie-init
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03b36a01c7 | ||
|
|
401b7f5f67 | ||
|
|
411066bedb | ||
|
|
bedf588e2a | ||
|
|
3a629b11ec | ||
|
|
fc2eb57b40 | ||
|
|
1c429f0d1c | ||
|
|
ac6ffc72e9 | ||
|
|
07399bb4ef | ||
|
|
aa988ef2b0 | ||
|
|
b58be2b89b | ||
|
|
8fa90f6121 | ||
|
|
6ba03c6352 | ||
|
|
912e06885d | ||
|
|
e803a5d333 | ||
|
|
4a1ad1b991 | ||
|
|
80d433f051 | ||
|
|
afd9703ce6 | ||
|
|
f9d310bc4b | ||
|
|
a3a9ca0bf0 | ||
|
|
0e609aeb1c | ||
|
|
e9dae1d66c | ||
|
|
f0ad9d21e6 | ||
|
|
7138aa2100 | ||
|
|
de4667628f | ||
|
|
5e958fe20b | ||
|
|
baa921caac | ||
|
|
ba040bd191 | ||
|
|
a3a20b52e5 | ||
|
|
5d8d27176b | ||
|
|
d878a57a8e | ||
|
|
eaec12f460 | ||
|
|
da7dafb6e7 | ||
|
|
5a7aaf12d6 |
12
.devcontainer/devcontainer.json
Normal file
12
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Java",
|
||||
"image": "mcr.microsoft.com/devcontainers/java:1-21",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/java:1": {
|
||||
"version": "none",
|
||||
"installMaven": "true",
|
||||
"mavenVersion": "3.8.6",
|
||||
"installGradle": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
22
.github/workflows/deploy-website.yml
vendored
22
.github/workflows/deploy-website.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -39,30 +39,26 @@ jobs:
|
||||
www.bestpractices.dev:443
|
||||
www.youtube.com:443
|
||||
youtrack.jetbrains.com:443
|
||||
- name: Check out code and set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.0
|
||||
- name: Check out code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
java-version: 17.0.13
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.9
|
||||
persist-credentials: false
|
||||
- uses: ruby/setup-ruby@1a615958ad9d422dd932dc1d5823942ee002799f # v1.227.0
|
||||
with:
|
||||
working-directory: ./website
|
||||
bundler-cache: true
|
||||
- name: Configure Github Pages
|
||||
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
|
||||
- name: Compile project and extract data
|
||||
run: mvn -T1C clean install -DskipTests -Dverification.skip
|
||||
- name: Generate documentation
|
||||
run: mvn exec:java@generate-docs -pl documentation-support
|
||||
run: ./generate-docs.sh
|
||||
- name: Build website with Jekyll
|
||||
working-directory: ./website
|
||||
run: bundle exec jekyll build
|
||||
- name: Validate HTML output
|
||||
working-directory: ./website
|
||||
# XXX: Bealdung and StackOverflow return HTTP 403 responses when run on
|
||||
# a GitHub Action node.
|
||||
run: bundle exec htmlproofer --no-check-external-hash --swap-url 'https\://error-prone.picnic.tech:' --ignore-urls '/^https:\/\/(www\.baeldung\.com|stackoverflow\.com)\/.*/' ./_site
|
||||
# XXX: Drop `--disable_external true` once we fully adopted the
|
||||
# "Refaster rules" terminology on our website and in the code.
|
||||
run: bundle exec htmlproofer --disable_external true --check-external-hash false ./_site
|
||||
- name: Upload website as artifact
|
||||
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
|
||||
with:
|
||||
@@ -79,7 +75,7 @@ jobs:
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
22
.github/workflows/junie.yml
vendored
Normal file
22
.github/workflows/junie.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Junie
|
||||
run-name: Junie run ${{ inputs.run_id }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_id:
|
||||
description: "id of workflow process"
|
||||
required: true
|
||||
workflow_params:
|
||||
description: "stringified params"
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
call-workflow-passing-data:
|
||||
uses: jetbrains-junie/junie-workflows/.github/workflows/ej-issue.yml@main
|
||||
with:
|
||||
workflow_params: ${{ inputs.workflow_params }}
|
||||
2
.github/workflows/openssf-scorecard.yml
vendored
2
.github/workflows/openssf-scorecard.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
2
.github/workflows/pitest-analyze-pr.yml
vendored
2
.github/workflows/pitest-analyze-pr.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
2
.github/workflows/pitest-update-pr.yml
vendored
2
.github/workflows/pitest-update-pr.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
2
.github/workflows/run-integration-tests.yml
vendored
2
.github/workflows/run-integration-tests.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
integration-test: [ "checkstyle", "metrics", "prometheus-java-client" ]
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
2
.github/workflows/sonarcloud.yml
vendored
2
.github/workflows/sonarcloud.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>documentation-support</artifactId>
|
||||
@@ -28,18 +28,10 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-guava</artifactId>
|
||||
@@ -84,10 +76,6 @@
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
@@ -116,29 +104,4 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-docs</id>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<mainClass>tech.picnic.errorprone.documentation.JekyllCollectionGenerator</mainClass>
|
||||
<arguments>
|
||||
<argument>${maven.multiModuleProjectDirectory}</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -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.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@@ -167,7 +168,10 @@ public final class BugPatternTestExtractor implements Extractor<BugPatternTestCa
|
||||
* 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), "Instance method invocation must have receiver");
|
||||
|
||||
String path = ASTHelpers.constValue(inputTree.getArguments().get(0), String.class);
|
||||
Optional<String> inputCode = getSourceCode(inputTree);
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableTable.toImmutableTable;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.documentation.BugPatternExtractor.BugPatternDocumentation;
|
||||
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.BugPatternTestCase;
|
||||
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.BugPatternTestCases;
|
||||
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.IdentificationTestEntry;
|
||||
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.ReplacementTestEntry;
|
||||
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.TestEntry;
|
||||
import tech.picnic.errorprone.documentation.RefasterRuleCollectionTestExtractor.RefasterTestCase;
|
||||
import tech.picnic.errorprone.documentation.RefasterRuleCollectionTestExtractor.RefasterTestCases;
|
||||
|
||||
/**
|
||||
* A command line utility that produces configuration files for the Jekyll-based Error Prone Support
|
||||
* website.
|
||||
*/
|
||||
// XXX: Expand the class documentation.
|
||||
// XXX: Rename this class. Then also update the reference in `website/.gitignore`.
|
||||
// XXX: Now that we have bug checkers in multiple Maven modules, we should
|
||||
// likely document the source of each check on the website, perhaps even
|
||||
// grouping them by module.
|
||||
public final class JekyllCollectionGenerator {
|
||||
// XXX: Find a bette name. Also, externalize this.
|
||||
private static final PathMatcher PATH_MATCHER =
|
||||
FileSystems.getDefault().getPathMatcher("glob:**/target/docs/*.json");
|
||||
|
||||
// XXX: Review class setup.
|
||||
private JekyllCollectionGenerator() {}
|
||||
|
||||
/**
|
||||
* Runs the application.
|
||||
*
|
||||
* @param args Arguments to the application; must specify the path to the Error Prone Support
|
||||
* project root, and nothing else.
|
||||
* @throws IOException If any file could not be read or written.
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
checkArgument(args.length == 1, "Precisely one project root path must be provided");
|
||||
Path projectRoot = Path.of(args[0]).toAbsolutePath();
|
||||
|
||||
generateIndex(projectRoot);
|
||||
PageGenerator.apply(projectRoot);
|
||||
}
|
||||
|
||||
private static void generateIndex(Path projectRoot) throws IOException {
|
||||
try (BufferedWriter writer =
|
||||
Files.newBufferedWriter(projectRoot.resolve("website").resolve("index.md"), UTF_8)) {
|
||||
writer.write("---");
|
||||
writer.newLine();
|
||||
writer.write("layout: default");
|
||||
writer.newLine();
|
||||
writer.write("title: Home");
|
||||
writer.newLine();
|
||||
writer.write("nav_order: 1");
|
||||
writer.newLine();
|
||||
writer.write("---");
|
||||
writer.newLine();
|
||||
writer.write(
|
||||
Files.readString(projectRoot.resolve("README.md")).replace("=\"website/", "=\""));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Review this class should be split in two: one for bug patterns and one for Refaster rules.
|
||||
private static final class PageGenerator extends SimpleFileVisitor<Path> {
|
||||
private static final Splitter LINE_SPLITTER = Splitter.on(System.lineSeparator());
|
||||
private static final YAMLMapper YAML_MAPPER =
|
||||
YAMLMapper.builder()
|
||||
.visibility(PropertyAccessor.FIELD, Visibility.ANY)
|
||||
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
||||
.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)
|
||||
.enable(YAMLGenerator.Feature.USE_PLATFORM_LINE_BREAKS)
|
||||
.build();
|
||||
|
||||
private final List<BugPatternDocumentation> bugPatterns = new ArrayList<>();
|
||||
private final List<BugPatternTestCases> bugPatternTests = new ArrayList<>();
|
||||
private final List<RefasterTestCases> refasterRuleCollectionTests = new ArrayList<>();
|
||||
|
||||
static void apply(Path projectRoot) throws IOException {
|
||||
PageGenerator pageGenerator = new PageGenerator();
|
||||
Files.walkFileTree(projectRoot, pageGenerator);
|
||||
pageGenerator.writePages(projectRoot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||
if (!PATH_MATCHER.matches(file)) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
// XXX: If we use a consistent ID separator, then this can become a switch statement. Now we
|
||||
// depend on evaluation order.
|
||||
// XXX: Alternatively, use polymorphism and let Jackson figure it out.
|
||||
// XXX: If we stick with an ID-based approach, then deduplicate the ID references here and in
|
||||
// the `Extractor` implementations.
|
||||
String fileName = file.getFileName().toString();
|
||||
if (fileName.startsWith("bugpattern-test")) {
|
||||
bugPatternTests.add(Json.read(file, BugPatternTestCases.class));
|
||||
} else if (fileName.startsWith("bugpattern")) {
|
||||
bugPatterns.add(Json.read(file, BugPatternDocumentation.class));
|
||||
} else if (fileName.startsWith("refaster-rule-collection-test")) {
|
||||
refasterRuleCollectionTests.add(Json.read(file, RefasterTestCases.class));
|
||||
} else {
|
||||
// XXX: Handle differently?
|
||||
throw new IllegalStateException("Unexpected file: " + fileName);
|
||||
}
|
||||
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
private void writePages(Path projectRoot) throws IOException {
|
||||
Path website = projectRoot.resolve("website");
|
||||
writePages(
|
||||
website.resolve("_bugpatterns"),
|
||||
getJekyllBugPatternDescriptions(projectRoot),
|
||||
JekyllBugPatternDescription::name);
|
||||
writePages(
|
||||
website.resolve("_refasterrules"),
|
||||
getJekyllRefasterRuleCollectionDescription(),
|
||||
JekyllRefasterRuleCollectionDescription::name);
|
||||
}
|
||||
|
||||
private static <T> void writePages(
|
||||
Path directory, ImmutableList<T> documents, Function<T, String> nameExtractor)
|
||||
throws IOException {
|
||||
for (T document : documents) {
|
||||
Files.createDirectories(directory);
|
||||
try (BufferedWriter writer =
|
||||
Files.newBufferedWriter(
|
||||
directory.resolve(nameExtractor.apply(document) + ".md"), UTF_8)) {
|
||||
YAML_MAPPER.writeValue(writer, document);
|
||||
writer.write("---");
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableList<JekyllBugPatternDescription> getJekyllBugPatternDescriptions(
|
||||
Path projectRoot) {
|
||||
ImmutableListMultimap<String, TestEntry> bugPatternTestCases =
|
||||
bugPatternTests.stream()
|
||||
.flatMap(testCases -> testCases.testCases().stream())
|
||||
.collect(
|
||||
flatteningToImmutableListMultimap(
|
||||
BugPatternTestCase::classUnderTest, t -> t.entries().stream()));
|
||||
|
||||
return bugPatterns.stream()
|
||||
.map(
|
||||
b ->
|
||||
new AutoValue_JekyllCollectionGenerator_JekyllBugPatternDescription(
|
||||
b.name(),
|
||||
b.name(),
|
||||
b.summary(),
|
||||
b.severityLevel(),
|
||||
b.tags(),
|
||||
// XXX: Derive `Path` from filesytem.
|
||||
projectRoot.relativize(Path.of(b.source())).toString(),
|
||||
bugPatternTestCases.get(b.fullyQualifiedName()).stream()
|
||||
.filter(t -> t.type() == TestEntry.TestType.IDENTIFICATION)
|
||||
.map(t -> ((IdentificationTestEntry) t).code())
|
||||
.collect(toImmutableList()),
|
||||
bugPatternTestCases.get(b.fullyQualifiedName()).stream()
|
||||
.filter(t -> t.type() == TestEntry.TestType.REPLACEMENT)
|
||||
.map(t -> generateDiff((ReplacementTestEntry) t))
|
||||
.collect(toImmutableList())))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
private ImmutableList<JekyllRefasterRuleCollectionDescription>
|
||||
getJekyllRefasterRuleCollectionDescription() {
|
||||
ImmutableTable<String, Boolean, List<RefasterTestCase>> refasterTests =
|
||||
refasterRuleCollectionTests.stream()
|
||||
.collect(
|
||||
toImmutableTable(
|
||||
RefasterTestCases::ruleCollection,
|
||||
RefasterTestCases::isInput,
|
||||
RefasterTestCases::testCases));
|
||||
|
||||
return refasterTests.rowMap().entrySet().stream()
|
||||
.map(
|
||||
c ->
|
||||
new AutoValue_JekyllCollectionGenerator_JekyllRefasterRuleCollectionDescription(
|
||||
c.getKey(),
|
||||
c.getKey(),
|
||||
// XXX: Derive severity from input.
|
||||
SUGGESTION,
|
||||
// XXX: Derive tags from input (or drop this feature).
|
||||
ImmutableList.of("Simplification"),
|
||||
// XXX: Derive source location from input.
|
||||
String.format(
|
||||
"error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/%s.java",
|
||||
c.getKey()),
|
||||
getRules(c.getValue().get(true), c.getValue().get(false))))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
private static ImmutableList<JekyllRefasterRuleCollectionDescription.Rule> getRules(
|
||||
@Nullable List<RefasterTestCase> inputTests, @Nullable List<RefasterTestCase> outputTests) {
|
||||
ImmutableMap<String, String> inputs = indexRefasterTestData(inputTests);
|
||||
ImmutableMap<String, String> outputs = indexRefasterTestData(outputTests);
|
||||
|
||||
return Sets.intersection(inputs.keySet(), outputs.keySet()).stream()
|
||||
.map(
|
||||
name ->
|
||||
new AutoValue_JekyllCollectionGenerator_JekyllRefasterRuleCollectionDescription_Rule(
|
||||
name,
|
||||
// XXX: Derive severity from input.
|
||||
SUGGESTION,
|
||||
// XXX: Derive tags from input (or drop this feature).
|
||||
ImmutableList.of("Simplification"),
|
||||
generateDiff(
|
||||
requireNonNull(inputs.get(name), "Input"),
|
||||
requireNonNull(outputs.get(name), "Output"))))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
private static ImmutableMap<String, String> indexRefasterTestData(
|
||||
@Nullable List<RefasterTestCase> data) {
|
||||
return data == null
|
||||
? ImmutableMap.of()
|
||||
: data.stream()
|
||||
.collect(toImmutableMap(RefasterTestCase::name, RefasterTestCase::content));
|
||||
}
|
||||
|
||||
private static String generateDiff(ReplacementTestEntry testEntry) {
|
||||
return generateDiff(testEntry.input(), testEntry.output());
|
||||
}
|
||||
|
||||
private static String generateDiff(String before, String after) {
|
||||
// XXX: Extract splitter.
|
||||
List<String> originalLines = LINE_SPLITTER.splitToList(before);
|
||||
List<String> replacementLines = LINE_SPLITTER.splitToList(after);
|
||||
|
||||
Patch<String> diff = DiffUtils.diff(originalLines, replacementLines);
|
||||
|
||||
return UnifiedDiffUtils.generateUnifiedDiff(
|
||||
"", "", originalLines, diff, Integer.MAX_VALUE / 2)
|
||||
.stream()
|
||||
.skip(3)
|
||||
.collect(joining(System.lineSeparator()));
|
||||
}
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class JekyllBugPatternDescription {
|
||||
// XXX: Make this a derived property?
|
||||
abstract String title();
|
||||
|
||||
abstract String name();
|
||||
|
||||
abstract String summary();
|
||||
|
||||
abstract SeverityLevel severity();
|
||||
|
||||
abstract ImmutableList<String> tags();
|
||||
|
||||
// XXX: The documentation could link to the original test code. Perhaps even with the correct
|
||||
// line numbers.
|
||||
abstract String source();
|
||||
|
||||
// XXX: The `identification` and `replacement` fields have odd names.
|
||||
abstract ImmutableList<String> identification();
|
||||
|
||||
abstract ImmutableList<String> replacement();
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class JekyllRefasterRuleCollectionDescription {
|
||||
// XXX: Make this a derived property?
|
||||
abstract String title();
|
||||
|
||||
abstract String name();
|
||||
|
||||
abstract SeverityLevel severity();
|
||||
|
||||
abstract ImmutableList<String> tags();
|
||||
|
||||
// XXX: The documentation could link to the original test code. Perhaps even with the correct
|
||||
// line numbers. If we do this, we should do the same for individual rules.
|
||||
abstract String source();
|
||||
|
||||
abstract ImmutableList<Rule> rules();
|
||||
|
||||
@AutoValue
|
||||
abstract static class Rule {
|
||||
abstract String name();
|
||||
|
||||
abstract SeverityLevel severity();
|
||||
|
||||
abstract ImmutableList<String> tags();
|
||||
|
||||
abstract String diff();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package tech.picnic.errorprone.documentation.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Object containing all data related to a Refaster template collection. This is solely used for
|
||||
* serialization.
|
||||
*/
|
||||
// XXX: This class is not yet used.
|
||||
@AutoValue
|
||||
@JsonDeserialize(as = AutoValue_RefasterTemplateCollectionData.class)
|
||||
abstract class RefasterTemplateCollectionData {
|
||||
static RefasterTemplateCollectionData create(
|
||||
String name, String description, String link, ImmutableList<RefasterTemplateData> templates) {
|
||||
return new AutoValue_RefasterTemplateCollectionData(name, description, link, templates);
|
||||
}
|
||||
|
||||
abstract String name();
|
||||
|
||||
abstract String description();
|
||||
|
||||
abstract String link();
|
||||
|
||||
abstract ImmutableList<RefasterTemplateData> templates();
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package tech.picnic.errorprone.documentation.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
|
||||
// XXX: This class is not yet used.
|
||||
@AutoValue
|
||||
@JsonDeserialize(as = AutoValue_RefasterTemplateData.class)
|
||||
abstract class RefasterTemplateData {
|
||||
static RefasterTemplateData create(
|
||||
String name, String description, String link, SeverityLevel severityLevel) {
|
||||
return new AutoValue_RefasterTemplateData(name, description, link, severityLevel);
|
||||
}
|
||||
|
||||
abstract String name();
|
||||
|
||||
abstract String description();
|
||||
|
||||
abstract String link();
|
||||
|
||||
abstract SeverityLevel severityLevel();
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package tech.picnic.errorprone.documentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
// XXX: Implement tests.
|
||||
final class JekyllCollectionGeneratorTest {
|
||||
@Test
|
||||
void foo() throws IOException {
|
||||
JekyllCollectionGenerator.main(
|
||||
new String[] {"/home/sschroevers/workspace/picnic/error-prone-support"});
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
@@ -62,6 +62,16 @@
|
||||
<artifactId>auto-value-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- XXX: JSR-305 (meta-)annotation usage by some dependencies triggers
|
||||
NullAway to attempt to load said annotations. As such some modules
|
||||
require these annotations to be on the classpath. Periodically review
|
||||
whether we can drop this dependeny declaration. See
|
||||
https://github.com/uber/NullAway/issues/1171. -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
|
||||
@@ -11,6 +11,7 @@ import static com.google.errorprone.matchers.Matchers.not;
|
||||
import static com.google.errorprone.matchers.Matchers.returnStatement;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.toType;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
@@ -79,7 +80,10 @@ public final class DirectReturn extends BugChecker implements BlockTreeMatcher {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
Symbol variableSymbol = ASTHelpers.getSymbol(((ReturnTree) finalStatement).getExpression());
|
||||
Symbol variableSymbol =
|
||||
requireNonNull(
|
||||
ASTHelpers.getSymbol(((ReturnTree) finalStatement).getExpression()),
|
||||
"Missing symbol for returned variable");
|
||||
StatementTree precedingStatement = statements.get(statements.size() - 2);
|
||||
|
||||
return tryMatchAssignment(variableSymbol, precedingStatement)
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
@@ -33,6 +34,8 @@ import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -178,30 +181,45 @@ public final class ExplicitArgumentEnumeration extends BugChecker
|
||||
state.getTypes())
|
||||
.collect(toImmutableList());
|
||||
|
||||
/*
|
||||
* If all overloads have a single parameter, and at least one of them is a varargs method, then
|
||||
* we assume that unwrapping the iterable argument will cause a suitable overload to be invoked.
|
||||
* (Note that there may be multiple varargs overloads, either with different parameter types, or
|
||||
* due to method overriding; this check does not attempt to determine which exact method or
|
||||
* overload will be invoked as a result of the suggested simplification.)
|
||||
*
|
||||
* Note that this is a (highly!) imperfect heuristic, but it is sufficient to prevent e.g.
|
||||
* unwrapping of arguments to `org.jooq.impl.DSL#row`, which can cause the expression's return
|
||||
* type to change from `RowN` to (e.g.) `Row2`.
|
||||
*/
|
||||
// XXX: There are certainly cases where it _would_ be nice to unwrap the arguments to
|
||||
// `org.jooq.impl.DSL#row(Collection<?>)`. Look into this.
|
||||
// XXX: Ideally we do check that one of the overloads accepts the unwrapped arguments.
|
||||
// XXX: Ideally we validate that eligible overloads have compatible return types.
|
||||
boolean hasLikelySuitableVarargsOverload =
|
||||
overloads.stream().allMatch(m -> m.params().size() == 1)
|
||||
&& overloads.stream().anyMatch(MethodSymbol::isVarArgs);
|
||||
|
||||
return hasLikelySuitableVarargsOverload
|
||||
return hasLikelySuitableVarargsOverload(method, overloads, state)
|
||||
? Optional.of(SourceCode.unwrapMethodInvocation(argument, state))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether it is likely that, if the argument to the given method is unwrapped, a suitable
|
||||
* varargs overload will be invoked instead.
|
||||
*
|
||||
* <p>If all overloads have a single parameter, and at least one of them is a suitably-typed
|
||||
* varargs method, then we assume that unwrapping the iterable argument will cause a suitable
|
||||
* overload to be invoked. (Note that there may be multiple varargs overloads due to method
|
||||
* overriding; this check does not attempt to determine which exact method or overload will be
|
||||
* invoked as a result of the suggested simplification.)
|
||||
*
|
||||
* <p>Note that this is a (highly!) imperfect heuristic, but it is sufficient to prevent e.g.
|
||||
* unwrapping of arguments to `org.jooq.impl.DSL#row`, which can cause the expression's return
|
||||
* type to change from `RowN` to (e.g.) `Row2`.
|
||||
*/
|
||||
// XXX: There are certainly cases where it _would_ be nice to unwrap the arguments to
|
||||
// `org.jooq.impl.DSL#row(Collection<?>)`. Look into this.
|
||||
// XXX: Ideally we validate that eligible overloads have compatible return types.
|
||||
private static boolean hasLikelySuitableVarargsOverload(
|
||||
MethodSymbol method, ImmutableList<MethodSymbol> overloads, VisitorState state) {
|
||||
Types types = state.getTypes();
|
||||
// XXX: This logic is fragile, as it assumes that the method parameter's type is of the form
|
||||
// `X<T>`, where `T` is the type of the explicitly enumerated values passed to the expression to
|
||||
// be unwrapped. This should generally hold, given the types returned by the
|
||||
// `EXPLICIT_ITERABLE_CREATOR` expressions: `Iterable<T>`, `List<T>`, `Set<T>`, etc.
|
||||
Type parameterType =
|
||||
Iterables.getOnlyElement(
|
||||
Iterables.getOnlyElement(method.getParameters()).type.getTypeArguments());
|
||||
return overloads.stream().allMatch(m -> m.params().size() == 1)
|
||||
&& overloads.stream()
|
||||
.filter(MethodSymbol::isVarArgs)
|
||||
.map(m -> types.elemtype(Iterables.getOnlyElement(m.getParameters()).type))
|
||||
.anyMatch(varArgsType -> types.containsType(parameterType, varArgsType));
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix> trySuggestCallingCustomAlternative(
|
||||
MethodInvocationTree tree, MethodInvocationTree argument, VisitorState state) {
|
||||
return ALTERNATIVE_METHODS.rowMap().entrySet().stream()
|
||||
|
||||
@@ -17,6 +17,7 @@ import static com.google.errorprone.matchers.Matchers.isSameType;
|
||||
import static com.google.errorprone.matchers.Matchers.methodHasParameters;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.toType;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
@@ -129,7 +130,10 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
Type parameterType = ASTHelpers.getType(Iterables.getOnlyElement(tree.getParameters()));
|
||||
Type parameterType =
|
||||
requireNonNull(
|
||||
ASTHelpers.getType(Iterables.getOnlyElement(tree.getParameters())),
|
||||
"Missing type for method parameter");
|
||||
|
||||
return findMethodSourceAnnotation(tree, state)
|
||||
.flatMap(
|
||||
@@ -173,7 +177,9 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
|
||||
private static Optional<MethodTree> findMatchingSibling(
|
||||
MethodTree tree, Predicate<? super MethodTree> predicate, VisitorState state) {
|
||||
return state.findEnclosing(ClassTree.class).getMembers().stream()
|
||||
return requireNonNull(state.findEnclosing(ClassTree.class), "No class enclosing method")
|
||||
.getMembers()
|
||||
.stream()
|
||||
.filter(MethodTree.class::isInstance)
|
||||
.map(MethodTree.class::cast)
|
||||
.filter(not(tree::equals))
|
||||
|
||||
@@ -5,6 +5,7 @@ import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
@@ -86,7 +87,9 @@ public final class NonEmptyMono extends BugChecker implements MethodInvocationTr
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
|
||||
ExpressionTree receiver =
|
||||
requireNonNull(
|
||||
ASTHelpers.getReceiver(tree), "Instance method invocation must have receiver");
|
||||
if (!NON_EMPTY_MONO.matches(receiver, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
@@ -204,6 +204,11 @@ final class AssertJEnumerableRules {
|
||||
return enumAssert.hasSize(iterable.length);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, CharSequence iterable) {
|
||||
return enumAssert.hasSize(iterable.length());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, S> after(EnumerableAssert<?, S> enumAssert, Iterable<E> iterable) {
|
||||
return enumAssert.hasSameSizeAs(iterable);
|
||||
|
||||
@@ -515,8 +515,14 @@ final class ReactorRules {
|
||||
mono.switchIfEmpty(Mono.empty()), mono.flux().next(), mono.flux().singleOrEmpty());
|
||||
}
|
||||
|
||||
// XXX: Consider filing a SonarCloud issue for the S2637 false positive.
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Mono<@Nullable Void> mono) {
|
||||
@SuppressWarnings({
|
||||
"java:S2637" /* False positive: result is never `null`. */,
|
||||
"java:S4968" /* Result may be `Mono<Void>`. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
Mono<? extends @Nullable Void> before2(Mono<@Nullable Void> mono) {
|
||||
return Refaster.anyOf(mono.ignoreElement(), mono.then());
|
||||
}
|
||||
|
||||
@@ -945,7 +951,8 @@ final class ReactorRules {
|
||||
/** Prefer direct invocation of {@link Mono#then()}} over more contrived alternatives. */
|
||||
static final class MonoThen<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Mono<T> mono) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Mono<T> mono) {
|
||||
return Refaster.anyOf(
|
||||
mono.ignoreElement().then(),
|
||||
mono.flux().then(),
|
||||
@@ -954,7 +961,8 @@ final class ReactorRules {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Mono<T> mono) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Mono<T> mono) {
|
||||
return mono.then();
|
||||
}
|
||||
}
|
||||
@@ -962,17 +970,25 @@ final class ReactorRules {
|
||||
/** Avoid vacuous invocations of {@link Flux#ignoreElements()}. */
|
||||
static final class FluxThen<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Flux<T> flux) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Flux<T> flux) {
|
||||
return flux.ignoreElements().then();
|
||||
}
|
||||
|
||||
// XXX: Consider filing a SonarCloud issue for the S2637 false positive.
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Flux<@Nullable Void> flux) {
|
||||
@SuppressWarnings({
|
||||
"java:S2637" /* False positive: result is never `null`. */,
|
||||
"java:S4968" /* Result may be `Mono<Void>`. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
Mono<? extends @Nullable Void> before2(Flux<@Nullable Void> flux) {
|
||||
return flux.ignoreElements();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Flux<T> flux) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Flux<T> flux) {
|
||||
return flux.then();
|
||||
}
|
||||
}
|
||||
@@ -980,12 +996,14 @@ final class ReactorRules {
|
||||
/** Avoid vacuous invocations of {@link Mono#ignoreElement()}. */
|
||||
static final class MonoThenEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
return mono.ignoreElement().thenEmpty(publisher);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
return mono.thenEmpty(publisher);
|
||||
}
|
||||
}
|
||||
@@ -993,12 +1011,14 @@ final class ReactorRules {
|
||||
/** Avoid vacuous invocations of {@link Flux#ignoreElements()}. */
|
||||
static final class FluxThenEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
return flux.ignoreElements().thenEmpty(publisher);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
return flux.thenEmpty(publisher);
|
||||
}
|
||||
}
|
||||
@@ -1054,7 +1074,8 @@ final class ReactorRules {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Mono<T> mono1, Mono<@Nullable Void> mono2) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before2(Mono<T> mono1, Mono<@Nullable Void> mono2) {
|
||||
return mono1.thenEmpty(mono2);
|
||||
}
|
||||
|
||||
@@ -1072,7 +1093,8 @@ final class ReactorRules {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Flux<T> flux, Mono<@Nullable Void> mono) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before2(Flux<T> flux, Mono<@Nullable Void> mono) {
|
||||
return flux.thenEmpty(mono);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,14 +23,16 @@ final class RxJava2AdapterRules {
|
||||
/** Use the fluent API style when using {@link RxJava2Adapter#completableToMono}. */
|
||||
static final class CompletableToMono {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Completable completable) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Completable completable) {
|
||||
return Refaster.anyOf(
|
||||
RxJava2Adapter.completableToMono(completable),
|
||||
completable.to(RxJava2Adapter::completableToMono));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Completable completable) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Completable completable) {
|
||||
return completable.as(RxJava2Adapter::completableToMono);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ final class ExplicitArgumentEnumerationTest {
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import io.micrometer.core.instrument.Counter;",
|
||||
"import io.micrometer.core.instrument.Tag;",
|
||||
"import org.jooq.impl.DSL;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.test.StepVerifier;",
|
||||
@@ -32,6 +34,8 @@ final class ExplicitArgumentEnumerationTest {
|
||||
"",
|
||||
" DSL.row(ImmutableList.of(1, 2));",
|
||||
"",
|
||||
" Counter.builder(\"foo\").tags(ImmutableList.of(Tag.of(\"bar\", \"baz\")));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" unaryMethod(ImmutableList.of(1, 2));",
|
||||
" unaryMethodWithLessVisibleOverload(ImmutableList.of(1, 2));",
|
||||
|
||||
@@ -67,10 +67,11 @@ final class AssertJEnumerableRulesTest implements RefasterRuleCollectionTestCase
|
||||
assertThat(ImmutableSet.of(4)).size().isBetween(5, 6));
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Integer>> testEnumerableAssertHasSameSizeAs() {
|
||||
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertHasSameSizeAs() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSize(Iterables.size(ImmutableSet.of(2))),
|
||||
assertThat(ImmutableSet.of(3)).hasSize(ImmutableSet.of(4).size()),
|
||||
assertThat(ImmutableSet.of(5)).hasSize(new Integer[0].length));
|
||||
assertThat("foo").hasSize(Iterables.size(ImmutableSet.of(1))),
|
||||
assertThat("bar").hasSize(ImmutableSet.of(2).size()),
|
||||
assertThat("baz").hasSize(new Integer[0].length),
|
||||
assertThat("qux").hasSize("quux".length()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,11 @@ final class AssertJEnumerableRulesTest implements RefasterRuleCollectionTestCase
|
||||
assertThat(ImmutableSet.of(4)).hasSizeBetween(5, 6));
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Integer>> testEnumerableAssertHasSameSizeAs() {
|
||||
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertHasSameSizeAs() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSameSizeAs(ImmutableSet.of(2)),
|
||||
assertThat(ImmutableSet.of(3)).hasSameSizeAs(ImmutableSet.of(4)),
|
||||
assertThat(ImmutableSet.of(5)).hasSameSizeAs(new Integer[0]));
|
||||
assertThat("foo").hasSameSizeAs(ImmutableSet.of(1)),
|
||||
assertThat("bar").hasSameSizeAs(ImmutableSet.of(2)),
|
||||
assertThat("baz").hasSameSizeAs(new Integer[0]),
|
||||
assertThat("qux").hasSameSizeAs("quux"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-experimental</artifactId>
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.sun.source.tree.ReturnTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -126,7 +127,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Symbol sym = ASTHelpers.getSymbol(methodSelect);
|
||||
Symbol sym = ASTHelpers.getSymbol(subTree);
|
||||
return ASTHelpers.isStatic(sym)
|
||||
? constructFix(lambdaExpr, sym.owner, methodSelect)
|
||||
: constructFix(lambdaExpr, "this", methodSelect);
|
||||
@@ -200,7 +201,8 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
Name sName = target.getSimpleName();
|
||||
Optional<SuggestedFix.Builder> fix = constructFix(lambdaExpr, sName, methodName);
|
||||
|
||||
if (!"java.lang".equals(ASTHelpers.enclosingPackage(target).toString())) {
|
||||
PackageSymbol pkg = ASTHelpers.enclosingPackage(target);
|
||||
if (pkg != null && !"java.lang".equals(pkg.toString())) {
|
||||
Name fqName = target.getQualifiedName();
|
||||
if (!sName.equals(fqName)) {
|
||||
return fix.map(b -> b.addImport(fqName.toString()));
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-guidelines</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-utils</artifactId>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package tech.picnic.errorprone.utils;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -115,9 +117,15 @@ public final class AnnotationAttributeMatcher implements Serializable {
|
||||
}
|
||||
|
||||
private static String extractAttributeName(ExpressionTree expr) {
|
||||
return (expr instanceof AssignmentTree assignment)
|
||||
? ASTHelpers.getSymbol(assignment.getVariable()).getSimpleName().toString()
|
||||
: "value";
|
||||
if (!(expr instanceof AssignmentTree assignment)) {
|
||||
return "value";
|
||||
}
|
||||
|
||||
return requireNonNull(
|
||||
ASTHelpers.getSymbol(assignment.getVariable()),
|
||||
"Missing symbol for annotation attribute")
|
||||
.getSimpleName()
|
||||
.toString();
|
||||
}
|
||||
|
||||
// XXX: The caller of this method can be implemented more efficiently in case of a "wholeTypes"
|
||||
|
||||
27
generate-docs.sh
Executable file
27
generate-docs.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e -u -o pipefail
|
||||
|
||||
REPOSITORY_ROOT="$(git rev-parse --show-toplevel)"
|
||||
WEBSITE_ROOT="${REPOSITORY_ROOT}/website"
|
||||
|
||||
generate_homepage() {
|
||||
local homepage="${WEBSITE_ROOT}/index.md"
|
||||
|
||||
echo "Generating ${homepage}..."
|
||||
cat - "${REPOSITORY_ROOT}/README.md" > "${homepage}" << EOF
|
||||
---
|
||||
layout: default
|
||||
title: Home
|
||||
nav_order: 1
|
||||
---
|
||||
EOF
|
||||
|
||||
local macos_compat=""
|
||||
[[ "${OSTYPE}" == "darwin"* ]] && macos_compat="yes"
|
||||
sed -i ${macos_compat:+".bak"} 's/src="website\//src="/g' "${homepage}"
|
||||
sed -i ${macos_compat:+".bak"} 's/srcset="website\//srcset="/g' "${homepage}"
|
||||
}
|
||||
|
||||
# Generate the website.
|
||||
generate_homepage
|
||||
@@ -38,7 +38,7 @@
|
||||
+ <dependency>
|
||||
+ <groupId>com.google.guava</groupId>
|
||||
+ <artifactId>guava</artifactId>
|
||||
+ <version>33.4.0-jre<!-- Renovate: com.google.guava:guava-bom --></version>
|
||||
+ <version>33.4.7-jre<!-- Renovate: com.google.guava:guava-bom --></version>
|
||||
+ </dependency>
|
||||
+ </dependencies>
|
||||
+ </dependencyManagement>
|
||||
|
||||
67
pom.xml
67
pom.xml
@@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Picnic :: Error Prone Support</name>
|
||||
@@ -146,7 +146,7 @@
|
||||
<error-prone.self-check-args />
|
||||
<!-- The build timestamp is derived from the most recent commit
|
||||
timestamp in support of reproducible builds. -->
|
||||
<project.build.outputTimestamp>2025-03-24T10:41:07Z</project.build.outputTimestamp>
|
||||
<project.build.outputTimestamp>2025-04-14T09:36:15Z</project.build.outputTimestamp>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- Glob pattern identifying Refaster rule definition files. These
|
||||
Java classes don't contain "regular" code, and thus require special
|
||||
@@ -211,11 +211,11 @@
|
||||
<version.guava-beta-checker>1.0</version.guava-beta-checker>
|
||||
<version.jdk>17</version.jdk>
|
||||
<version.maven>3.9.9</version.maven>
|
||||
<version.mockito>5.16.1</version.mockito>
|
||||
<version.mockito>5.17.0</version.mockito>
|
||||
<version.nopen-checker>1.0.1</version.nopen-checker>
|
||||
<version.nullaway>0.12.4</version.nullaway>
|
||||
<version.pitest-git>2.2.0</version.pitest-git>
|
||||
<version.rewrite-templating>1.24.1</version.rewrite-templating>
|
||||
<version.nullaway>0.12.6</version.nullaway>
|
||||
<version.pitest-git>2.2.1</version.pitest-git>
|
||||
<version.rewrite-templating>1.25.1</version.rewrite-templating>
|
||||
<version.surefire>3.2.3</version.surefire>
|
||||
</properties>
|
||||
|
||||
@@ -303,6 +303,16 @@
|
||||
<artifactId>auto-value-annotations</artifactId>
|
||||
<version>${version.auto-value}</version>
|
||||
</dependency>
|
||||
<!-- XXX: JSR-305 (meta-)annotation usage by some dependencies
|
||||
triggers NullAway to attempt to load said annotations. As such
|
||||
some modules require these annotations to be on the classpath.
|
||||
Periodically review whether we can drop this dependeny version
|
||||
declaration. See https://github.com/uber/NullAway/issues/1171. -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
@@ -331,7 +341,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.googlejavaformat</groupId>
|
||||
<artifactId>google-java-format</artifactId>
|
||||
<version>1.25.2</version>
|
||||
<version>1.26.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
@@ -341,7 +351,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava-bom</artifactId>
|
||||
<version>33.4.0-jre</version>
|
||||
<version>33.4.7-jre</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -360,22 +370,17 @@
|
||||
<artifactId>nullaway</artifactId>
|
||||
<version>${version.nullaway}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils</artifactId>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-bom</artifactId>
|
||||
<version>1.14.5</version>
|
||||
<version>1.14.6</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
<version>2024.0.4</version>
|
||||
<version>2024.0.5</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -392,7 +397,7 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>2.2.29</version>
|
||||
<version>2.2.30</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
@@ -427,7 +432,7 @@
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.17.4</version>
|
||||
<version>1.17.5</version>
|
||||
</dependency>
|
||||
<!-- Specified so that Renovate will file Maven upgrade PRs, which
|
||||
subsequently will cause `maven-enforcer-plugin` to require that
|
||||
@@ -440,7 +445,7 @@
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.9.23</version>
|
||||
<version>1.9.24</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
@@ -452,7 +457,7 @@
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.49.1</version>
|
||||
<version>3.49.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
@@ -477,7 +482,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.12.1</version>
|
||||
<version>5.12.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -503,7 +508,7 @@
|
||||
<dependency>
|
||||
<groupId>org.openrewrite.recipe</groupId>
|
||||
<artifactId>rewrite-recipe-bom</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.6.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -615,7 +620,7 @@
|
||||
<plugin>
|
||||
<groupId>de.thetaphi</groupId>
|
||||
<artifactId>forbiddenapis</artifactId>
|
||||
<version>3.8</version>
|
||||
<version>3.9</version>
|
||||
<configuration>
|
||||
<bundledSignatures>
|
||||
<bundledSignature>jdk-internal</bundledSignature>
|
||||
@@ -930,7 +935,7 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>10.21.4</version>
|
||||
<version>10.23.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.nohttp</groupId>
|
||||
@@ -1141,7 +1146,7 @@
|
||||
<dependency>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>extra-enforcer-rules</artifactId>
|
||||
<version>1.9.0</version>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -1305,7 +1310,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.2</version>
|
||||
<version>3.5.3</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
@@ -1502,7 +1507,7 @@
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.12</version>
|
||||
<version>0.8.13</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<!-- Refaster rules are tested using a custom method
|
||||
@@ -1532,7 +1537,7 @@
|
||||
<plugin>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-maven</artifactId>
|
||||
<version>1.19.0</version>
|
||||
<version>1.19.1</version>
|
||||
<configuration>
|
||||
<excludedClasses>
|
||||
<!-- AutoValue generated classes. -->
|
||||
@@ -1586,7 +1591,7 @@
|
||||
<plugin>
|
||||
<groupId>org.sonarsource.scanner.maven</groupId>
|
||||
<artifactId>sonar-maven-plugin</artifactId>
|
||||
<version>5.0.0.4389</version>
|
||||
<version>5.1.0.4751</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
@@ -1812,11 +1817,6 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
@@ -1950,6 +1950,7 @@
|
||||
-XepOpt:NullAway:AnnotatedPackages=tech.picnic
|
||||
-XepOpt:NullAway:AssertsEnabled=true
|
||||
-XepOpt:NullAway:CheckOptionalEmptiness=true
|
||||
-XepOpt:NullAway:JSpecifyMode=true
|
||||
-XepOpt:Nullness:Conservative=false
|
||||
-XepOpt:StatementSwitchToExpressionSwitch:EnableDirectConversion=true
|
||||
<!-- Append additional custom arguments. -->
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.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.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-runner</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-support</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<version>0.22.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-test-support</artifactId>
|
||||
|
||||
7
website/.gitignore
vendored
7
website/.gitignore
vendored
@@ -1,13 +1,12 @@
|
||||
# Generated by Bundler and Jekyll.
|
||||
.bundle/
|
||||
Gemfile.lock
|
||||
.jekyll-cache/
|
||||
.jekyll-metadata
|
||||
.sass-cache/
|
||||
_site/
|
||||
vendor/
|
||||
|
||||
# XXX: Update generator name when it's renamed.
|
||||
# Generated by `JekyllCollectionGenerator`.
|
||||
# Generated by `../generate-docs.sh`.
|
||||
*.bak
|
||||
index.md
|
||||
_bugpatterns/
|
||||
_refasterrules/
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.3.5
|
||||
3.1.2
|
||||
|
||||
@@ -1,27 +1,8 @@
|
||||
ruby File.read(".ruby-version").strip
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
# XXX: This dependency group is declared to suppress Ruby depreciation
|
||||
# warnings. Drop once redundant.
|
||||
group :standard_library_replacements do
|
||||
gem "base64", "0.2.0"
|
||||
gem "csv", "3.3.0"
|
||||
gem "logger", "1.6.1"
|
||||
end
|
||||
|
||||
group :jekyll_site_dependencies do
|
||||
gem "jekyll", "4.3.4"
|
||||
gem "jekyll-sitemap", "1.4.0"
|
||||
gem "just-the-docs", "0.10.0"
|
||||
gem "rake", "13.2.1"
|
||||
# XXX: Drop this `sass-embedded` version pinning once various parts of the
|
||||
# ecosystem caught up. See
|
||||
# https://github.com/just-the-docs/just-the-docs/issues/1541#issuecomment-2401649789.
|
||||
gem "sass-embedded", "1.78.0"
|
||||
gem "webrick", "1.9.0"
|
||||
end
|
||||
|
||||
group :website_validation_dependencies do
|
||||
gem "html-proofer", "5.0.9"
|
||||
end
|
||||
gem "html-proofer", "4.4.1"
|
||||
gem "jekyll", "4.2.2"
|
||||
gem "jekyll-sitemap", "1.4"
|
||||
gem "just-the-docs", "0.4.0.rc2"
|
||||
gem "webrick", "1.7"
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (2.0.1)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
afm (0.2.2)
|
||||
async (2.18.0)
|
||||
console (~> 1.26)
|
||||
fiber-annotation
|
||||
io-event (~> 1.6, >= 1.6.5)
|
||||
base64 (0.2.0)
|
||||
bigdecimal (3.1.8)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.3.4)
|
||||
console (1.27.0)
|
||||
fiber-annotation
|
||||
fiber-local (~> 1.1)
|
||||
json
|
||||
csv (3.3.0)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
eventmachine (1.2.7)
|
||||
ffi (1.17.0-aarch64-linux-gnu)
|
||||
ffi (1.17.0-aarch64-linux-musl)
|
||||
ffi (1.17.0-arm-linux-gnu)
|
||||
ffi (1.17.0-arm-linux-musl)
|
||||
ffi (1.17.0-arm64-darwin)
|
||||
ffi (1.17.0-x86-linux-gnu)
|
||||
ffi (1.17.0-x86-linux-musl)
|
||||
ffi (1.17.0-x86_64-darwin)
|
||||
ffi (1.17.0-x86_64-linux-gnu)
|
||||
ffi (1.17.0-x86_64-linux-musl)
|
||||
fiber-annotation (0.2.0)
|
||||
fiber-local (1.1.0)
|
||||
fiber-storage
|
||||
fiber-storage (1.0.0)
|
||||
forwardable-extended (2.6.0)
|
||||
google-protobuf (4.28.3)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
google-protobuf (4.28.3-aarch64-linux)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
google-protobuf (4.28.3-arm64-darwin)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
google-protobuf (4.28.3-x86-linux)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
google-protobuf (4.28.3-x86_64-darwin)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
google-protobuf (4.28.3-x86_64-linux)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
hashery (2.1.2)
|
||||
html-proofer (5.0.9)
|
||||
addressable (~> 2.3)
|
||||
async (~> 2.1)
|
||||
nokogiri (~> 1.13)
|
||||
pdf-reader (~> 2.11)
|
||||
rainbow (~> 3.0)
|
||||
typhoeus (~> 1.3)
|
||||
yell (~> 2.0)
|
||||
zeitwerk (~> 2.5)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
io-event (1.7.3)
|
||||
jekyll (4.3.4)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
i18n (~> 1.0)
|
||||
jekyll-sass-converter (>= 2.0, < 4.0)
|
||||
jekyll-watch (~> 2.0)
|
||||
kramdown (~> 2.3, >= 2.3.1)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
liquid (~> 4.0)
|
||||
mercenary (>= 0.3.6, < 0.5)
|
||||
pathutil (~> 0.9)
|
||||
rouge (>= 3.0, < 5.0)
|
||||
safe_yaml (~> 1.0)
|
||||
terminal-table (>= 1.8, < 4.0)
|
||||
webrick (~> 1.7)
|
||||
jekyll-include-cache (0.2.1)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-sass-converter (3.0.0)
|
||||
sass-embedded (~> 1.54)
|
||||
jekyll-seo-tag (2.8.0)
|
||||
jekyll (>= 3.8, < 5.0)
|
||||
jekyll-sitemap (1.4.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
json (2.7.5)
|
||||
just-the-docs (0.10.0)
|
||||
jekyll (>= 3.8.5)
|
||||
jekyll-include-cache
|
||||
jekyll-seo-tag (>= 2.0)
|
||||
rake (>= 12.3.1)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.4)
|
||||
listen (3.9.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
logger (1.6.1)
|
||||
mercenary (0.4.0)
|
||||
nokogiri (1.16.7-aarch64-linux)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.16.7-arm-linux)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.16.7-arm64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.16.7-x86-linux)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.16.7-x86_64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.16.7-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
pdf-reader (2.13.0)
|
||||
Ascii85 (>= 1.0, < 3.0, != 2.0.0)
|
||||
afm (~> 0.2.1)
|
||||
hashery (~> 2.0)
|
||||
ruby-rc4
|
||||
ttfunk
|
||||
public_suffix (6.0.1)
|
||||
racc (1.8.1)
|
||||
rainbow (3.1.1)
|
||||
rake (13.2.1)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.11.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.3.9)
|
||||
rouge (4.4.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
safe_yaml (1.0.5)
|
||||
sass-embedded (1.78.0-aarch64-linux-gnu)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-aarch64-linux-musl)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-arm-linux-gnueabihf)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-arm-linux-musleabihf)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-arm64-darwin)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-x86-linux-gnu)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-x86-linux-musl)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-x86_64-darwin)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-x86_64-linux-gnu)
|
||||
google-protobuf (~> 4.27)
|
||||
sass-embedded (1.78.0-x86_64-linux-musl)
|
||||
google-protobuf (~> 4.27)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
ttfunk (1.8.0)
|
||||
bigdecimal (~> 3.1)
|
||||
typhoeus (1.4.1)
|
||||
ethon (>= 0.9.0)
|
||||
unicode-display_width (2.6.0)
|
||||
webrick (1.9.0)
|
||||
yell (2.2.2)
|
||||
zeitwerk (2.7.1)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux
|
||||
aarch64-linux-gnu
|
||||
aarch64-linux-musl
|
||||
arm-linux
|
||||
arm-linux-gnu
|
||||
arm-linux-gnueabihf
|
||||
arm-linux-musl
|
||||
arm-linux-musleabihf
|
||||
arm64-darwin
|
||||
x86-linux
|
||||
x86-linux-gnu
|
||||
x86-linux-musl
|
||||
x86_64-darwin
|
||||
x86_64-linux-gnu
|
||||
x86_64-linux-musl
|
||||
|
||||
DEPENDENCIES
|
||||
base64 (= 0.2.0)
|
||||
csv (= 3.3.0)
|
||||
html-proofer (= 5.0.9)
|
||||
jekyll (= 4.3.4)
|
||||
jekyll-sitemap (= 1.4.0)
|
||||
just-the-docs (= 0.10.0)
|
||||
logger (= 1.6.1)
|
||||
rake (= 13.2.1)
|
||||
sass-embedded (= 1.78.0)
|
||||
webrick (= 1.9.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.3.5p100
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.16
|
||||
@@ -7,30 +7,18 @@ statically generated using [Jekyll][jekyll].
|
||||
# Local development
|
||||
|
||||
To view the website on `localhost`, first follow the [Jekyll installation
|
||||
instructions][jekyll-docs-installation]. Once done, run the following Maven
|
||||
commands in the root of the repository to extract the (test) data from the bug
|
||||
patterns and Refaster rule collections and to transform this data into a
|
||||
Jekyll-digestible format. Unless and relevant Java code has been changed, these
|
||||
commands needs to be executed once.
|
||||
|
||||
```sh
|
||||
mvn -T1C clean install -DskipTests -Dverification.skip
|
||||
mvn exec:java@generate-docs -pl documentation-support
|
||||
```
|
||||
|
||||
Then to build the website for local development, execute in this directory:
|
||||
instructions][jekyll-docs-installation]. Once done, in this directory execute:
|
||||
|
||||
```sh
|
||||
bundle install
|
||||
bundle exec jekyll serve --livereload
|
||||
../generate-docs.sh && bundle exec jekyll serve --livereload
|
||||
```
|
||||
|
||||
The website will now be [available][localhost-port-4000] on port 4000. Source
|
||||
code modifications (including the result of rerunning `mvn
|
||||
exec:java@generate-docs -pl documentation-support`) will automatically be
|
||||
reflected. (An exception is `_config.yml`: changes to this file require a
|
||||
server restart.) Subsequent server restarts do not require running `bundle
|
||||
install`, unless `Gemfile` has been updated in the interim.
|
||||
code modifications (including the result of rerunning `../generate-docs.sh`)
|
||||
will automatically be reflected. (An exception is `_config.yml`: changes to
|
||||
this file require a server restart.) Subsequent server restarts do not require
|
||||
running `bundle install`, unless `Gemfile` has been updated in the interim.
|
||||
|
||||
If you are not familiar with Jekyll, be sure to check out its
|
||||
[documentation][jekyll-docs]. It is recommended to follow the provided
|
||||
|
||||
@@ -8,40 +8,15 @@ description: >-
|
||||
|
||||
theme: just-the-docs
|
||||
plugins:
|
||||
- jekyll-sitemap
|
||||
- jekyll-sitemap
|
||||
|
||||
# Files and directories not to be deployed through GitHub pages.
|
||||
exclude:
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- generate-version-compatibility-overview.sh
|
||||
- README.md
|
||||
- vendor
|
||||
|
||||
collections:
|
||||
bugpatterns:
|
||||
output: true
|
||||
refasterrules:
|
||||
output: true
|
||||
|
||||
defaults:
|
||||
- scope:
|
||||
type: "bugpatterns"
|
||||
values:
|
||||
layout: "bugpattern"
|
||||
- scope:
|
||||
type: "refasterrules"
|
||||
values:
|
||||
layout: "refasterrule"
|
||||
|
||||
just_the_docs:
|
||||
collections:
|
||||
bugpatterns:
|
||||
name: Bug Patterns
|
||||
nav_fold: true
|
||||
refasterrules:
|
||||
name: Refaster Rules
|
||||
nav_fold: true
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- generate-version-compatibility-overview.sh
|
||||
- README.md
|
||||
- vendor
|
||||
|
||||
# See https://jekyllrb.com/docs/permalinks/#built-in-formats.
|
||||
permalink: pretty
|
||||
@@ -50,9 +25,9 @@ permalink: pretty
|
||||
# See
|
||||
# https://just-the-docs.github.io/just-the-docs/docs/navigation-structure/#external-navigation-links.
|
||||
nav_external_links:
|
||||
- title: Error Prone Support on GitHub
|
||||
url: https://github.com/PicnicSupermarket/error-prone-support
|
||||
hide_icon: false
|
||||
- title: Error Prone Support on GitHub
|
||||
url: https://github.com/PicnicSupermarket/error-prone-support
|
||||
hide_icon: false
|
||||
|
||||
callouts:
|
||||
summary:
|
||||
@@ -65,9 +40,9 @@ callouts:
|
||||
social:
|
||||
name: Picnic
|
||||
links:
|
||||
- https://github.com/PicnicSupermarket
|
||||
- https://twitter.com/picnic
|
||||
- https://www.linkedin.com/company/picnictechnologies
|
||||
- https://github.com/PicnicSupermarket
|
||||
- https://twitter.com/picnic
|
||||
- https://www.linkedin.com/company/picnictechnologies
|
||||
twitter:
|
||||
username: picnic
|
||||
card: summary
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# An overview of Error Prone Support releases, along with compatible Error
|
||||
# Prone releases. This data was generated by `generate-version-compatibility-overview.sh`.
|
||||
releases:
|
||||
- version: 0.22.0
|
||||
compatible:
|
||||
- "2.37.0"
|
||||
- version: 0.21.0
|
||||
compatible:
|
||||
- "2.37.0"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
ERROR:
|
||||
color: red
|
||||
WARNING:
|
||||
color: yellow
|
||||
SUGGESTION:
|
||||
color: green
|
||||
@@ -1,94 +0,0 @@
|
||||
---
|
||||
# XXX: To be implemented:
|
||||
# - Support for alt names.
|
||||
# - Support for explanations.
|
||||
# - Support for "can disable".
|
||||
# - Support for custom suppression annotations.
|
||||
layout: default
|
||||
---
|
||||
|
||||
{% capture markdown_layout %}
|
||||
|
||||
# {{ page.name }}
|
||||
|
||||
{{ page.severity }}
|
||||
{: .label .label-{{ site.data.severities[page.severity].color }} }
|
||||
|
||||
{% for tag in page.tags %}
|
||||
{{ tag }}
|
||||
{: .label }
|
||||
{% endfor %}
|
||||
|
||||
<a href="https://github.com/PicnicSupermarket/error-prone-support/blob/master/{{ page.source }}" class="fs-3 btn external" target="_blank">
|
||||
View source code on GitHub
|
||||
<svg viewBox="0 0 24 24" aria-labelledby="svg-external-link-title">
|
||||
<use xlink:href="#svg-external-link"></use>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
{: .summary-title }
|
||||
> Summary
|
||||
>
|
||||
> {{ page.summary }}
|
||||
|
||||
{% comment %}
|
||||
# XXX: Here, include a more elaborate explantion, if available.
|
||||
{% endcomment %}
|
||||
|
||||
{: .note-title }
|
||||
> Suppression
|
||||
>
|
||||
> Suppress false positives by adding the suppression annotation `@SuppressWarnings("{{ page.name }}")` to
|
||||
> the enclosing element.
|
||||
>
|
||||
> Disable this pattern completely by adding `-Xep:{{ page.name }}:OFF` as compiler argument.
|
||||
> [Learn more][error-prone-flags].
|
||||
{% comment %}
|
||||
# XXX: Create an internal page on documenting the usage of compiler flags.
|
||||
{% endcomment %}
|
||||
|
||||
{% if page.replacement or page.identification %}
|
||||
|
||||
## Samples
|
||||
|
||||
{% comment %}
|
||||
# XXX: Either make this "Samples" header useful, or drop it. (In which case
|
||||
# the wrapping conjunctive guard should also go.)
|
||||
{% endcomment %}
|
||||
|
||||
{% if page.replacement %}
|
||||
|
||||
### Replacement
|
||||
|
||||
Shows the difference in example code before and after the bug pattern is
|
||||
applied.
|
||||
|
||||
{% for diff in page.replacement %}
|
||||
{% highlight diff %}
|
||||
{{ diff }}
|
||||
{% endhighlight %}
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if page.identification %}
|
||||
|
||||
### Identification
|
||||
|
||||
Shows code lines which will (not) be flagged by this bug pattern. \
|
||||
A `//BUG: Diagnostic contains:` comment is placed above any violating line.
|
||||
|
||||
{% for source in page.identification %}
|
||||
{% highlight java %}
|
||||
{{ source }}
|
||||
{% endhighlight %}
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
[error-prone-flags]: https://errorprone.info/docs/flags
|
||||
|
||||
{% endcapture %}
|
||||
{{ markdown_layout | markdownify }}
|
||||
@@ -1,78 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
{% capture markdown_layout %}
|
||||
|
||||
# {{ page.name }}
|
||||
{: .no_toc }
|
||||
|
||||
{{ page.severity }}
|
||||
{: .label .label-{{ site.data.severities[page.severity].color }} }
|
||||
|
||||
{% for tag in page.tags %}
|
||||
{{ tag }}
|
||||
{: .label }
|
||||
{% endfor %}
|
||||
|
||||
<a href="https://github.com/PicnicSupermarket/error-prone-support/blob/master/{{ page.source }}" class="fs-3 btn external" target="_blank">
|
||||
View source code on GitHub
|
||||
<svg viewBox="0 0 24 24" aria-labelledby="svg-external-link-title">
|
||||
<use xlink:href="#svg-external-link"></use>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
{: .note-title }
|
||||
> Suppression
|
||||
>
|
||||
> Disable all rules by adding `-XepOpt:Refaster:NamePattern=^(?!{{page.name}}\$).*` as
|
||||
> compiler argument.
|
||||
{% comment %}
|
||||
# XXX: Create an internal page on documenting the usage of compiler flags.
|
||||
{% endcomment %}
|
||||
|
||||
<details open markdown="block">
|
||||
<summary>
|
||||
Table of contents
|
||||
</summary>
|
||||
{: .text-delta }
|
||||
1. TOC
|
||||
{:toc}
|
||||
</details>
|
||||
|
||||
{% for rule in page.rules %}
|
||||
## {{rule.name}}
|
||||
|
||||
{{ page.severity }}
|
||||
{: .label .label-{{ site.data.severities[rule.severity].color }} }
|
||||
|
||||
{% for tag in rule.tags %}
|
||||
{{ tag }}
|
||||
{: .label }
|
||||
{% endfor %}
|
||||
|
||||
{: .note-title }
|
||||
> Suppression
|
||||
>
|
||||
> Suppress false positives by adding the suppression annotation `@SuppressWarnings("{{rule.name}}")` to
|
||||
> the enclosing element.
|
||||
>
|
||||
> Disable this rule by adding `-XepOpt:Refaster:NamePattern=^(?!{{page.name}}\${{rule.name}}).*`
|
||||
> as compiler argument.
|
||||
{% comment %}
|
||||
# XXX: Create an internal page on documenting the usage of compiler flags.
|
||||
{% endcomment %}
|
||||
|
||||
### Samples
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
Shows the difference in example code before and after the Refaster rule is
|
||||
applied.
|
||||
|
||||
{% highlight diff %}
|
||||
{{ rule.diff }}
|
||||
{% endhighlight %}
|
||||
{% endfor %}
|
||||
|
||||
{% endcapture %}
|
||||
{{ markdown_layout | markdownify }}
|
||||
@@ -2,4 +2,4 @@
|
||||
// https://github.com/just-the-docs/just-the-docs/blob/main/_sass/support/_variables.scss.
|
||||
|
||||
// Grid system.
|
||||
$nav-width: 25rem;
|
||||
$nav-width: 400px;
|
||||
|
||||
8
website/bugpatterns.md
Normal file
8
website/bugpatterns.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
layout: default
|
||||
title: Bug Patterns
|
||||
nav_order: 2
|
||||
has_children: true
|
||||
---
|
||||
|
||||
# Bug Patterns
|
||||
8
website/refasterrules.md
Normal file
8
website/refasterrules.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
layout: default
|
||||
title: Refaster Rules
|
||||
nav_order: 2
|
||||
has_children: true
|
||||
---
|
||||
|
||||
# Refaster Rules
|
||||
Reference in New Issue
Block a user