diff --git a/CLAUDE.md b/CLAUDE.md index 695521c1e..3ed0f72fc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,8 +8,10 @@ Building and testing: the README's "Building and testing locally" section. Gradl - **Collections.** Plain `java.util` types. `List.of`, `List.copyOf`, `Map.of` and `Stream.toList()` give unmodifiable collections, so new code does not need Guava's `ImmutableList` or `ImmutableMap`; use them only where an existing API already hands one over. -- **Nullability.** One annotation, `javax.annotation.Nullable` (jsr305), the one the code uses; do not add another - `Nullable`. +- **Nullability.** One annotation, JSpecify's `org.jspecify.annotations.Nullable`; do not add another `Nullable`, + nor a `NotNull` or `NonNull`: what is not `@Nullable` is non-null, and NullAway checks it. It is a type-use + annotation, so on a nested type it goes before the simple name (`Input.@Nullable Token`), and on an array before + the brackets (`String @Nullable []`). - **Local variables.** `var` wherever the initializer gives the type unchanged, in `for` loops too. Not where it would box a primitive (`for (var n : List)`), and not without an initializer that has a type of its own (a lambda, `null`). diff --git a/buildSrc/src/main/groovy/open-java-format.error-prone-conventions.gradle b/buildSrc/src/main/groovy/open-java-format.error-prone-conventions.gradle index 9bb1278d3..6e798f00e 100644 --- a/buildSrc/src/main/groovy/open-java-format.error-prone-conventions.gradle +++ b/buildSrc/src/main/groovy/open-java-format.error-prone-conventions.gradle @@ -11,13 +11,36 @@ dependencies { } nullaway { + severity = net.ltgt.gradle.errorprone.CheckSeverity.ERROR annotatedPackages.add('com.palantir') + jspecifyMode = true } tasks.withType(JavaCompile).configureEach { + // JSpecify mode reads @Nullable on types from class files, which javac 21 does only with this flag. + options.compilerArgs.add('-XDaddTypeAnnotationsToSymbol=true') options.errorprone { // Annotation processor output (Immutables) is not ours to fix. excludedPaths = '.*/build/generated/.*' + nullaway { + handleTestAssertionLibraries = true + } + error('CanonicalAnnotationSyntax') + error('CollectorMutability') + error('DirectReturn') + error('EffectivelyPrivate') + error('FormatStringConcatenation') + error('JUnitClassModifiers') + error('JUnitMethodDeclaration') + error('RedundantStringConversion') + error('RefactorSwitch') + error('SameNameButDifferent') + error('StringConcatToTextBlock') + error('UnusedVariable') + disable('IsInstanceLambdaUsage') + disable('LexicographicalAnnotationAttributeListing') + disable('LexicographicalAnnotationListing') + disable('StringJoining') } } @@ -27,27 +50,3 @@ pluginManager.withPlugin('java-gradle-plugin') { options.errorprone.disable('JavaxInjectOnAbstractMethod') } } - -// The checks vfs-s3 makes build-breaking. The commented ones stay off until the code is fixed, one check at a -// time: StaticImport 84, LexicographicalAnnotationListing 46, RedundantStringConversion 6, AlmostJavadoc 3 -// findings; the rest have none. -tasks.withType(JavaCompile).configureEach { - options.errorprone { - //error('StaticImport') - //error('UnnecessarilyFullyQualified') - //error('EmptyBlockTag') - //error('OperatorPrecedence') - //error('RedundantStringConversion') - //error('PatternMatchingInstanceof') - //error('UnnecessaryParentheses') - //error('LexicographicalAnnotationListing') - error('JUnitMethodDeclaration') - error('JUnitClassModifiers') - //error('MissingSummary') - //error('AlmostJavadoc') - //error('BadImport') - //error('JdkObsolete') - // NonStaticImport (Picnic) is the inverse of StaticImport and would give contradictory advice. - //disable('NonStaticImport') - } -} diff --git a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/BundledFormatter.java b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/BundledFormatter.java index 6caba53d8..82b66d93a 100644 --- a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/BundledFormatter.java +++ b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/BundledFormatter.java @@ -14,11 +14,12 @@ package com.palantir.javaformat.gradle; +import static java.nio.charset.StandardCharsets.UTF_8; + import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.security.DigestInputStream; @@ -86,10 +87,7 @@ static List jars(Path gradleUserHome, ClassLoader plugin) { } private static List list(ClassLoader plugin) { - return new String(resource(plugin, LIST), StandardCharsets.UTF_8) - .lines() - .map(Jar::parse) - .toList(); + return new String(resource(plugin, LIST), UTF_8).lines().map(Jar::parse).toList(); } private static boolean isComplete(Path dir, List list) { diff --git a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatDiff.java b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatDiff.java index 6ac871250..ec4fb6abd 100644 --- a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatDiff.java +++ b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatDiff.java @@ -129,7 +129,6 @@ private static Path gitTopLevelDir(Path dir) throws IOException, InterruptedExce return Paths.get(gitCommand(dir, "git", "rev-parse", "--show-toplevel")); } - @SuppressWarnings("for-rollout:DefaultCharset") private static String gitCommand(Path dir, String... args) throws IOException, InterruptedException { Process process = new ProcessBuilder().command(args).directory(dir.toFile()).start(); diff --git a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatterServiceLoader.java b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatterServiceLoader.java index 233e6b0ef..ca01b2630 100644 --- a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatterServiceLoader.java +++ b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/FormatterServiceLoader.java @@ -69,7 +69,6 @@ public static synchronized FormatterService load(Collection jars) { return LOADED.computeIfAbsent(key, _key -> loadUncached(jars)); } - @SuppressWarnings("for-rollout:NullAway") private static FormatterService loadUncached(Collection jars) { URL[] jarUris = jars.stream() .map(file -> { diff --git a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatProviderPlugin.java b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatProviderPlugin.java index 39d219a21..e8305c486 100644 --- a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatProviderPlugin.java +++ b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatProviderPlugin.java @@ -25,7 +25,6 @@ public final class PalantirJavaFormatProviderPlugin implements Plugin { static final String CONFIGURATION_NAME = "palantirJavaFormat"; - @SuppressWarnings({"for-rollout:GradleTypesAsFields", "for-rollout:NonAbstractGradleType"}) @Override public void apply(Project rootProject) { Preconditions.checkState( @@ -34,7 +33,6 @@ public void apply(Project rootProject) { rootProject.getPluginManager().apply(NativeImageFormatProviderPlugin.class); - @SuppressWarnings("for-rollout:ConfigurationAvoidanceRegistration") Configuration configuration = rootProject.getConfigurations().create(CONFIGURATION_NAME, conf -> { // Empty unless the build declares a formatter: the plugin carries its own, and needs no repository. conf.setDescription("Overrides the open-java-format implementation that comes inside the plugin"); diff --git a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/spotless/PalantirJavaFormatStep.java b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/spotless/PalantirJavaFormatStep.java index d56ecbea1..9cff43b4d 100644 --- a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/spotless/PalantirJavaFormatStep.java +++ b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/spotless/PalantirJavaFormatStep.java @@ -84,8 +84,7 @@ Signature sign() throws IOException { static final class Signature implements Serializable { private static final long serialVersionUID = 1L; - // Spotless compares the signature in its serialized form, and reads nothing out of it. - @SuppressWarnings("UnusedVariable") + /** The hash of the plugin's own jars, or empty when the build declared its own. */ private final String bundled; private final FileSignature override; @@ -100,7 +99,7 @@ static final class Signature implements Serializable { } List jars() { - return BundledFormatter.jarsUnlessOverridden(override.files(), gradleUserHome); + return bundled.isEmpty() ? List.copyOf(override.files()) : BundledFormatter.jars(gradleUserHome); } } diff --git a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/BundledFormatterTest.java b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/BundledFormatterTest.java index baa6165c2..41049d113 100644 --- a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/BundledFormatterTest.java +++ b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/BundledFormatterTest.java @@ -14,6 +14,7 @@ package com.palantir.javaformat.gradle; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -23,7 +24,6 @@ import java.io.UncheckedIOException; import java.net.URL; import java.net.URLClassLoader; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.FileTime; @@ -148,8 +148,7 @@ void a_jar_that_does_not_match_the_list_fails_and_leaves_nothing_behind(@TempDir var bundle = Files.createDirectories(plugin.resolve(BUNDLE)); Files.writeString(bundle.resolve("formatter.jar"), "not what the list says"); Files.writeString( - bundle.resolve("jars.txt"), - sha256("what the list says".getBytes(StandardCharsets.UTF_8)) + " formatter.jar\n"); + bundle.resolve("jars.txt"), sha256("what the list says".getBytes(UTF_8)) + " formatter.jar\n"); try (var loader = new URLClassLoader(new URL[] {plugin.toUri().toURL()}, null)) { assertThatThrownBy(() -> BundledFormatter.jars(gradleUserHome, loader)) @@ -161,9 +160,7 @@ void a_jar_that_does_not_match_the_list_fails_and_leaves_nothing_behind(@TempDir } private static List bundledList() { - return new String(resource(BUNDLE + "jars.txt"), StandardCharsets.UTF_8) - .lines() - .toList(); + return new String(resource(BUNDLE + "jars.txt"), UTF_8).lines().toList(); } private static List bundledNames() { diff --git a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/FormatDiffTest.java b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/FormatDiffTest.java index ba6e08ea5..21fdd5075 100644 --- a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/FormatDiffTest.java +++ b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/FormatDiffTest.java @@ -34,7 +34,6 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -58,7 +57,7 @@ void parsing_git_diff_output_works() throws IOException { List strings = FormatDiff.parseGitDiffOutput(example1) .map(FormatDiff.SingleFileDiff::toString) - .collect(Collectors.toList()); + .toList(); assertThat(strings) .containsExactly( "SingleFileDiff{path=build.gradle, lineRanges=[[24..25), [29..30)]}", @@ -104,7 +103,7 @@ private void runCommandInRepo(String... args) throws IOException, InterruptedExc process.getErrorStream().transferTo(baos); String stderr = baos.toString(UTF_8); - Preconditions.checkState(process.exitValue() == 0, "Expected return code of 0: " + stderr); + Preconditions.checkState(process.exitValue() == 0, "Expected return code of 0: %s", stderr); } private static Stream getFormatters() throws IOException { @@ -121,7 +120,7 @@ private static List getClasspath() throws IOException { .omitEmptyStrings() .splitToStream(Files.readString(CLASSPATH_FILE.toPath())) .map(Path::of) - .collect(Collectors.toList()); + .toList(); } private static Path javaBinPath() { diff --git a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageAtomicCopyTest.java b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageAtomicCopyTest.java index e5e56d523..1e3f04d3e 100644 --- a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageAtomicCopyTest.java +++ b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageAtomicCopyTest.java @@ -45,8 +45,10 @@ void the_copy_is_executable_and_the_image_is_left_as_it_was() throws IOException var copy = NativeImageAtomicCopy.copyToCache(image, gradleUserHome.toFile()); - assertThat(copy.getParent().getParent()).isEqualTo(gradleUserHome.resolve("open-java-format-caches")); - assertThat(copy.getParent().getFileName().toString()).matches("[0-9a-f]{16}"); + var cacheDir = copy.getParent(); + assertThat(cacheDir).isNotNull(); + assertThat(cacheDir.getParent()).isEqualTo(gradleUserHome.resolve("open-java-format-caches")); + assertThat(cacheDir.getFileName().toString()).matches("[0-9a-f]{16}"); assertThat(copy.getFileName()).isEqualTo(image.getFileName()); assertThat(copy).hasContent("an image"); assertThat(Files.isExecutable(copy)).isTrue(); diff --git a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageResolutionTest.java b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageResolutionTest.java index 5d6f43434..7c0f05b29 100644 --- a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageResolutionTest.java +++ b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/NativeImageResolutionTest.java @@ -14,6 +14,7 @@ package com.palantir.javaformat.gradle; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import com.fasterxml.jackson.databind.json.JsonMapper; @@ -22,7 +23,6 @@ import com.palantir.javaformat.java.Replacement; import java.io.IOException; import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermissions; @@ -154,7 +154,7 @@ private static String lddVersion() { var process = new ProcessBuilder("ldd", "--version") .redirectErrorStream(true) .start(); - var output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + var output = new String(process.getInputStream().readAllBytes(), UTF_8); process.waitFor(); return output.lines().findFirst().orElse(""); } catch (IOException e) { diff --git a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/SpotlessExcludesTest.java b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/SpotlessExcludesTest.java index 35facc407..7554a5e3e 100644 --- a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/SpotlessExcludesTest.java +++ b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/SpotlessExcludesTest.java @@ -93,11 +93,7 @@ void format_ignores_excluded_directories(String srcDir) { } @ParameterizedTest - @ValueSource( - strings = { - "foo/generated_foo/src/bar", - "src/main/java/test/generatedNamespace", - }) + @ValueSource(strings = {"foo/generated_foo/src/bar", "src/main/java/test/generatedNamespace"}) void format_checks_non_generated_files(String srcDir) { project.buildGradle(""" sourceSets { diff --git a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/testing/GradleTestProject.java b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/testing/GradleTestProject.java index d141ce5f3..32706115b 100644 --- a/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/testing/GradleTestProject.java +++ b/gradle-open-java-format/src/test/java/com/palantir/javaformat/gradle/testing/GradleTestProject.java @@ -16,11 +16,12 @@ package com.palantir.javaformat.gradle.testing; +import static java.nio.charset.StandardCharsets.UTF_8; + import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -164,7 +165,7 @@ public GradleTestProject writeFile(String relativePath, String content) { Path target = file(relativePath); try { Files.createDirectories(target.getParent()); - Files.writeString(target, content, StandardCharsets.UTF_8); + Files.writeString(target, content, UTF_8); } catch (IOException e) { throw new UncheckedIOException("Could not write " + relativePath, e); } @@ -189,7 +190,7 @@ public GradleTestProject delete(String relativePath) { public String readFile(String relativePath) { try { - return Files.readString(file(relativePath), StandardCharsets.UTF_8); + return Files.readString(file(relativePath), UTF_8); } catch (IOException e) { throw new UncheckedIOException("Could not read " + relativePath, e); } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 95dc01d2d..e41b0d3bd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ jackson-datatype-jdk8 = { module = "com.fasterxml.jackson.datatype:jackson-datat jackson-module-parameterNames = { module = "com.fasterxml.jackson.module:jackson-module-parameter-names", version = "2.22.4" } jmh-core = { module = "org.openjdk.jmh:jmh-core", version = "1.37" } jmh-generator-annprocess = { module = "org.openjdk.jmh:jmh-generator-annprocess", version = "1.37" } -jsr305 = { module = "com.google.code.findbugs:jsr305", version = "3.0.2" } +jspecify = { module = "org.jspecify:jspecify", version = "1.0.1" } junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version = "6.1.3" } junit-jupiter-migrationsupport = { module = "org.junit.jupiter:junit-jupiter-migrationsupport", version = "6.1.3" } junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version = "6.1.3" } diff --git a/open-java-format-eclipse-plugin/build.gradle b/open-java-format-eclipse-plugin/build.gradle index b3bc9cce9..8e4deca32 100644 --- a/open-java-format-eclipse-plugin/build.gradle +++ b/open-java-format-eclipse-plugin/build.gradle @@ -28,7 +28,7 @@ dependencies { compileOnly libs.eclipse.text implementation project(':open-java-format') - implementation libs.jsr305 + implementation libs.jspecify } // The dependencies embedded in the plugin jar. Named once, so the manifest can list exactly what diff --git a/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/PalantirJavaFormatter.java b/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/PalantirJavaFormatter.java index 94d6cfe9e..8e9e1b262 100644 --- a/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/PalantirJavaFormatter.java +++ b/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/PalantirJavaFormatter.java @@ -19,7 +19,6 @@ import com.palantir.javaformat.java.SnippetFormatter.SnippetKind; import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jface.text.IRegion; @@ -27,22 +26,23 @@ import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.ReplaceEdit; import org.eclipse.text.edits.TextEdit; +import org.jspecify.annotations.Nullable; /** Runs the Palantir Java formatter on the given code. */ public class PalantirJavaFormatter extends CodeFormatter { private static final int INDENTATION_SIZE = 4; - @Nullable @Override + @Nullable public TextEdit format( int kind, String source, int offset, int length, int indentationLevel, String _lineSeparator) { IRegion[] regions = new IRegion[] {new Region(offset, length)}; return formatInternal(kind, source, regions, indentationLevel); } - @Nullable @Override + @Nullable public TextEdit format(int kind, String source, IRegion[] regions, int indentationLevel, String _lineSeparator) { return formatInternal(kind, source, regions, indentationLevel); } diff --git a/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/SnippetFormatter.java b/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/SnippetFormatter.java index b1457c261..995f53955 100644 --- a/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/SnippetFormatter.java +++ b/open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/SnippetFormatter.java @@ -42,18 +42,18 @@ private final class SnippetWrapper { int offset; final StringBuilder contents = new StringBuilder(); - public SnippetWrapper append(String str) { + SnippetWrapper append(String str) { contents.append(str); return this; } - public SnippetWrapper appendSource(String source) { + SnippetWrapper appendSource(String source) { this.offset = contents.length(); contents.append(source); return this; } - public void closeBraces(int initialIndent) { + void closeBraces(int initialIndent) { for (int i = initialIndent; --i >= 0; ) { contents.append("\n").append(createIndentationString(i)).append("}"); } @@ -159,7 +159,7 @@ private SnippetWrapper snippetWrapper(SnippetKind kind, String source, int initi * dummy class is correctly formatted -- the blocks use correct indentation, * etc. */ - switch (kind) { + return switch (kind) { case COMPILATION_UNIT -> { SnippetWrapper wrapper = new SnippetWrapper(); for (int i = 1; i <= initialIndent; i++) { @@ -167,7 +167,7 @@ private SnippetWrapper snippetWrapper(SnippetKind kind, String source, int initi } wrapper.appendSource(source); wrapper.closeBraces(initialIndent); - return wrapper; + yield wrapper; } case CLASS_BODY_DECLARATIONS -> { SnippetWrapper wrapper = new SnippetWrapper(); @@ -176,7 +176,7 @@ private SnippetWrapper snippetWrapper(SnippetKind kind, String source, int initi } wrapper.appendSource(source); wrapper.closeBraces(initialIndent); - return wrapper; + yield wrapper; } case STATEMENTS -> { SnippetWrapper wrapper = new SnippetWrapper(); @@ -186,7 +186,7 @@ private SnippetWrapper snippetWrapper(SnippetKind kind, String source, int initi } wrapper.appendSource(source); wrapper.closeBraces(initialIndent); - return wrapper; + yield wrapper; } case EXPRESSION -> { SnippetWrapper wrapper = new SnippetWrapper(); @@ -198,9 +198,9 @@ private SnippetWrapper snippetWrapper(SnippetKind kind, String source, int initi wrapper.appendSource(source); wrapper.append(";"); wrapper.closeBraces(initialIndent); - return wrapper; + yield wrapper; } default -> throw new IllegalArgumentException("Unknown snippet kind: " + kind); - } + }; } } diff --git a/open-java-format-idea-plugin/build.gradle b/open-java-format-idea-plugin/build.gradle index f0e43a8ac..9796fb5ab 100644 --- a/open-java-format-idea-plugin/build.gradle +++ b/open-java-format-idea-plugin/build.gradle @@ -81,7 +81,7 @@ dependencies { testImplementation libs.assertj testImplementation libs.junit.jupiter testImplementation libs.junit.platform.launcher - implementation libs.jsr305 + implementation libs.jspecify } intellijPlatform { diff --git a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/EmbeddedNativeImage.java b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/EmbeddedNativeImage.java index cf2abc701..7fb8b33cd 100644 --- a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/EmbeddedNativeImage.java +++ b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/EmbeddedNativeImage.java @@ -43,7 +43,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * The native binary the plugin downloads for the IDE's platform, one for the whole IDE. It is kept in the IDE's system diff --git a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/FormatterProvider.java b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/FormatterProvider.java index 7e2c47f84..bca69fe16 100644 --- a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/FormatterProvider.java +++ b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/FormatterProvider.java @@ -36,7 +36,6 @@ import java.util.NoSuchElementException; import java.util.Optional; import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.Optional.ofNullable; @@ -92,7 +91,7 @@ private static Optional createFormatter(FormatterCacheKey cach } private static List getProvidedImplementationUrls(List implementationClasspath) { - return implementationClasspath.stream().map(Path::of).collect(Collectors.toList()); + return implementationClasspath.stream().map(Path::of).toList(); } private static List getBundledImplementationUrls() { @@ -127,7 +126,7 @@ private static List getImplementationUrls( private static List listDirAsUrlsUnchecked(Path dir) { try (Stream list = Files.list(dir)) { - return list.collect(Collectors.toList()); + return list.toList(); } catch (IOException e) { throw new UncheckedIOException("Couldn't list dir: " + dir, e); } diff --git a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/InitialConfigurationStartupActivity.java b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/InitialConfigurationStartupActivity.java index 941d1603f..b4c3261fb 100644 --- a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/InitialConfigurationStartupActivity.java +++ b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/InitialConfigurationStartupActivity.java @@ -18,11 +18,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; -import org.jetbrains.annotations.NotNull; public final class InitialConfigurationStartupActivity implements StartupActivity.DumbAware { @Override - public void runActivity(@NotNull Project project) { + public void runActivity(Project project) { PalantirJavaFormatSettings settings = PalantirJavaFormatSettings.getInstance(project); if (settings.isUninitialized()) { settings.setEnabled(false); diff --git a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/NativeImageNoticeStartupActivity.java b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/NativeImageNoticeStartupActivity.java index 8f5fd78a6..cf44f4495 100644 --- a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/NativeImageNoticeStartupActivity.java +++ b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/NativeImageNoticeStartupActivity.java @@ -22,8 +22,7 @@ import com.intellij.openapi.startup.StartupActivity; import com.palantir.javaformat.intellij.EmbeddedNativeImage.Status; import java.util.Optional; -import javax.annotation.Nullable; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.Nullable; /** * Tells the user, as the IDE does about outdated spelling dictionaries, when the embedded native binary is older than @@ -41,7 +40,7 @@ record Missing() implements Notice {} } @Override - public void runActivity(@NotNull Project project) { + public void runActivity(Project project) { var embedded = EmbeddedNativeImage.getInstance(); embedded.removeStale(); diff --git a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurable.java b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurable.java index 6f1f7238b..0b5dc9d97 100644 --- a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurable.java +++ b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurable.java @@ -41,7 +41,6 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.Optional; -import javax.annotation.Nullable; import javax.swing.Box; import javax.swing.JCheckBox; import javax.swing.JComponent; @@ -50,7 +49,7 @@ import javax.swing.JTextArea; import javax.swing.event.DocumentEvent; import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.Nullable; class PalantirJavaFormatConfigurable extends BaseConfigurable implements SearchableConfigurable { @@ -130,14 +129,13 @@ protected void textChanged(DocumentEvent event) { .getPanel(); } - @NotNull @Override public String getId() { return "open-java-format.settings"; } - @Nullable @Override + @Nullable public Runnable enableSearch(String option) { return null; } @@ -148,14 +146,14 @@ public String getDisplayName() { return "open-java-format Settings"; } - @Nullable @Override + @Nullable public String getHelpTopic() { return null; } - @Nullable @Override + @Nullable public JComponent createComponent() { if (uiDisposable == null) { uiDisposable = Disposer.newDisposable("open-java-format settings page"); diff --git a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingService.java b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingService.java index 58d53559f..abe5dee8a 100644 --- a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingService.java +++ b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingService.java @@ -33,9 +33,8 @@ import com.palantir.javaformat.java.FormatterException; import com.palantir.javaformat.java.FormatterService; import com.palantir.javaformat.java.Replacement; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.Nullable; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -57,7 +56,7 @@ class PalantirJavaFormatFormattingService extends AsyncDocumentFormattingService private PluginDescriptor pluginDescriptor; @Override - public void setPluginDescriptor(@NotNull PluginDescriptor pluginDescriptor) { + public void setPluginDescriptor(PluginDescriptor pluginDescriptor) { this.pluginDescriptor = pluginDescriptor; } @@ -66,7 +65,8 @@ Optional getPluginDescriptor() { } @Override - protected FormattingTask createFormattingTask(@NotNull AsyncFormattingRequest request) { + @Nullable + protected FormattingTask createFormattingTask(AsyncFormattingRequest request) { Project project = request.getContext().getProject(); // The marketplace verifier reports this class as experimental, and newer IDEs also deprecate it. It stays: // its replacement, com.intellij.ide.trustedProjects.TrustedProjects, is @ApiStatus.Internal — a worse thing @@ -84,22 +84,22 @@ protected FormattingTask createFormattingTask(@NotNull AsyncFormattingRequest re } @Override - protected @NotNull String getNotificationGroupId() { + protected String getNotificationGroupId() { return Notifications.PARSING_ERROR_NOTIFICATION_GROUP; } @Override - protected @NotNull @NlsSafe String getName() { + protected @NlsSafe String getName() { return "open-java-format"; } @Override - public @NotNull Set getFeatures() { + public Set getFeatures() { return Set.of(Feature.FORMAT_FRAGMENTS); } @Override - public boolean canFormat(@NotNull PsiFile file) { + public boolean canFormat(PsiFile file) { return JavaFileType.INSTANCE.equals(file.getFileType()) && PalantirJavaFormatSettings.getInstance(file.getProject()).isEnabled(); } @@ -108,8 +108,7 @@ private static final class PalantirJavaFormatFormattingTask implements Formattin private final AsyncFormattingRequest request; private final Optional formatterService; - public PalantirJavaFormatFormattingTask( - AsyncFormattingRequest request, Optional formatterService) { + PalantirJavaFormatFormattingTask(AsyncFormattingRequest request, Optional formatterService) { this.request = request; this.formatterService = formatterService; } @@ -174,7 +173,7 @@ public void run() { } } - public static String applyReplacements(String input, Collection replacementsCollection) { + static String applyReplacements(String input, Collection replacementsCollection) { List replacements = new ArrayList<>(replacementsCollection); replacements.sort(comparing((Replacement r) -> r.getReplaceRange().lowerEndpoint()) .reversed()); diff --git a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettings.java b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettings.java index 48420169d..1306237d6 100644 --- a/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettings.java +++ b/open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettings.java @@ -23,8 +23,8 @@ import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.project.Project; import com.palantir.javaformat.java.FormatterService; +import org.jspecify.annotations.Nullable; -import javax.annotation.Nullable; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; @@ -32,33 +32,26 @@ import java.util.List; import java.util.Optional; import java.util.jar.JarFile; -import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.Optional.ofNullable; -@SuppressWarnings("for-rollout:SameNameButDifferent") -@State( - name = "PalantirJavaFormatSettings", - storages = {@Storage("open-java-format.xml")}) -public class PalantirJavaFormatSettings implements PersistentStateComponent { +@State(name = "PalantirJavaFormatSettings", storages = @Storage("open-java-format.xml")) +public class PalantirJavaFormatSettings implements PersistentStateComponent { - @SuppressWarnings("for-rollout:SameNameButDifferent") - private State state = new State(); + private StoredSettings state = new StoredSettings(); static PalantirJavaFormatSettings getInstance(Project project) { return project.getService(PalantirJavaFormatSettings.class); } - @SuppressWarnings("for-rollout:SameNameButDifferent") - @Nullable @Override - public State getState() { + public StoredSettings getState() { return state; } @Override - public void loadState(@SuppressWarnings("for-rollout:SameNameButDifferent") State state) { + public void loadState(StoredSettings state) { this.state = state; } @@ -152,7 +145,7 @@ enum EnabledState { DISABLED } - static class State { + static class StoredSettings { private EnabledState enabled = EnabledState.UNKNOWN; private Optional> implementationClassPath = Optional.empty(); @@ -164,13 +157,13 @@ static class State { public void setImplementationClassPath(@Nullable List value) { implementationClassPath = Optional.ofNullable(value) - .map(strings -> strings.stream().map(URI::create).collect(Collectors.toList())); + .map(strings -> strings.stream().map(URI::create).toList()); } - @SuppressWarnings("for-rollout:NullAway") + @Nullable public List getImplementationClassPath() { return implementationClassPath - .map(paths -> paths.stream().map(URI::toString).collect(Collectors.toList())) + .map(paths -> paths.stream().map(URI::toString).toList()) .orElse(null); } @@ -185,7 +178,7 @@ public void setEnabled(@Nullable String enabledStr) { } } - @SuppressWarnings("for-rollout:NullAway") + @Nullable public String getEnabled() { return switch (enabled) { case ENABLED -> "true"; diff --git a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/FormatterProviderTest.java b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/FormatterProviderTest.java index 0bfa7dbd6..1dc3d138b 100644 --- a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/FormatterProviderTest.java +++ b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/FormatterProviderTest.java @@ -22,7 +22,7 @@ import com.intellij.testFramework.fixtures.JavaTestFixtureFactory; import com.palantir.javaformat.bootstrap.BootstrappingFormatterService; import com.palantir.javaformat.bootstrap.NativeImageFormatterService; -import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.State; +import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.StoredSettings; import java.nio.file.Path; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; @@ -45,7 +45,7 @@ void setUp() throws Exception { fixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); fixture.setUp(); settings = PalantirJavaFormatSettings.getInstance(fixture.getProject()); - settings.loadState(new State()); + settings.loadState(new StoredSettings()); } @AfterEach diff --git a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurableTest.java b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurableTest.java index 177201dc5..c74d18bf6 100644 --- a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurableTest.java +++ b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurableTest.java @@ -34,7 +34,7 @@ import com.palantir.javaformat.intellij.EmbeddedNativeImage.Installed; import com.palantir.javaformat.intellij.EmbeddedNativeImage.Status; import com.palantir.javaformat.intellij.PalantirJavaFormatConfigurable.StatusLine; -import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.State; +import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.StoredSettings; import java.awt.Component; import java.awt.Container; import java.io.IOException; @@ -74,7 +74,7 @@ void setUp() throws Exception { fixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); fixture.setUp(); settings = PalantirJavaFormatSettings.getInstance(fixture.getProject()); - settings.loadState(new State()); + settings.loadState(new StoredSettings()); settings.setEnabled(true); // Nothing downloaded, and nowhere to download from. var embedded = new EmbeddedNativeImage( @@ -104,7 +104,7 @@ void hasNoChoiceOfCodeStyle() { @Test void readsAndWritesTheEnabledSetting() throws Throwable { - State disabled = new State(); + var disabled = new StoredSettings(); disabled.setEnabled("false"); settings.loadState(disabled); @@ -176,7 +176,7 @@ void showsTheActiveFormatterAsThePageStands() throws Throwable { useNativeImage.setSelected(true); assertThat(activeFormatter().getText()) - .isEqualTo("Need to download version " + pluginVersion + " from Maven Central"); + .isEqualTo("Need to download version %s from Maven Central", pluginVersion); path.setText("/opt/open-java-format"); assertThat(activeFormatter().getText()).isEqualTo("/opt/open-java-format"); @@ -268,7 +268,7 @@ void refusesAPathThatIsNotAnExecutableFile() throws Throwable { assertThatThrownBy(configurable::apply) .isInstanceOf(ConfigurationException.class) - .hasMessage(missing + " is not an executable file"); + .hasMessage("%s is not an executable file", missing); }); } diff --git a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingServiceTest.java b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingServiceTest.java index 64050f4d5..4c4ebf3d0 100644 --- a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingServiceTest.java +++ b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingServiceTest.java @@ -35,8 +35,7 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture; import com.intellij.testFramework.fixtures.JavaTestFixtureFactory; import com.intellij.testFramework.fixtures.TestFixtureBuilder; -import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.State; -import org.jetbrains.annotations.NotNull; +import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.StoredSettings; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -49,6 +48,7 @@ import java.nio.file.Paths; import java.util.List; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; final class PalantirJavaFormatFormattingServiceTest { @@ -70,7 +70,7 @@ void setUp() throws Exception { settings = PalantirJavaFormatSettings.getInstance(fixture.getProject()); - State resetState = new State(); + var resetState = new StoredSettings(); resetState.setEnabled("true"); settings.loadState(resetState); } @@ -102,7 +102,6 @@ protected Project getProject() { return fixture.getProject(); } - @NotNull protected LightProjectDescriptor getProjectDescriptor() { return new DefaultLightProjectDescriptor() { @Override @@ -127,12 +126,11 @@ private PsiFile createPsiFile(String path, String... contents) throws IOExceptio } private static final class DelegatingFormatter extends PalantirJavaFormatFormattingService { - @SuppressWarnings("DataFlowIssue") - public DelegatingFormatter() { - this.setPluginDescriptor(FormattingService.EP_NAME - .findExtension(PalantirJavaFormatFormattingService.class) - .getPluginDescriptor() - .orElseThrow()); + DelegatingFormatter() { + this.setPluginDescriptor( + requireNonNull(FormattingService.EP_NAME.findExtension(PalantirJavaFormatFormattingService.class)) + .getPluginDescriptor() + .orElseThrow()); } private boolean invoked = false; @@ -143,7 +141,7 @@ private boolean wasInvoked() { @Override protected FormattingTask createFormattingTask(AsyncFormattingRequest request) { - FormattingTask delegateTask = super.createFormattingTask(request); + FormattingTask delegateTask = requireNonNull(super.createFormattingTask(request)); return new FormattingTask() { @Override public boolean cancel() { diff --git a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettingsTest.java b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettingsTest.java index d3d574b4b..8a7eae315 100644 --- a/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettingsTest.java +++ b/open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettingsTest.java @@ -18,8 +18,10 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.util.xmlb.XmlSerializer; -import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.State; +import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.StoredSettings; +import java.net.URI; import java.nio.file.Path; +import java.util.List; import java.util.Optional; import org.intellij.lang.annotations.Language; import org.junit.jupiter.api.Test; @@ -42,7 +44,7 @@ void loadsAFileThatStillHasTheCodeStyle() throws Exception { @Test void doesNotWriteACodeStyle() { - var xml = JDOMUtil.write(XmlSerializer.serialize(new State())); + var xml = JDOMUtil.write(XmlSerializer.serialize(new StoredSettings())); assertThat(xml).doesNotContain("style"); } @@ -60,6 +62,18 @@ void keepsTheNativeBinarySettings() throws Exception { assertThat(reloaded.getNativeImagePath()).hasValue(Path.of("/opt/open-java-format")); } + @Test + void keepsTheImplementationClassPath() throws Exception { + var state = new StoredSettings(); + state.setImplementationClassPath(List.of("file:/opt/formatter.jar", "file:/opt/guava.jar")); + + var reloaded = new PalantirJavaFormatSettings(); + reloaded.loadState(deserialize(JDOMUtil.write(XmlSerializer.serialize(state)))); + + assertThat(reloaded.getImplementationClassPath()) + .hasValue(List.of(URI.create("file:/opt/formatter.jar"), URI.create("file:/opt/guava.jar"))); + } + @Test void ignoresTheNativeImageTheGradlePluginUsedToWrite() throws Exception { // Gradle plugins up to 21.0.1 wrote this for openjavaformat.native.formatter=true. The native binary is a @@ -78,7 +92,7 @@ void ignoresTheNativeImageTheGradlePluginUsedToWrite() throws Exception { @Test void takesABlankPathForNone() { - var state = new State(); + var state = new StoredSettings(); state.nativeImagePath = " "; var settings = new PalantirJavaFormatSettings(); settings.loadState(state); @@ -86,7 +100,7 @@ void takesABlankPathForNone() { assertThat(settings.getNativeImagePath()).isEmpty(); } - private static State deserialize(@Language("xml") String xml) throws Exception { - return XmlSerializer.deserialize(JDOMUtil.load(xml), State.class); + private static StoredSettings deserialize(@Language("xml") String xml) throws Exception { + return XmlSerializer.deserialize(JDOMUtil.load(xml), StoredSettings.class); } } diff --git a/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/BootstrappingFormatterService.java b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/BootstrappingFormatterService.java index e46312c6b..acecabc06 100644 --- a/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/BootstrappingFormatterService.java +++ b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/BootstrappingFormatterService.java @@ -84,11 +84,10 @@ private ImmutableList getFormatReplacementsInternal(String input, C jvmArgsForVersion(jdkMajorVersion), implementationClassPath, /* outputReplacements= */ true, - ranges.stream().map(RangeUtils::toStringRange).collect(Collectors.toList())); + ranges.stream().map(RangeUtils::toStringRange).toList()); - @SuppressWarnings("for-rollout:NullAway") Optional output = - FormatterCommandRunner.runWithStdin(command.toArgs(), input, Optional.of(jdkPath.getParent())); + FormatterCommandRunner.runWithStdin(command.toArgs(), input, Optional.ofNullable(jdkPath.getParent())); if (output.isEmpty() || output.get().isEmpty()) { return ImmutableList.of(); } diff --git a/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/FormatterCommandRunner.java b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/FormatterCommandRunner.java index e8b63d221..028fa3475 100644 --- a/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/FormatterCommandRunner.java +++ b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/FormatterCommandRunner.java @@ -16,10 +16,11 @@ package com.palantir.javaformat.bootstrap; +import static java.nio.charset.StandardCharsets.UTF_8; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -37,7 +38,7 @@ static Optional runWithStdin(List command, String input, Optiona .start(); try (OutputStream outputStream = process.getOutputStream()) { - outputStream.write(input.getBytes(StandardCharsets.UTF_8)); + outputStream.write(input.getBytes(UTF_8)); } // Make sure to drain stdout before waiting for the process to exit as this can result in a deadlock otherwise. @@ -72,7 +73,7 @@ private static boolean isSyntaxError(String stderr) { private static String readToString(InputStream input) throws IOException { try (input) { - return new String(input.readAllBytes(), StandardCharsets.UTF_8); + return new String(input.readAllBytes(), UTF_8); } } diff --git a/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/NativeImageFormatterService.java b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/NativeImageFormatterService.java index bfaa5607b..cfe4e102d 100644 --- a/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/NativeImageFormatterService.java +++ b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/NativeImageFormatterService.java @@ -31,7 +31,6 @@ import java.util.Collection; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; public class NativeImageFormatterService implements FormatterService { private static final ObjectMapper MAPPER = @@ -49,7 +48,7 @@ public ImmutableList getFormatReplacements(String input, Collection FormatterNativeImageArgs command = new FormatterNativeImageArgs( nativeImagePath, /* outputReplacements= */ true, - ranges.stream().map(RangeUtils::toStringRange).collect(Collectors.toList())); + ranges.stream().map(RangeUtils::toStringRange).toList()); output = FormatterCommandRunner.runWithStdin( command.toArgs(), input, Optional.ofNullable(nativeImagePath.getParent())); diff --git a/open-java-format-jdk-bootstrap/src/test/java/com/palantir/javaformat/bootstrap/FormatterServicesTest.java b/open-java-format-jdk-bootstrap/src/test/java/com/palantir/javaformat/bootstrap/FormatterServicesTest.java index fe7944af3..7626cf4ee 100644 --- a/open-java-format-jdk-bootstrap/src/test/java/com/palantir/javaformat/bootstrap/FormatterServicesTest.java +++ b/open-java-format-jdk-bootstrap/src/test/java/com/palantir/javaformat/bootstrap/FormatterServicesTest.java @@ -32,7 +32,6 @@ import java.nio.file.Path; import java.util.List; import java.util.Locale; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -102,8 +101,7 @@ private static Stream getFormatters() { return Stream.of( new BootstrappingFormatterService( javaBinPath(), Runtime.version().feature(), getClasspath()), - new NativeImageFormatterService( - Path.of(System.getenv("NATIVE_IMAGE_CLASSPATH").toString()))); + new NativeImageFormatterService(Path.of(System.getenv("NATIVE_IMAGE_CLASSPATH")))); } private String getTestResourceContent(String resourceName) { @@ -122,7 +120,7 @@ private static List getClasspath() { .omitEmptyStrings() .splitToStream(classpath) .map(Path::of) - .collect(Collectors.toList()); + .toList(); } private static Path javaBinPath() { diff --git a/open-java-format/build.gradle b/open-java-format/build.gradle index b16e08fac..016e7fa55 100644 --- a/open-java-format/build.gradle +++ b/open-java-format/build.gradle @@ -26,7 +26,7 @@ dependencies { compileOnly variantOf(libs.immutables.value) { classifier('annotations') } annotationProcessor libs.immutables.value - implementation libs.jsr305 + implementation libs.jspecify } // Was baseline's `moduleJvmArgs`, dropped because it looks its extension up at execution diff --git a/open-java-format/src/main/java/com/palantir/javaformat/Newlines.java b/open-java-format/src/main/java/com/palantir/javaformat/Newlines.java index 73b03ce73..4f9eed64b 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/Newlines.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/Newlines.java @@ -19,6 +19,7 @@ import com.google.common.collect.Iterators; import java.util.Iterator; import java.util.NoSuchElementException; +import org.jspecify.annotations.Nullable; /** Platform-independent newline handling. */ public class Newlines { @@ -53,7 +54,7 @@ public static int hasNewlineAt(String input, int idx) { } /** Returns the terminating line break in the input, or {@code null} if the input does not end in a break. */ - @SuppressWarnings("for-rollout:NullAway") + @Nullable public static String getLineEnding(String input) { for (String b : BREAKS) { if (input.endsWith(b)) { @@ -155,19 +156,17 @@ public void remove() { private static final class LineIterator implements Iterator { int idx; - String curr; private final String input; private final Iterator indices; - @SuppressWarnings("for-rollout:NullAway") private LineIterator(String input) { this.input = input; this.indices = lineOffsetIterator(input); idx = indices.next(); // read leading 0 } - private void advance() { + private String advance() { int last = idx; if (indices.hasNext()) { idx = indices.next(); @@ -177,7 +176,7 @@ private void advance() { } else { throw new NoSuchElementException(); } - curr = input.substring(last, idx); + return input.substring(last, idx); } @Override @@ -187,8 +186,7 @@ public boolean hasNext() { @Override public String next() { - advance(); - return curr; + return advance(); } @Override diff --git a/open-java-format/src/main/java/com/palantir/javaformat/OpsBuilder.java b/open-java-format/src/main/java/com/palantir/javaformat/OpsBuilder.java index 7ff81101e..25234ff67 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/OpsBuilder.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/OpsBuilder.java @@ -14,6 +14,8 @@ package com.palantir.javaformat; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; @@ -49,16 +51,14 @@ public final class OpsBuilder { /** Return the actual size of the AST node at position, including comments. */ public int actualSize(int position, int length) { - Input.Token startToken = input.getPositionTokenMap().get(position); - @SuppressWarnings("for-rollout:NullAway") + Input.Token startToken = checkNotNull(input.getPositionTokenMap().get(position)); int start = startToken.getTok().getPosition(); for (Input.Tok tok : startToken.getToksBefore()) { if (tok.isComment()) { start = Math.min(start, tok.getPosition()); } } - Input.Token endToken = input.getPositionTokenMap().get(position + length - 1); - @SuppressWarnings("for-rollout:NullAway") + Input.Token endToken = checkNotNull(input.getPositionTokenMap().get(position + length - 1)); int end = endToken.getTok().getPosition() + endToken.getTok().length(); for (Input.Tok tok : endToken.getToksAfter()) { if (tok.isComment()) { @@ -70,8 +70,7 @@ public int actualSize(int position, int length) { /** Return the start column of the token at {@code position}, including leading comments. */ public Integer actualStartColumn(int position) { - Input.Token startToken = input.getPositionTokenMap().get(position); - @SuppressWarnings("for-rollout:NullAway") + Input.Token startToken = checkNotNull(input.getPositionTokenMap().get(position)); int start = startToken.getTok().getPosition(); int line0 = input.getLineNumber(start); for (Input.Tok tok : startToken.getToksBefore()) { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/doc/Comment.java b/open-java-format/src/main/java/com/palantir/javaformat/doc/Comment.java index 37742b128..8297503a4 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/doc/Comment.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/doc/Comment.java @@ -157,7 +157,6 @@ protected Range computeRange() { public State computeBreaks( CommentsHelper commentsHelper, int maxWidth, State state, Obs.ExplorationNode observationNode) { String text = commentsHelper.rewrite(tok, maxWidth, state.column()); - @SuppressWarnings("for-rollout:NullAway") int lastLineStart = Iterators.getLast(Newlines.lineOffsetIterator(text)); int lastLineLength = text.length() - lastLineStart; // rewrite() indents every line after the first to state.column(), so after a comment that spans lines the diff --git a/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java b/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java index 2824bdb9d..176616b06 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java @@ -48,7 +48,7 @@ import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** A {@code Level} inside a {@link Doc}. */ public final class Level extends Doc { @@ -402,7 +402,6 @@ private Optional tryInlinePrefixOntoCurrentLine( commentsHelper, maxWidth, newState, memoizedSplitsBreaks.get(), explorationNode)); } - @SuppressWarnings("for-rollout:NullAway") private Optional tryBreakLastLevel( CommentsHelper commentsHelper, int maxWidth, @@ -429,7 +428,6 @@ private Optional tryBreakLastLevel( /** A call of {@link #tryBreakLastLevel}, by everything besides this level that decides its outcome. */ private record LastLevelAttempt(int maxWidth, boolean isSimpleInliningSoFar, State.LayoutInputs inputs) {} - @SuppressWarnings("for-rollout:NullAway") private Optional tryInlineSuffix( CommentsHelper commentsHelper, int maxWidth, @@ -549,7 +547,6 @@ private static Optional tryBreakInnerLevel_acceptInlineChain( .markAccepted()); } - @SuppressWarnings("for-rollout:NullAway") private static Optional tryBreakInnerLevel_checkInner( CommentsHelper commentsHelper, int maxWidth, diff --git a/open-java-format/src/main/java/com/palantir/javaformat/doc/LevelDelimitedFlatValueDocVisitor.java b/open-java-format/src/main/java/com/palantir/javaformat/doc/LevelDelimitedFlatValueDocVisitor.java index 5ef16ab9b..8de02dac4 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/doc/LevelDelimitedFlatValueDocVisitor.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/doc/LevelDelimitedFlatValueDocVisitor.java @@ -53,7 +53,6 @@ public String visitBreak(Break doc) { return sb.toString(); } - @SuppressWarnings("for-rollout:NullAway") @Override public String visitLevel(Level level) { if (level.getFlat().isEmpty()) { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/doc/Obs.java b/open-java-format/src/main/java/com/palantir/javaformat/doc/Obs.java index 457351e08..1f215473e 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/doc/Obs.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/doc/Obs.java @@ -16,10 +16,11 @@ package com.palantir.javaformat.doc; +import com.google.errorprone.annotations.CheckReturnValue; import java.util.Optional; import java.util.OptionalInt; import java.util.function.Function; -import javax.annotation.CheckReturnValue; +import org.jspecify.annotations.Nullable; /** * These classes exist purely for observing the operation of {@link Doc#computeBreaks}, including all the alternative @@ -64,7 +65,6 @@ FinishExplorationNode startExplorationNode( String getOutput(); } - @SuppressWarnings("for-rollout:NullAway") public static ExplorationNode createRoot(Sink sink) { return new ExplorationNodeImpl(null, "(initial node)", sink, 0, Optional.empty()); } @@ -95,7 +95,7 @@ private static class LevelNodeImpl extends HasUniqueId implements LevelNode { private final FinishLevelNode finisher; private final int startColumn; - public LevelNodeImpl(Level level, State incomingState, int parentExplorationId, Sink sink) { + LevelNodeImpl(Level level, State incomingState, int parentExplorationId, Sink sink) { this.level = level; this.sink = sink; this.finisher = sink.writeLevelNode(id(), parentExplorationId, incomingState, level); @@ -170,8 +170,8 @@ private static class ExplorationNodeImpl extends HasUniqueId implements Explorat private final FinishExplorationNode finishExplorationNode; private final Optional parentLevel; - public ExplorationNodeImpl( - LevelNodeImpl parent, + ExplorationNodeImpl( + @Nullable LevelNodeImpl parent, String humanDescription, Sink sink, int startColumn, diff --git a/open-java-format/src/main/java/com/palantir/javaformat/doc/State.java b/open-java-format/src/main/java/com/palantir/javaformat/doc/State.java index d5b53f13b..02b523d78 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/doc/State.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/doc/State.java @@ -26,8 +26,6 @@ import org.immutables.value.Value; /** State for writing. */ -// Automatically suppressed to unblock enforcement in new code -@SuppressWarnings("ImmutablesStyle") @Value.Immutable @Value.Style(overshadowImplementation = true) @JsonSerialize(as = ImmutableState.class) diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptionsParser.java b/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptionsParser.java index 7a1dd0a36..658833405 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptionsParser.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptionsParser.java @@ -30,7 +30,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** A parser for {@link CommandLineOptions}. */ final class CommandLineOptionsParser { @@ -55,7 +55,6 @@ final class CommandLineOptionsParser { ); /** Parses {@link CommandLineOptions}. */ - @SuppressWarnings("for-rollout:NullAway") static CommandLineOptions parse(Iterable options) { CommandLineOptions.Builder optionsBuilder = CommandLineOptions.builder(); List expandedOptions = new ArrayList<>(); @@ -108,7 +107,7 @@ static CommandLineOptions parse(Iterable options) { return optionsBuilder.build(); } - private static Integer parseInteger(Iterator it, String flag, String value) { + private static Integer parseInteger(Iterator it, String flag, @Nullable String value) { try { return Integer.valueOf(getValue(flag, it, value)); } catch (NumberFormatException e) { @@ -142,18 +141,18 @@ private static void parseCharacterRanges(ImmutableRangeSet.Builder resu */ private static Range parseCharacterRange(String range) { List args = COLON_SPLITTER.splitToList(range); - switch (args.size()) { + return switch (args.size()) { case 1 -> { int lowerUpperRange = Integer.parseInt(args.get(0)); - return Range.closed(lowerUpperRange, lowerUpperRange); + yield Range.closed(lowerUpperRange, lowerUpperRange); } case 2 -> { int lower = Integer.parseInt(args.get(0)); int higher = Integer.parseInt(args.get(1)); - return Range.closed(lower, higher); + yield Range.closed(lower, higher); } default -> throw new IllegalArgumentException(range); - } + }; } /** @@ -173,18 +172,18 @@ private static void parseRangeSet(RangeSet result, String ranges) { */ private static Range parseRange(String arg) { List args = COLON_SPLITTER.splitToList(arg); - switch (args.size()) { + return switch (args.size()) { case 1 -> { int line = Integer.parseInt(args.get(0)) - 1; - return Range.closedOpen(line, line + 1); + yield Range.closedOpen(line, line + 1); } case 2 -> { int line0 = Integer.parseInt(args.get(0)) - 1; int line1 = Integer.parseInt(args.get(1)) - 1; - return Range.closedOpen(line0, line1 + 1); + yield Range.closedOpen(line0, line1 + 1); } default -> throw new IllegalArgumentException(arg); - } + }; } /** diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/DebugRenderer.java b/open-java-format/src/main/java/com/palantir/javaformat/java/DebugRenderer.java index 01cebd7f3..11656fb8c 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/DebugRenderer.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/DebugRenderer.java @@ -16,6 +16,8 @@ package com.palantir.javaformat.java; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -37,7 +39,6 @@ import com.palantir.javaformat.doc.Token; import java.io.IOException; import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -77,7 +78,7 @@ static void render( formatterDecisionsJson); try { - Files.write(getOutputFile(), javascript.getBytes(StandardCharsets.UTF_8)); + Files.write(getOutputFile(), javascript.getBytes(UTF_8)); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/DimensionHelpers.java b/open-java-format/src/main/java/com/palantir/javaformat/java/DimensionHelpers.java index 965be309f..3e01962d6 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/DimensionHelpers.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/DimensionHelpers.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.Deque; import java.util.List; +import org.jspecify.annotations.Nullable; /** * Utilities for working with array dimensions. @@ -38,10 +39,12 @@ class DimensionHelpers { /** The array dimension specifiers (including any type annotations) associated with a type. */ static class TypeWithDims { + @Nullable final Tree node; + final ImmutableList> dims; - public TypeWithDims(Tree node, ImmutableList> dims) { + public TypeWithDims(@Nullable Tree node, ImmutableList> dims) { this.node = node; this.dims = dims; } @@ -102,22 +105,18 @@ private static Iterable> reorderBySourcePosition(DequeGiven {@code int @A @B [][] @C []}, adds {@code [[@A, @B], [@C]]} to dims and returns {@code int}. */ private static Tree extractDims(Deque> dims, Tree node) { - switch (node.getKind()) { - case ARRAY_TYPE -> { - return extractDims(dims, ((ArrayTypeTree) node).getType()); - } + return switch (node.getKind()) { + case ARRAY_TYPE -> extractDims(dims, ((ArrayTypeTree) node).getType()); case ANNOTATED_TYPE -> { AnnotatedTypeTree annotatedTypeTree = (AnnotatedTypeTree) node; if (!(annotatedTypeTree.getUnderlyingType() instanceof ArrayTypeTree)) { - return node; + yield node; } node = extractDims(dims, annotatedTypeTree.getUnderlyingType()); dims.addFirst(ImmutableList.copyOf(annotatedTypeTree.getAnnotations())); - return node; + yield node; } - default -> { - return node; - } - } + default -> node; + }; } } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java b/open-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java index ebc10209d..8e05831d7 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java @@ -243,7 +243,6 @@ static int getRuntimeVersion() { return Runtime.version().feature(); } - @SuppressWarnings("for-rollout:ThrowError") private static JavaInputAstVisitor createVisitor( final String className, final OpsBuilder builder, final JavaFormatterOptions options) { try { @@ -310,8 +309,7 @@ public String formatSourceAndFixImports(String input) throws FormatterException input = ImportOrderer.reorderImports(input, options.style()); input = RemoveUnusedImports.removeUnusedImports(input); String formatted = formatSource(input); - formatted = StringWrapper.wrap(options.maxLineLength(), formatted, this); - return formatted; + return StringWrapper.wrap(options.maxLineLength(), formatted, this); } /** diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/ImportOrderer.java b/open-java-format/src/main/java/com/palantir/javaformat/java/ImportOrderer.java index 3478db685..7d58138b3 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/ImportOrderer.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/ImportOrderer.java @@ -93,7 +93,6 @@ private String reorderImports() throws FormatterException { tail.add(CharMatcher.whitespace().trimLeadingFrom(tokString(afterLastImport, toks.size()))); if (!toks.isEmpty()) { Tok lastTok = getLast(toks); - @SuppressWarnings("for-rollout:NullAway") int tailStart = lastTok.getPosition() + lastTok.length(); tail.add(text.substring(tailStart)); } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadataBuilder.java b/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadataBuilder.java index 7bc9846d4..6ded45a09 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadataBuilder.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadataBuilder.java @@ -24,7 +24,7 @@ import com.palantir.javaformat.OpsBuilder.BlankLineWanted; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; public final class InputMetadataBuilder { private final Map blankLines = new HashMap<>(); // Info on blank lines. diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaCommentsHelper.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaCommentsHelper.java index 80193bbbe..1a2de78d9 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaCommentsHelper.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaCommentsHelper.java @@ -25,7 +25,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** {@code JavaCommentsHelper} extends {@link CommentsHelper} to rewrite Java comments. */ public final class JavaCommentsHelper implements CommentsHelper { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInput.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInput.java index de951b0ca..e46b20818 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInput.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInput.java @@ -57,9 +57,9 @@ import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; import javax.tools.SimpleJavaFileObject; +import org.jspecify.annotations.Nullable; /** {@code JavaInput} extends {@link Input} to represent a Java input document. */ -@SuppressWarnings("for-rollout:ThrowError") public final class JavaInput extends Input { /** * A {@code JavaInput} is a sequence of {@link Tok}s that cover the Java input. A {@link Tok} is either a token (if @@ -80,6 +80,8 @@ static final class Tok implements Input.Tok { private final int position; private final int columnI; private final boolean isToken; + + @Nullable private final TokenKind kind; /** @@ -93,7 +95,14 @@ static final class Tok implements Input.Tok { * @param isToken whether the {@code Tok} is a token * @param kind the token kind */ - Tok(int index, String originalText, String text, int position, int columnI, boolean isToken, TokenKind kind) { + Tok( + int index, + String originalText, + String text, + int position, + int columnI, + boolean isToken, + @Nullable TokenKind kind) { this.index = index; this.originalText = originalText; this.text = text; @@ -175,6 +184,7 @@ public String toString() { .toString(); } + @Nullable public TokenKind kind() { return kind; } @@ -258,7 +268,6 @@ public String toString() { * output. */ - @SuppressWarnings("for-rollout:AlmostJavadoc") private final ImmutableMap positionToColumnMap; // Map Tok position to column. private final ImmutableList tokens; // The Tokens for this input. @@ -273,7 +282,6 @@ public String toString() { * @param text the input text * @throws FormatterException if the input cannot be parsed */ - @SuppressWarnings("for-rollout:NullAway") public JavaInput(String text) throws FormatterException { this.text = checkNotNull(text); setLines(ImmutableList.copyOf(Newlines.lineIterator(text))); @@ -338,7 +346,6 @@ public String getLineSeparator() { } /** Lex the input and build the list of toks. */ - @SuppressWarnings("for-rollout:NullAway") private ImmutableList buildToks(String text) throws FormatterException { ImmutableList toks = buildToks(text, ImmutableSet.of()); kN = getLast(toks).getIndex(); @@ -353,7 +360,6 @@ private ImmutableList buildToks(String text) throws FormatterException { * @param stopTokens a set of tokens which should cause lexing to stop. If one of these is found, the returned list * will include tokens up to but not including that token. */ - @SuppressWarnings("for-rollout:NullAway") static ImmutableList buildToks(String text, ImmutableSet stopTokens) throws FormatterException { stopTokens = ImmutableSet.builder() .addAll(stopTokens) @@ -388,7 +394,7 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept // Get string, possibly with Unicode escapes. String originalTokText = text.substring(charI0, t.endPos()); String tokText = t.kind() == TokenKind.STRINGLITERAL - ? t.stringVal() // Unicode escapes removed. + ? checkNotNull(t.stringVal()) // Unicode escapes removed. : originalTokText; char tokText0 = tokText.charAt(0); // The token's first character. final boolean isToken; // Is this tok a token? @@ -419,7 +425,7 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept } else if (tokText.startsWith("//") || tokText.startsWith("/*")) { // For compatibility with an earlier lexer, the newline after a // comment is its own tok. if (tokText.startsWith("//") && (originalTokText.endsWith("\n") || originalTokText.endsWith("\r"))) { - extraNewline = Newlines.getLineEnding(originalTokText); + extraNewline = checkNotNull(Newlines.getLineEnding(originalTokText)); tokText = tokText.substring(0, tokText.length() - extraNewline.length()); originalTokText = originalTokText.substring(0, originalTokText.length() - extraNewline.length()); } @@ -481,7 +487,6 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept * @param handler the diagnostic handler * @return a collection of diagnostics */ - @SuppressWarnings({"unchecked", "for-rollout:ThrowError"}) private static Collection getDiagnostics(DeferredDiagnosticHandler handler) { try { return (Collection) GET_DIAGNOSTICS.invoke(handler); @@ -549,7 +554,6 @@ private static boolean isSpaces(Tok tok) { return !tok.isToken() && !tok.isNewline() && !tok.isComment(); } - @SuppressWarnings("for-rollout:NullAway") private static int updateColumn(int columnI, String originalTokText) { Integer last = Iterators.getLast(Newlines.lineOffsetIterator(originalTokText)); if (last > 0) { @@ -642,7 +646,6 @@ private static boolean isParamComment(Tok tok) { * @return the {@code 0}-based {@link Range} of tokens * @throws FormatterException on formatting errors */ - @SuppressWarnings("for-rollout:NullAway") Range characterRangeToTokenRange(int offset, int length) throws FormatterException { int requiredLength = offset + length; if (requiredLength > text.length()) { @@ -715,6 +718,7 @@ public String toString() { .toString(); } + @Nullable private JCCompilationUnit unit; @Override diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java index ad0f8df96..a3717902f 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java @@ -14,6 +14,7 @@ package com.palantir.javaformat.java; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.getLast; import static com.google.common.collect.Iterables.getOnlyElement; import static com.palantir.javaformat.Indent.If.make; @@ -32,7 +33,6 @@ import static com.sun.source.tree.Tree.Kind.ANNOTATION; import static com.sun.source.tree.Tree.Kind.EXTENDS_WILDCARD; import static com.sun.source.tree.Tree.Kind.STRING_LITERAL; -import static java.util.stream.Collectors.toList; import com.google.common.base.Enums; import com.google.common.base.MoreObjects; @@ -146,9 +146,9 @@ import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Stream; -import javax.annotation.Nullable; import javax.lang.model.element.Modifier; import javax.lang.model.element.Name; +import org.jspecify.annotations.Nullable; /** An AST visitor that builds a stream of {@link Op}s to format from the given {@link CompilationUnitTree}. */ public class JavaInputAstVisitor extends TreePathScanner { @@ -330,7 +330,7 @@ private boolean inExpression() { } @Override - public Void scan(Tree tree, Void unused) { + public Void scan(@Nullable Tree tree, Void unused) { inExpression.addLast(tree instanceof ExpressionTree || inExpression.peekLast()); int previous = builder.depth(); try { @@ -984,18 +984,14 @@ void visitVariables(List fragments, DeclarationKind declarationKin Optional.ofNullable(fragment.getInitializer()), Optional.of(";"), /* receiverExpression= */ Optional.empty(), - Optional.ofNullable(variableFragmentDims(true, 0, fragment.getType()))); + Optional.ofNullable(fragment.getType()).map(type -> variableFragmentDims(true, 0, type))); } else { declareMany(fragments, annotationDirection); } } - @SuppressWarnings("for-rollout:NullAway") private TypeWithDims variableFragmentDims(boolean first, int leadingDims, Tree type) { - if (type == null) { - return null; - } if (first) { return DimensionHelpers.extractDims(type, SortedDims.YES); } @@ -1004,7 +1000,6 @@ private TypeWithDims variableFragmentDims(boolean first, int leadingDims, Tree t null, leadingDims > 0 ? dims.dims.subList(0, dims.dims.size() - leadingDims) : dims.dims); } - @SuppressWarnings("for-rollout:NullAway") @Override public Void visitForLoop(ForLoopTree node, Void unused) { sync(node); @@ -1134,6 +1129,7 @@ public Void visitIf(IfTree node, Void unused) { // ImportTree#isModule() (JEP 511) exists from JDK 23 on; this module compiles with a JDK 21 // compiler, so it can't be referenced directly. + @Nullable private static final Method IMPORT_TREE_IS_MODULE = maybeGetMethod(ImportTree.class, "isModule"); @Override @@ -1406,7 +1402,6 @@ private static boolean isCompactSourceFile(Tree type) { && (classDecl.mods.flags & IMPLICIT_CLASS) == IMPLICIT_CLASS; } - @SuppressWarnings("for-rollout:NullAway") @Override public Void visitMethod(MethodTree node, Void unused) { sync(node); @@ -1470,7 +1465,7 @@ public Void visitMethod(MethodTree node, Void unused) { openedNameAndTypeScope = true; } scan(baseReturnType, null); - maybeAddDims(dims); + maybeAddDims(checkNotNull(dims)); } if (!first) { builder.breakOp(FillMode.INDEPENDENT, " ", ZERO, Optional.of(breakBeforeName)); @@ -1646,10 +1641,9 @@ private static List handleStream(List parts) { Name name = getMethodName(methodInvocation); return Stream.of("stream", "parallelStream", "toBuilder").anyMatch(name::contentEquals); }) - .collect(toList()); + .toList(); } - @SuppressWarnings("for-rollout:NullAway") private static Stream indexes(Stream stream, Predicate predicate) { return Streams.mapWithIndex(stream, (x, i) -> predicate.apply(x) ? i : -1) .filter(x -> x != -1); @@ -1778,7 +1772,7 @@ private boolean ambiguousUnaryOperator(UnaryTree node, String operatorName) { return true; } - private JCTree.Tag unaryTag(ExpressionTree expression) { + private JCTree.@Nullable Tag unaryTag(ExpressionTree expression) { if (expression instanceof UnaryTree) { return ((JCTree) expression).getTag(); } @@ -1825,7 +1819,6 @@ public Void visitReturn(ReturnTree node, Void unused) { } // TODO(cushon): is this worth special-casing? - @SuppressWarnings("for-rollout:NullAway") boolean visitSingleMemberAnnotation(AnnotationTree node) { if (node.getArguments().size() != 1) { return false; @@ -1851,7 +1844,6 @@ boolean visitSingleMemberAnnotation(AnnotationTree node) { return true; } - @SuppressWarnings("for-rollout:deprecation") @Override public Void visitCase(CaseTree node, Void unused) { sync(node); @@ -2204,7 +2196,6 @@ private void visitStatement( } } - @SuppressWarnings("for-rollout:NullAway") protected void visitStatements(List statements, boolean inlineFirst) { boolean first = true; PeekingIterator it = Iterators.peekingIterator(statements.iterator()); @@ -2219,7 +2210,6 @@ protected void visitStatements(List statements, boolean } markForPartialFormat(); first = false; - @SuppressWarnings("for-rollout:NullAway") List fragments = variableFragments(it, tree); if (!fragments.isEmpty()) { visitVariables( @@ -2944,7 +2934,6 @@ private void visitRegularDot(List items, boolean needDot) { // .happens()) // .thenReturn(result); // - @SuppressWarnings("for-rollout:NullAway") private boolean fillFirstArgument(ExpressionTree e, List items, Indent indent) { // is there a trailing dereference? if (items.size() < 2) { @@ -2984,7 +2973,6 @@ private boolean fillFirstArgument(ExpressionTree e, List items, private void visitDotWithPrefix( List items, boolean needDot, Collection prefixes, FillMode prefixFillMode) { // Are there method invocations or field accesses after the prefix? - @SuppressWarnings("for-rollout:NullAway") boolean trailingDereferences = !prefixes.isEmpty() && getLast(prefixes) < items.size() - 1; boolean hasMethodInvocations = items.stream().anyMatch(expr -> expr instanceof MethodInvocationTree); @@ -3120,7 +3108,7 @@ private ExpressionTree getArrayBase(ExpressionTree node) { return node; } - @SuppressWarnings("for-rollout:NullAway") + @Nullable private ExpressionTree getMethodReceiver(MethodInvocationTree methodInvocation) { ExpressionTree select = methodInvocation.getMethodSelect(); return select instanceof MemberSelectTree memberSelectTree ? memberSelectTree.getExpression() : null; @@ -3364,14 +3352,12 @@ public void scan(JCTree tree) { } /** Returns the number of columns if the arguments arg laid out in a grid, or else {@code -1}. */ - @SuppressWarnings("for-rollout:NullAway") private int argumentsAreTabular(List arguments) { if (arguments.isEmpty()) { return -1; } List> rows = new ArrayList<>(); PeekingIterator it = Iterators.peekingIterator(arguments.iterator()); - @SuppressWarnings("for-rollout:NullAway") int start0 = actualColumn(it.peek()); { List row = new ArrayList<>(); @@ -3389,7 +3375,6 @@ private int argumentsAreTabular(List arguments) { } while (it.hasNext()) { List row = new ArrayList<>(); - @SuppressWarnings("for-rollout:NullAway") int start = actualColumn(it.peek()); if (start != start0) { return -1; @@ -3444,14 +3429,12 @@ static int rowLength(List row) { return size; } - @SuppressWarnings("for-rollout:NullAway") private Integer actualColumn(ExpressionTree expression) { Map positionToColumnMap = builder.getInput().getPositionToColumnMap(); - return positionToColumnMap.get(builder.actualStartColumn(getStartPosition(expression))); + return checkNotNull(positionToColumnMap.get(builder.actualStartColumn(getStartPosition(expression)))); } /** How many lines does this node take up in the input. Returns at least 1. */ - @SuppressWarnings("for-rollout:NullAway") int lineSpan(Tree node) { ImmutableRangeMap positionTokenMap = builder.getInput().getPositionTokenMap(); @@ -3464,8 +3447,8 @@ int lineSpan(Tree node) { while (endPosition > startPosition && positionTokenMap.get(endPosition) == null) { endPosition--; } - Input.Token startToken = positionTokenMap.get(startPosition); - Input.Token endToken = positionTokenMap.get(endPosition); + Input.Token startToken = checkNotNull(positionTokenMap.get(startPosition)); + Input.Token endToken = checkNotNull(positionTokenMap.get(endPosition)); return lineNumberAt(endToken) - lineNumberAt(startToken) + 1; } @@ -3505,12 +3488,11 @@ enum DeclarationKind { } /** Declare one variable or variable-like thing. */ - @SuppressWarnings("TooManyArguments") int declareOne( DeclarationKind kind, Direction annotationsDirection, Optional modifiers, - Tree type, + @Nullable Tree type, Name name, String op, String equals, @@ -3534,12 +3516,11 @@ int declareOne( } /** Declare one variable or variable-like thing. */ - @SuppressWarnings("TooManyArguments") int declareOne( DeclarationKind kind, Direction annotationsDirection, Optional modifiers, - Tree type, + @Nullable Tree type, Name name, String op, String equals, @@ -3792,7 +3773,6 @@ protected void addBodyDeclarations( * class/interface/enum bodies (indented by {@link #plusTwo}) and for the bare top-level member list of a * compact source file (JEP 512), which is indented by {@link Indent.Const#ZERO}. */ - @SuppressWarnings("for-rollout:NullAway") private void addBodyDeclarations( List bodyDeclarations, BracesOrNot braces, @@ -3931,7 +3911,6 @@ private boolean hasTrailingToken(Input input, List nodes, String return false; } Tree lastNode = getLast(nodes); - @SuppressWarnings("for-rollout:NullAway") Optional nextToken = getNextToken(input, getEndPosition(lastNode, getCurrentPath())); return nextToken.isPresent() && nextToken.get().getTok().getText().equals(token); } @@ -4025,7 +4004,7 @@ protected void sync(Tree node) { * have it. Used with {@link #invoke} to reach AST accessors that are newer than the compiler this module builds * with, such as {@code ImportTree#isModule()} (JDK 23). */ - @SuppressWarnings("for-rollout:NullAway") + @Nullable protected static Method maybeGetMethod(Class c, String name) { try { return c.getMethod(name); diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaOutput.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaOutput.java index 1b254f680..5ddeefca5 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaOutput.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaOutput.java @@ -14,6 +14,8 @@ package com.palantir.javaformat.java; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.base.CharMatcher; import com.google.common.base.MoreObjects; import com.google.common.collect.DiscreteDomain; @@ -242,7 +244,6 @@ void flush() { * * @return a list of {@link Replacement}s, sorted by start index, without overlaps */ - @SuppressWarnings("for-rollout:NullAway") public ImmutableList getFormatReplacements(RangeSet iRangeSet0) { ImmutableList.Builder result = ImmutableList.builder(); Map> kToJ = JavaOutput.makeKToIJ(this); @@ -278,15 +279,14 @@ public ImmutableList getFormatReplacements(RangeSet iRange replaceFrom--; } - @SuppressWarnings("for-rollout:NullAway") - int i = kToJ.get(startTok.getIndex()).lowerEndpoint(); + int i = checkNotNull(kToJ.get(startTok.getIndex())).lowerEndpoint(); // Include leading blank lines from the formatted output, unless the formatted range // starts at the beginning of the file. while (i > 0 && getLine(i - 1).isEmpty()) { i--; } // Write out the formatted range. - for (; i < kToJ.get(endTok.getIndex()).upperEndpoint(); i++) { + for (; i < checkNotNull(kToJ.get(endTok.getIndex())).upperEndpoint(); i++) { // It's possible to run out of output lines (e.g. if the input ended with // multiple trailing newlines). if (i < getLineCount()) { @@ -357,7 +357,6 @@ public ImmutableList getFormatReplacements(RangeSet iRange * @param iRange the {@link Range} of tokens * @return the expanded token range */ - @SuppressWarnings("for-rollout:NullAway") private Range expandToBreakableRegions(Range iRange) { // The original line range. int loTok = iRange.lowerEndpoint(); @@ -367,8 +366,8 @@ private Range expandToBreakableRegions(Range iRange) { if (!partialFormatRanges().contains(loTok) || !partialFormatRanges().contains(hiTok)) { return EMPTY_RANGE; } - loTok = partialFormatRanges().rangeContaining(loTok).lowerEndpoint(); - hiTok = partialFormatRanges().rangeContaining(hiTok).upperEndpoint(); + loTok = checkNotNull(partialFormatRanges().rangeContaining(loTok)).lowerEndpoint(); + hiTok = checkNotNull(partialFormatRanges().rangeContaining(hiTok)).upperEndpoint(); return Range.closedOpen(loTok, hiTok + 1); } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/JavacTokens.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JavacTokens.java index 705837412..77baf2c3b 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/JavacTokens.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/JavacTokens.java @@ -28,6 +28,7 @@ import com.sun.tools.javac.parser.UnicodeReader; import com.sun.tools.javac.util.Context; import java.util.Set; +import org.jspecify.annotations.Nullable; /** A wrapper around javac's lexer. */ class JavacTokens { @@ -38,12 +39,16 @@ class JavacTokens { /** An unprocessed input token, including whitespace and comments. */ static class RawTok { + @Nullable private final String stringVal; + + @Nullable private final TokenKind kind; + private final int pos; private final int endPos; - RawTok(String stringVal, TokenKind kind, int pos, int endPos) { + RawTok(@Nullable String stringVal, @Nullable TokenKind kind, int pos, int endPos) { this.stringVal = stringVal; this.kind = kind; this.pos = pos; @@ -51,6 +56,7 @@ static class RawTok { } /** The token kind, or {@code null} for whitespace and comments. */ + @Nullable public TokenKind kind() { return kind; } @@ -66,13 +72,13 @@ public int endPos() { } /** The escaped string value of a literal, or {@code null} for other tokens. */ + @Nullable public String stringVal() { return stringVal; } } /** Lex the input and return a list of {@link RawTok}s. */ - @SuppressWarnings("for-rollout:NullAway") public static ImmutableList getTokens(String source, Context context, Set stopTokens) { if (source == null) { return ImmutableList.of(); @@ -155,7 +161,7 @@ static class CommentWithTextAndPosition implements Comment { private final AccessibleReader reader; private final CommentStyle style; - @SuppressWarnings("for-rollout:NullAway") + @Nullable private String text = null; public CommentWithTextAndPosition(int pos, int endPos, AccessibleReader reader, CommentStyle style) { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/JsonSink.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JsonSink.java index 6aa69eac2..a07871487 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/JsonSink.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/JsonSink.java @@ -15,6 +15,8 @@ */ package com.palantir.javaformat.java; +import static com.google.common.base.Preconditions.checkNotNull; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -31,16 +33,16 @@ import java.util.Map; import java.util.Optional; import java.util.OptionalInt; +import org.jspecify.annotations.Nullable; public final class JsonSink implements Sink { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().registerModule(new Jdk8Module()); private final Map childrenMap = new HashMap<>(); - @SuppressWarnings("for-rollout:NullAway") + @Nullable private ObjectNode rootNode; - @SuppressWarnings("for-rollout:NullAway") @Override public FinishExplorationNode startExplorationNode( int exporationId, @@ -50,7 +52,7 @@ public FinishExplorationNode startExplorationNode( Optional incomingState) { ObjectNode json; if (parentLevelId.isPresent()) { - json = childrenMap.get(parentLevelId.getAsInt()).addObject(); + json = checkNotNull(childrenMap.get(parentLevelId.getAsInt())).addObject(); } else { json = rootNode = OBJECT_MAPPER.createObjectNode(); } @@ -72,8 +74,7 @@ public FinishExplorationNode startExplorationNode( @Override public FinishLevelNode writeLevelNode(int levelNodeId, int parentExplorationId, State incomingState, Level level) { - @SuppressWarnings("for-rollout:NullAway") - ObjectNode json = childrenMap.get(parentExplorationId).addObject(); + ObjectNode json = checkNotNull(childrenMap.get(parentExplorationId)).addObject(); json.put("type", "level"); json.put("id", levelNodeId); json.put("levelId", level.id()); diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/Main.java b/open-java-format/src/main/java/com/palantir/javaformat/java/Main.java index 5551b325d..ca0373eb7 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/Main.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/Main.java @@ -129,7 +129,6 @@ private int formatFiles(CommandLineOptions parameters, JavaFormatterOptions opti } } - @SuppressWarnings("for-rollout:RedundantControlFlow") private int formatFiles( CommandLineOptions parameters, JavaFormatterOptions options, ExecutorService executorService) { Map inputs = new LinkedHashMap<>(); @@ -166,7 +165,7 @@ private int formatFiles( } catch (ExecutionException e) { if (e.getCause() instanceof FormatterException) { for (FormatterDiagnostic diagnostic : ((FormatterException) e.getCause()).diagnostics()) { - errWriter.println(path + ":" + diagnostic.toString()); + errWriter.println(path + ":" + diagnostic); } } else { errWriter.println(path + ": error: " @@ -229,7 +228,7 @@ private int formatStdin(CommandLineOptions parameters, JavaFormatterOptions opti } } catch (FormatterException e) { for (FormatterDiagnostic diagnostic : e.diagnostics()) { - errWriter.println(stdinFilename + ":" + diagnostic.toString()); + errWriter.println(stdinFilename + ":" + diagnostic); } ok = false; // TODO(cpovirk): Catch other types of exception (as we do in the formatFiles case). diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/ModifierOrderer.java b/open-java-format/src/main/java/com/palantir/javaformat/java/ModifierOrderer.java index fe97403ac..6366f1200 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/ModifierOrderer.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/ModifierOrderer.java @@ -16,6 +16,7 @@ package com.palantir.javaformat.java; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Iterables.getLast; @@ -33,8 +34,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import javax.annotation.Nullable; import javax.lang.model.element.Modifier; +import org.jspecify.annotations.Nullable; /** Fixes sequences of modifiers to be in JLS order. */ final class ModifierOrderer { @@ -71,7 +72,7 @@ boolean isEmpty() { return tokens.isEmpty() || modifier == null; } - @SuppressWarnings("for-rollout:NullAway") + @Nullable Modifier modifier() { return modifier; } @@ -105,10 +106,9 @@ ImmutableList getToksAfter() { } @Override - @SuppressWarnings("for-rollout:NullAway") public int compareTo(ModifierTokens o) { checkState(!isEmpty()); // empty ModifierTokens are filtered out prior to sorting - return modifier.compareTo(o.modifier); + return checkNotNull(modifier).compareTo(checkNotNull(o.modifier)); } } @@ -209,7 +209,6 @@ private static Modifier asModifier(ImmutableList tokens) { * Returns the given token as a {@link javax.lang.model.element.Modifier}, or {@code null} if it is not a modifier. */ @Nullable - @SuppressWarnings("for-rollout:NullAway") private static Modifier asModifier(Token token) { TokenKind kind = ((JavaInput.Tok) token.getTok()).kind(); if (kind != null) { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/RemoveUnusedImports.java b/open-java-format/src/main/java/com/palantir/javaformat/java/RemoveUnusedImports.java index a42aee5ec..a5441eb24 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/RemoveUnusedImports.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/RemoveUnusedImports.java @@ -49,6 +49,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.jspecify.annotations.Nullable; /** * Removes unused imports from a source file. Imports that are only used in javadoc are also removed, and the references @@ -76,7 +77,7 @@ private static final class UnusedImportScanner extends TreePathScanner usedNames = new LinkedHashSet<>(); - private final Multimap> usedInJavadoc = HashMultimap.create(); + private final Multimap> usedInJavadoc = HashMultimap.create(); final JavacTrees trees; final DocTreeScanner docTreeSymbolScanner; @@ -103,7 +104,6 @@ public Void visitIdentifier(IdentifierTree tree, Void unused) { // TODO(fwindheuser): remove this override when pattern matching in switch is no longer a preview // feature, and TreePathScanner visits CaseTree#getLabels instead of CaseTree#getExpressions - @SuppressWarnings("unchecked") // reflection @Override public Void visitCase(CaseTree tree, Void unused) { if (CASE_TREE_GET_LABELS != null) { @@ -116,9 +116,10 @@ public Void visitCase(CaseTree tree, Void unused) { return super.visitCase(tree, null); } + @Nullable private static final Method CASE_TREE_GET_LABELS = caseTreeGetLabels(); - @SuppressWarnings("for-rollout:NullAway") + @Nullable private static Method caseTreeGetLabels() { try { return CaseTree.class.getMethod("getLabels"); @@ -127,9 +128,8 @@ private static Method caseTreeGetLabels() { } } - @SuppressWarnings("for-rollout:VoidUsed") @Override - public Void scan(Tree tree, Void unused) { + public Void scan(@Nullable Tree tree, Void unused) { if (tree == null) { return null; } @@ -181,11 +181,10 @@ public Void visitReference(ReferenceTree referenceTree, Void unused) { private class ReferenceScanner extends TreeScanner { private final long basePos; - public ReferenceScanner(long basePos) { + ReferenceScanner(long basePos) { this.basePos = basePos; } - @SuppressWarnings("for-rollout:VoidUsed") @Override public Void visitIdentifier(IdentifierTree node, Void aVoid) { usedInJavadoc.put( @@ -223,7 +222,7 @@ private static RangeMap buildReplacements( String contents, JCCompilationUnit unit, Set usedNames, - Multimap> usedInJavadoc) { + Multimap> usedInJavadoc) { RangeMap replacements = TreeRangeMap.create(); String sep = Newlines.guessLineSeparator(contents); // From JDK 23 on, getImports() also returns JCModuleImport, which is not a JCImport, so iterate @@ -297,6 +296,7 @@ private static boolean isBlankLineAfter(String contents, int pos, String sep) { // ImportTree#isModule() (JEP 511) exists from JDK 23 on; this module compiles with a JDK 21 // compiler, so it can't be referenced directly. Same idiom as CASE_TREE_GET_LABELS above. + @Nullable private static final Method IMPORT_TREE_IS_MODULE = JavaInputAstVisitor.maybeGetMethod(ImportTree.class, "isModule"); @@ -316,7 +316,7 @@ private static String getSimpleName(ImportTree importTree) { private static boolean isUnused( JCCompilationUnit unit, Set usedNames, - Multimap> usedInJavadoc, + Multimap> usedInJavadoc, ImportTree importTree, String simpleName) { if (isModuleImport(importTree)) { @@ -358,7 +358,7 @@ private static boolean isOnDemand(ImportTree importTree) { } private static boolean isUsed( - Set usedNames, Multimap> usedInJavadoc, String simpleName) { + Set usedNames, Multimap> usedInJavadoc, String simpleName) { return usedNames.contains(simpleName) || usedInJavadoc.containsKey(simpleName); } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java b/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java index d5472baa8..e7cd74b3a 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java @@ -51,7 +51,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** Wraps string literals that exceed the column limit, and joins adjacent ones that share a line. */ public final class StringWrapper { @@ -130,7 +130,6 @@ private static String wrapOnce(final int columnLimit, String input, Formatter fo return result; } - @SuppressWarnings("ResultOfMethodCallIgnored") private static ImmutableSet> rangesAfterAppliedReplacements( TreeRangeMap replacements) { ImmutableSet.Builder> outputRanges = ImmutableSet.builder(); @@ -174,7 +173,7 @@ private static class Reflower { this.lineMap = unit.getLineMap(); } - protected TreeRangeMap getReflowReplacements() { + TreeRangeMap getReflowReplacements() { // Paths to string literals that extend past the column limit. List longStringLiterals = new ArrayList<>(); // Paths to text blocks to be re-indented. @@ -429,7 +428,7 @@ private Map computeCustomTextBlocksIndent(List textB } return textBlockToParent.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> parentToIndent.get(e.getValue()))); + .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> parentToIndent.get(e.getValue()))); } private String computePrefixIndentation( @@ -449,7 +448,6 @@ private String computePrefixIndentation( int startLine = lineMap.getLineNumber(startingPos); int lineStartPosition = lineMap.getStartPosition(startLine); int endPos = getEndPosition(unit, expression); - int endLine = lineMap.getLineNumber(endPos); int parentLine = shouldUseStartLineParent ? startParentLine : endParentLine; // ignore indentation if the current argument is on the same line as the parent if (startLine == parentLine) { @@ -482,7 +480,6 @@ private record Chain( int firstLineColumn, List plain) {} - @SuppressWarnings("for-rollout:NullAway") private void wrapLongStrings( TreeRangeMap replacements, List longStringLiterals, @@ -516,7 +513,6 @@ private void wrapLongStrings( // Handling leaving trailing non-string tokens at the end of the literal, // e.g. the trailing `);` in `foo("...");`. - @SuppressWarnings("for-rollout:NullAway") int end = getEndPosition(unit, getLast(flat)); int lineEnd = end; while (Newlines.hasNewlineAt(input, lineEnd) == -1) { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/Trees.java b/open-java-format/src/main/java/com/palantir/javaformat/java/Trees.java index d7fd65e2b..f90b1b8d5 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/Trees.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/Trees.java @@ -35,8 +35,8 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; -import javax.annotation.Nullable; import javax.lang.model.element.Name; +import org.jspecify.annotations.Nullable; /** Utilities for working with {@link Tree}s. */ class Trees { @@ -142,7 +142,7 @@ static Name getMethodName(MethodInvocationTree methodInvocation) { } /** Returns the receiver of a qualified method invocation expression, or {@code null}. */ - @SuppressWarnings("for-rollout:NullAway") + @Nullable static ExpressionTree getMethodReceiver(MethodInvocationTree methodInvocation) { ExpressionTree select = methodInvocation.getMethodSelect(); return select instanceof MemberSelectTree memberSelectTree ? memberSelectTree.getExpression() : null; diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/TypeNameClassifier.java b/open-java-format/src/main/java/com/palantir/javaformat/java/TypeNameClassifier.java index 8780f73ca..4353b2a8b 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/TypeNameClassifier.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/TypeNameClassifier.java @@ -29,7 +29,7 @@ private enum TyParseState { /** The start state. */ START(false) { @Override - public TyParseState next(JavaCaseFormat n) { + TyParseState next(JavaCaseFormat n) { return switch (n) { case UPPERCASE -> // if we see an UpperCamel later, assume this was a class @@ -47,7 +47,7 @@ public TyParseState next(JavaCaseFormat n) { /** The current prefix is a type. */ TYPE(true) { @Override - public TyParseState next(JavaCaseFormat n) { + TyParseState next(JavaCaseFormat n) { return switch (n) { case UPPERCASE, LOWER_CAMEL, LOWERCASE -> TyParseState.FIRST_STATIC_MEMBER; case UPPER_CAMEL -> TyParseState.TYPE; @@ -58,7 +58,7 @@ public TyParseState next(JavaCaseFormat n) { /** The current prefix is a type, followed by a single static member access. */ FIRST_STATIC_MEMBER(true) { @Override - public TyParseState next(JavaCaseFormat n) { + TyParseState next(JavaCaseFormat n) { return TyParseState.REJECT; } }, @@ -66,7 +66,7 @@ public TyParseState next(JavaCaseFormat n) { /** Anything not represented by one of the other states. */ REJECT(false) { @Override - public TyParseState next(JavaCaseFormat n) { + TyParseState next(JavaCaseFormat n) { return TyParseState.REJECT; } }, @@ -74,7 +74,7 @@ public TyParseState next(JavaCaseFormat n) { /** An ambiguous type prefix. */ AMBIGUOUS(false) { @Override - public TyParseState next(JavaCaseFormat n) { + TyParseState next(JavaCaseFormat n) { return switch (n) { case UPPERCASE -> AMBIGUOUS; case LOWER_CAMEL, LOWERCASE -> TyParseState.REJECT; @@ -89,12 +89,12 @@ public TyParseState next(JavaCaseFormat n) { this.isSingleUnit = isSingleUnit; } - public boolean isSingleUnit() { + boolean isSingleUnit() { return isSingleUnit; } /** Transition function. */ - public abstract TyParseState next(JavaCaseFormat n); + abstract TyParseState next(JavaCaseFormat n); } /** diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/UsageException.java b/open-java-format/src/main/java/com/palantir/javaformat/java/UsageException.java index eca7a781e..c8644ecc5 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/UsageException.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/UsageException.java @@ -17,7 +17,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Joiner; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** Checked exception class for formatter command-line usage errors. */ final class UsageException extends Exception { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java b/open-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java index 746a8e2be..0fac3c4a7 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java @@ -47,20 +47,31 @@ import java.util.List; import java.util.Optional; import javax.lang.model.element.Name; +import org.jspecify.annotations.Nullable; /** * Extends {@link JavaInputAstVisitor} with support for AST nodes that were added or modified for Java 14. */ -@SuppressWarnings("Since15") public class Java14InputAstVisitor extends JavaInputAstVisitor { + @Nullable private static final Method COMPILATION_UNIT_TREE_GET_MODULE = maybeGetMethod(CompilationUnitTree.class, "getModule"); + + @Nullable private static final Method CLASS_TREE_GET_PERMITS_CLAUSE = maybeGetMethod(ClassTree.class, "getPermitsClause"); + + @Nullable private static final Method BINDING_PATTERN_TREE_GET_VARIABLE = maybeGetMethod(BindingPatternTree.class, "getVariable"); + + @Nullable private static final Method BINDING_PATTERN_TREE_GET_TYPE = maybeGetMethod(BindingPatternTree.class, "getType"); + + @Nullable private static final Method BINDING_PATTERN_TREE_GET_BINDING = maybeGetMethod(BindingPatternTree.class, "getBinding"); + + @Nullable private static final Method CASE_TREE_GET_LABELS = maybeGetMethod(CaseTree.class, "getLabels"); public Java14InputAstVisitor(OpsBuilder builder, int indentMultiplier) { @@ -94,7 +105,6 @@ protected List getPermitsClause(ClassTree node) { } } - @SuppressWarnings("for-rollout:NullAway") @Override public Void visitBindingPattern(BindingPatternTree node, Void unused) { sync(node); @@ -121,7 +131,7 @@ private static boolean isVarType(Tree type) { return type.getKind().name().equals("VAR_TYPE"); } - private void visitBindingPattern(ModifiersTree modifiers, Tree type, Name name) { + private void visitBindingPattern(@Nullable ModifiersTree modifiers, @Nullable Tree type, Name name) { builder.open(plusFour); if (modifiers != null) { builder.addAll(visitModifiers(modifiers, Direction.HORIZONTAL, Optional.empty())); @@ -252,7 +262,6 @@ public Void visitInstanceOf(InstanceOfTree node, Void unused) { return null; } - @SuppressWarnings("for-rollout:NullAway") @Override public Void visitCase(CaseTree node, Void unused) { sync(node); @@ -347,7 +356,7 @@ public Void visitLambdaExpression(LambdaExpressionTree node, Void unused) { return null; } - @SuppressWarnings({"NullableProblems", "for-rollout:NullAway"}) + @Nullable protected ExpressionTree getGuard(final CaseTree node) { return null; } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/java21/Java21InputAstVisitor.java b/open-java-format/src/main/java/com/palantir/javaformat/java/java21/Java21InputAstVisitor.java index f6f586ee7..0d80cafa7 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/java21/Java21InputAstVisitor.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/java21/Java21InputAstVisitor.java @@ -27,12 +27,12 @@ import com.sun.source.tree.PatternTree; import com.sun.source.tree.Tree; import javax.lang.model.element.Name; +import org.jspecify.annotations.Nullable; /** * Extends {@link Java14InputAstVisitor} with support for AST nodes that were added or modified in * Java 21. */ -@SuppressWarnings("Since21") public class Java21InputAstVisitor extends Java14InputAstVisitor { // AnyPatternTree (the unnamed pattern `_`, JEP 456) is still a preview API on JDK 21, which this // module compiles with, so match it by Tree.Kind name instead of by type. @@ -43,7 +43,7 @@ public Java21InputAstVisitor(OpsBuilder builder, int indentMultiplier) { } @Override - public Void scan(Tree tree, Void unused) { + public Void scan(@Nullable Tree tree, Void unused) { if (tree != null && tree.getKind().name().equals(ANY_PATTERN_KIND_NAME)) { // No sync(tree): javac records the start position one past the `_`, which makes sync() // think a token was skipped and throw. This branch emits one leaf token and never recurses. diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/CharStream.java b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/CharStream.java index 2664aa3aa..f74d8eccf 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/CharStream.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/CharStream.java @@ -45,7 +45,6 @@ boolean tryConsume(String expected) { /* * @param pattern the pattern to search for, which must be anchored to match only at position 0 */ - @SuppressWarnings("for-rollout:AlmostJavadoc") boolean tryConsumeRegex(Pattern pattern) { Matcher matcher = pattern.matcher(remaining); if (!matcher.find()) { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocLexer.java b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocLexer.java index c67b0f1ae..72a899b06 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocLexer.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocLexer.java @@ -174,8 +174,7 @@ private ImmutableList generateTokens() throws LexException { result = joinAdjacentLiteralsAndAdjacentWhitespace(result); result = inferParagraphTags(result); result = optionalizeSpacesAfterLinks(result); - result = deindentPreCodeBlocks(result); - return result; + return deindentPreCodeBlocks(result); } private Token readToken() throws LexException { @@ -320,7 +319,6 @@ private void checkMatchingTags() throws LexException { * *

Note that we do not merge a literal token and a whitespace token together. */ - @SuppressWarnings("for-rollout:NullAway") private static ImmutableList joinAdjacentLiteralsAndAdjacentWhitespace(List input) { /* * Note: Our final token is always END_JAVADOC. This saves us some trouble: @@ -335,7 +333,6 @@ private static ImmutableList joinAdjacentLiteralsAndAdjacentWhitespace(Li boolean lastTagWasInlineTagStart = false; for (PeekingIterator tokens = peekingIterator(input.iterator()); tokens.hasNext(); ) { - @SuppressWarnings("for-rollout:NullAway") Token.Type nextType = tokens.peek().getType(); if (nextType == INLINE_TAG_OPEN) { inlineTagDepth.increment(); @@ -429,7 +426,6 @@ private static boolean isSuspendedHyphenConjunction(String s) { *

This method must be called after {@link #joinAdjacentLiteralsAndAdjacentWhitespace}, as it assumes that * adjacent whitespace tokens have already been joined. */ - @SuppressWarnings("for-rollout:NullAway") private static ImmutableList inferParagraphTags(List input) { ImmutableList.Builder output = ImmutableList.builder(); @@ -468,7 +464,6 @@ && hasMultipleNewlines(tokens.peek().getValue())) { *

This method must be called after {@link #joinAdjacentLiteralsAndAdjacentWhitespace}, as it assumes that * adjacent whitespace tokens have already been joined. */ - @SuppressWarnings("for-rollout:NullAway") private static ImmutableList optionalizeSpacesAfterLinks(List input) { ImmutableList.Builder output = ImmutableList.builder(); @@ -498,7 +493,6 @@ private static ImmutableList optionalizeSpacesAfterLinks(List inpu * *

Also trim leading and trailing blank lines, and move the trailing `}` to its own line. */ - @SuppressWarnings("for-rollout:NullAway") private static ImmutableList deindentPreCodeBlocks(List input) { ImmutableList.Builder output = ImmutableList.builder(); for (PeekingIterator tokens = peekingIterator(input.iterator()); tokens.hasNext(); ) { @@ -523,7 +517,6 @@ private static ImmutableList deindentPreCodeBlocks(List input) { return output.build(); } - @SuppressWarnings("for-rollout:NullAway") private static void deindentPreCodeBlock(ImmutableList.Builder output, PeekingIterator tokens) { Deque saved = new ArrayDeque<>(); output.add(new Token(LITERAL, tokens.next().getValue().trim())); @@ -549,7 +542,7 @@ private static void deindentPreCodeBlock(ImmutableList.Builder output, Pe if (last.length() > 1) { saved.addLast(new Token( LITERAL, last.getValue().substring(0, last.getValue().length() - 1))); - saved.addLast(new Token(FORCED_NEWLINE, null)); + saved.addLast(new Token(FORCED_NEWLINE, "\n")); } trailingBrace = true; } @@ -635,7 +628,6 @@ private static boolean hasMultipleNewlines(String s) { * with matching only one character here. That would eliminate the need for the regex entirely. * That might be faster or slower than what we do now. */ - @SuppressWarnings("for-rollout:AlmostJavadoc") private static final Pattern LITERAL_PATTERN = compile("^.[^ \t\n@<{}*]*", DOTALL); private static Pattern fullCommentPattern() { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocWriter.java b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocWriter.java index 47be68fdb..b9071173a 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocWriter.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocWriter.java @@ -280,7 +280,6 @@ private void requestNewline() { requestWhitespace(NEWLINE); } - @SuppressWarnings("for-rollout:NullAway") private void requestWhitespace(RequestedWhitespace requestedWhitespace) { this.requestedWhitespace = Ordering.natural().max(requestedWhitespace, this.requestedWhitespace); } diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/DiagnosticTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/DiagnosticTest.java index 5961a4335..b57ee476f 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/DiagnosticTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/DiagnosticTest.java @@ -17,13 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.UTF_8; -import com.google.common.base.Joiner; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Locale; @@ -54,20 +52,19 @@ void restoreLocale() throws Exception { @Test void parseError() throws Exception { - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String input = Joiner.on('\n') - .join( - "public class InvalidSyntax {", - " private static NumPrinter {", - " public static void print(int n) {", - " System.out.printf(\"%d%n\", n);", - " }", - " }", - "", - " public static void main(String[] args) {", - " NumPrinter.print(args.length);", - " }", - "}"); + String input = """ + public class InvalidSyntax { + private static NumPrinter { + public static void print(int n) { + System.out.printf("%d%n", n); + } + } + + public static void main(String[] args) { + NumPrinter.print(args.length); + } + }\ + """; StringWriter stdout = new StringWriter(); StringWriter stderr = new StringWriter(); @@ -149,7 +146,7 @@ void parseError2() throws FormatterException, IOException, UsageException { String input = "class Foo { void f() {\n g() } }"; Path path = testFolder.resolve("A.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -166,7 +163,7 @@ void parseError2() throws FormatterException, IOException, UsageException { void parseErrorStdin() throws FormatterException, IOException, UsageException { String input = "class Foo { void f() {\n g() } }"; - InputStream inStream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)); + InputStream inStream = new ByteArrayInputStream(input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); Main main = new Main(new PrintWriter(out, true), new PrintWriter(err, true), inStream); @@ -182,7 +179,7 @@ void lexError2() throws FormatterException, IOException, UsageException { String input = "class Foo { void f() {\n g('foo'); } }"; Path path = testFolder.resolve("A.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -198,7 +195,7 @@ void lexError2() throws FormatterException, IOException, UsageException { @Test void lexErrorStdin() throws FormatterException, IOException, UsageException { String input = "class Foo { void f() {\n g('foo'); } }"; - InputStream inStream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)); + InputStream inStream = new ByteArrayInputStream(input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); Main main = new Main(new PrintWriter(out, true), new PrintWriter(err, true), inStream); diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterIntegrationTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterIntegrationTest.java index ae644be92..6190d5174 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterIntegrationTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterIntegrationTest.java @@ -14,6 +14,7 @@ package com.palantir.javaformat.java; +import static com.google.common.base.Preconditions.checkNotNull; import static com.palantir.javaformat.java.FileBasedTests.assumeJavaVersionForTest; import static com.palantir.javaformat.java.FileBasedTests.isRecreate; import static org.assertj.core.api.Assertions.assertThat; @@ -43,13 +44,16 @@ public static List data() throws IOException { private final String name; private final String input; private final String expected; - private final String separator; public FormatterIntegrationTest(String name, String input, String expected) { this.name = name; this.input = input; this.expected = expected; - this.separator = isRecreate() ? null : Newlines.getLineEnding(expected); + } + + /** The line separator of the expected output, which the idempotency tests replace with each of the others. */ + private String separator() { + return checkNotNull(Newlines.getLineEnding(expected)); } /** @@ -79,7 +83,7 @@ public void format() { tests.writeFormatterOutput(name, output); return; } - assertThat(output).describedAs("bad output for " + name).isEqualTo(expected); + assertThat(output).describedAs("bad output for %s", name).isEqualTo(expected); } catch (FormatterException e) { throw new RuntimeException(String.format("Formatter crashed on %s", name), e); } @@ -98,9 +102,9 @@ public void idempotentLF() { assumeJavaVersionForTest(name); Assumptions.assumeFalse(isRecreate(), "Not running when recreating test outputs"); try { - String mangled = expected.replace(separator, "\n"); + String mangled = expected.replace(separator(), "\n"); String output = createFormatter().formatSource(mangled); - assertThat(output).describedAs("bad output for " + name).isEqualTo(mangled); + assertThat(output).describedAs("bad output for %s", name).isEqualTo(mangled); } catch (FormatterException e) { throw new RuntimeException(String.format("Formatter crashed on %s", name), e); } @@ -111,9 +115,9 @@ public void idempotentCR() { assumeJavaVersionForTest(name); Assumptions.assumeFalse(isRecreate(), "Not running when recreating test outputs"); try { - String mangled = expected.replace(separator, "\r"); + String mangled = expected.replace(separator(), "\r"); String output = createFormatter().formatSource(mangled); - assertThat(output).describedAs("bad output for " + name).isEqualTo(mangled); + assertThat(output).describedAs("bad output for %s", name).isEqualTo(mangled); } catch (FormatterException e) { throw new RuntimeException(String.format("Formatter crashed on %s", name), e); } @@ -124,9 +128,9 @@ public void idempotentCRLF() { assumeJavaVersionForTest(name); Assumptions.assumeFalse(isRecreate(), "Not running when recreating test outputs"); try { - String mangled = expected.replace(separator, "\r\n"); + String mangled = expected.replace(separator(), "\r\n"); String output = createFormatter().formatSource(mangled); - assertThat(output).describedAs("bad output for " + name).isEqualTo(mangled); + assertThat(output).describedAs("bad output for %s", name).isEqualTo(mangled); } catch (FormatterException e) { throw new RuntimeException(String.format("Formatter crashed on %s", name), e); } diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java index 68f462e27..96ddfadca 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java @@ -17,11 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static com.palantir.javaformat.java.JavaFormatterOptions.Style; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; -import com.google.common.base.Joiner; import com.google.common.collect.Range; import com.google.common.io.CharStreams; import java.io.ByteArrayInputStream; @@ -30,13 +30,13 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; import java.util.Arrays; import java.util.List; import javax.lang.model.element.Modifier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -69,12 +69,20 @@ void formatNonJavaFiles() throws Exception { @Test void formatStdinStdoutWithDashFlag() throws Exception { - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String input = "class Foo{\n" + "void f\n" + "() {\n" + "}\n" + "}\n"; - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String expectedOutput = "class Foo {\n" + " void f() {}\n" + "}\n"; + String input = """ + class Foo{ + void f + () { + } + } + """; + String expectedOutput = """ + class Foo { + void f() {} + } + """; - InputStream in = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)); + InputStream in = new ByteArrayInputStream(input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -90,13 +98,26 @@ void formatStdinStdoutWithDashFlag() throws Exception { @Test void formatLengthUpToEOF() throws Exception { - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String input = "class Foo{\n" + "void f\n" + "() {\n" + "}\n" + "}\n\n\n\n\n\n"; - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String expectedOutput = "class Foo {\n" + " void f() {}\n" + "}\n"; + String input = """ + class Foo{ + void f + () { + } + } + + + + + + """; + String expectedOutput = """ + class Foo { + void f() {} + } + """; Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -112,7 +133,7 @@ void formatLengthOutOfRange() throws Exception { String input = "class Foo{}\n"; Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -131,20 +152,19 @@ void blankInClassBodyNoTrailing() throws FormatterException { assertThat(output).isEqualTo(expect); } - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - private static final String UNORDERED_IMPORTS = Joiner.on('\n') - .join( - "import com.google.common.base.Preconditions;", - "", - "import static org.junit.Assert.fail;", - "import static com.google.truth.Truth.assertThat;", - "", - "import org.junit.runners.JUnit4;", - "import org.junit.runner.RunWith;", - "", - "import java.util.List;", - "", - "import javax.annotations.Nullable;"); + private static final String UNORDERED_IMPORTS = """ + import com.google.common.base.Preconditions; + + import static org.junit.Assert.fail; + import static com.google.truth.Truth.assertThat; + + import org.junit.runners.JUnit4; + import org.junit.runner.RunWith; + + import java.util.List; + + import javax.annotations.Nullable;\ + """; @Test void importsNotReorderedByDefault() throws FormatterException { @@ -178,13 +198,14 @@ void formattingWithoutRemovingUnusedImports() throws IOException, UsageException "com/palantir/javaformat/java/testimports/A.formatting-and-import-sorting"); } - private void importOrdering(String sortArg, String outputResourceName) throws IOException, UsageException { + private void importOrdering(@Nullable String sortArg, String outputResourceName) + throws IOException, UsageException { Path path = testFolder.resolve("Foo.java"); String inputResourceName = "com/palantir/javaformat/java/testimports/A.input"; String input = getResource(inputResourceName); String expectedOutput = getResource(outputResourceName); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -195,14 +216,14 @@ private void importOrdering(String sortArg, String outputResourceName) throws IO assertThat(err.toString()).isEmpty(); assertThat(out.toString()).isEmpty(); - String output = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); + String output = new String(Files.readAllBytes(path), UTF_8); assertThat(output).isEqualTo(expectedOutput); } private String getResource(String resourceName) throws IOException { try (InputStream stream = getClass().getClassLoader().getResourceAsStream(resourceName)) { assertWithMessage("Missing resource: " + resourceName).that(stream).isNotNull(); - return CharStreams.toString(new InputStreamReader(stream, StandardCharsets.UTF_8)); + return CharStreams.toString(new InputStreamReader(stream, UTF_8)); } } @@ -220,19 +241,27 @@ void throwsFormatterException() throws Exception { @Test void blankLinesImportComment() throws FormatterException { - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String withBlank = "package p;\n" - + "\n" - + "/** test */\n" - + "\n" - + "import a.A;\n" - + "\n" - + "class T {\n" - + " A a;\n" - + "}\n"; - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String withoutBlank = - "package p;\n" + "\n" + "/** test */\n" + "import a.A;\n" + "\n" + "class T {\n" + " A a;\n" + "}\n"; + String withBlank = """ + package p; + + /** test */ + + import a.A; + + class T { + A a; + } + """; + String withoutBlank = """ + package p; + + /** test */ + import a.A; + + class T { + A a; + } + """; // Formatting deletes the blank line between the "javadoc" and the first import. assertThat(FORMATTER.formatSource(withBlank)).isEqualTo(withoutBlank); @@ -259,14 +288,15 @@ void canParse_java9_private_interface_methods() { @Test void producesFormattingChangesOnAlreadyFormattedFiles() throws FormatterException { Formatter formatter = FORMATTER; - @SuppressWarnings("for-rollout:StringConcatToTextBlock") - String simpleClass = "package com.palantir;\n" - + "\n" - + "public final class Formatted {\n" - + " public static int count(int number) {\n" - + " return number;\n" - + " }\n" - + "}"; + String simpleClass = """ + package com.palantir; + + public final class Formatted { + public static int count(int number) { + return number; + } + }\ + """; // This is kinda overkill but the point of the test is to show that it // is for sure formatted and still producing a replacement. String formattedClass = formatter.formatSourceAndFixImports(simpleClass); diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/JavaCommentsHelperTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/JavaCommentsHelperTest.java index 59e564baf..cf25955c4 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/JavaCommentsHelperTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/JavaCommentsHelperTest.java @@ -97,6 +97,7 @@ void anUnbreakableTokenIsLeftLong() throws Exception { } @Test + @SuppressWarnings("FormatStringConcatenation") // Written out like the input, not as a template void theMissingSpaceRuleAppliesToEveryLineOfTheRun() throws Exception { // Otherwise the same source formats differently depending on whether the running JDK hands the run // over as one tok (23 and later) or as one tok per line. diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/JavadocFormattingTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/JavadocFormattingTest.java index 80394ce20..0643bfce0 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/JavadocFormattingTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/JavadocFormattingTest.java @@ -1147,7 +1147,6 @@ void unicodeEscapesNotReplaced() { } @Test - @SuppressWarnings("UnicodeEscape") void unicodeEscapesNotInterpretedBug() { /* * In theory, "\u003C" should be treated exactly like <, and so too should the escaped versions of diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/MainTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/MainTest.java index 3f675eac5..47a9f817c 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/MainTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/MainTest.java @@ -439,10 +439,7 @@ void dryRunFiles() throws Exception { assertThat(exitCode).isEqualTo(0); assertThat(out.toString()) - .isEqualTo(b.toAbsolutePath().toString() - + System.lineSeparator() - + c.toAbsolutePath().toString() - + System.lineSeparator()); + .isEqualTo(b.toAbsolutePath() + System.lineSeparator() + c.toAbsolutePath() + System.lineSeparator()); assertThat(err.toString()).isEmpty(); } @@ -483,7 +480,6 @@ void exitIfChangedStdin() throws Exception { Files.write(path, "class Test {\n}\n".getBytes(UTF_8)); Process process = formatterMain("-").redirectInput(path.toFile()).start(); process.waitFor(); - String err = new String(ByteStreams.toByteArray(process.getErrorStream()), UTF_8); String out = new String(ByteStreams.toByteArray(process.getInputStream()), UTF_8); assertThat(out).isEqualTo("" + System.lineSeparator()); assertThat(process.exitValue()).isEqualTo(1); @@ -495,9 +491,8 @@ void exitIfChangedFiles() throws Exception { Files.write(path, "class Test {\n}\n".getBytes(UTF_8)); Process process = formatterMain(path.toAbsolutePath().toString()).start(); process.waitFor(); - String err = new String(ByteStreams.toByteArray(process.getErrorStream()), UTF_8); String out = new String(ByteStreams.toByteArray(process.getInputStream()), UTF_8); - assertThat(out).isEqualTo(path.toAbsolutePath().toString() + System.lineSeparator()); + assertThat(out).isEqualTo(path.toAbsolutePath() + System.lineSeparator()); assertThat(process.exitValue()).isEqualTo(1); } diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/ModuleImportTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/ModuleImportTest.java index e2c7cc43f..96ebbede8 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/ModuleImportTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/ModuleImportTest.java @@ -16,12 +16,12 @@ package com.palantir.javaformat.java; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayInputStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -79,7 +79,7 @@ class Example {} Main main = new Main( new PrintWriter(out, true), new PrintWriter(err, true), - new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8))); + new ByteArrayInputStream(input.getBytes(UTF_8))); int exitCode = main.format("-", "--fix-imports-only", "--skip-removing-unused-imports"); assertThat(err.toString()).isEmpty(); assertThat(exitCode).isZero(); diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/PartialFormattingTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/PartialFormattingTest.java index 3b7e7e250..72be6cf1c 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/PartialFormattingTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/PartialFormattingTest.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -344,7 +343,7 @@ public void testLength() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -373,7 +372,7 @@ public void testLengthRange() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -416,7 +415,7 @@ public void statementAndComments() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -459,7 +458,7 @@ public void statementAndComments2() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -502,7 +501,7 @@ public void statementAndComments3() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -640,7 +639,7 @@ public void noTokensOnLine() throws Exception { "}"); Path path = testFolder.resolve("FormatterException.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -853,7 +852,7 @@ public void lineWithTrailingComment() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -967,7 +966,7 @@ public void outOfRangeStartLine() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -991,7 +990,7 @@ public void outOfRangeEndLine() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -1013,7 +1012,7 @@ public void testOutOfRangeLines() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -1034,7 +1033,7 @@ public void testEmptyFirstLine() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -1053,7 +1052,7 @@ public void testEmptyLastLine() throws Exception { ""); Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -1286,7 +1285,7 @@ public void partialEnum() throws Exception { }; Path path = testFolder.resolve("Foo.java"); - Files.write(path, lines(input).getBytes(StandardCharsets.UTF_8)); + Files.write(path, lines(input).getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -1315,7 +1314,7 @@ public void partialModifierOrder() throws Exception { }; Path path = testFolder.resolve("Foo.java"); - Files.write(path, lines(input).getBytes(StandardCharsets.UTF_8)); + Files.write(path, lines(input).getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -1364,7 +1363,7 @@ public void endOfLine() throws Exception { private String formatMain(String input, String... args) throws Exception { Path path = testFolder.resolve("Test.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); @@ -1497,7 +1496,7 @@ public void b21668189() throws Exception { private String runFormatter(String input, String[] args) throws IOException, UsageException { Path path = testFolder.resolve("Foo.java"); - Files.write(path, input.getBytes(StandardCharsets.UTF_8)); + Files.write(path, input.getBytes(UTF_8)); StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); diff --git a/open-java-format/src/test/java/com/palantir/javaformat/jupiter/ParameterizedClass.java b/open-java-format/src/test/java/com/palantir/javaformat/jupiter/ParameterizedClass.java index 6bd5cf22f..e158dde2a 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/jupiter/ParameterizedClass.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/jupiter/ParameterizedClass.java @@ -167,7 +167,6 @@ public boolean supportsTestTemplate(ExtensionContext _value) { } /** Users must provide a public static Object[][] method, and this invokes it *once*, caching the result. */ - @SuppressWarnings("for-rollout:deprecation") private static List invokeUserParametersMethod(ExtensionContext extensionContext, Class testClass) { List methods = AnnotationUtils.findAnnotatedMethods( testClass, Parameters.class, ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP); @@ -176,11 +175,10 @@ private static List invokeUserParametersMethod(ExtensionContext extens return extensionContext .getStore(namespace) - .getOrComputeIfAbsent( + .computeIfAbsent( "invokeUserParametersMethod", unused -> allParameters(userParametersMethod), List.class); } - @SuppressWarnings("unchecked") private static List allParameters(Method method) { try { Object parameters = method.invoke(null); @@ -204,11 +202,10 @@ private static List allParameters(Method method) { } } - @SuppressWarnings("for-rollout:deprecation") private static String findStringFormatTemplate(ExtensionContext extensionContext, Class testClass) { return extensionContext .getStore(namespace) - .getOrComputeIfAbsent( + .computeIfAbsent( "findStringFormatTemplate", unused -> { List methods = AnnotationUtils.findAnnotatedMethods(