diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 883ef4dee..320bdf1bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: caches/*/transforms - name: Build - run: ./gradlew test + run: ./gradlew check - name: Publish Test Report uses: mikepenz/action-junit-report@4a26df3e2ae132254ba12a53f65a388d0961e786 # v6.7.0 diff --git a/CLAUDE.md b/CLAUDE.md index 3ed0f72fc..e2eada00d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,13 +1,15 @@ # Working in this repository Building and testing: the README's "Building and testing locally" section. Gradle runs on the Temurin 21 that -`mise install` provides, `./gradlew test` is what CI runs, and `./gradlew formatDiff` formats the files you changed. +`mise install` provides, `./gradlew check` is what CI runs, and `./gradlew formatDiff` formats the files you changed. ## Conventions for new code - **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. + unmodifiable collections; unlike Guava's, `Set.of` and `Map.of` do not keep insertion order, and `contains(null)` + on them throws. Guava's `ImmutableList`, `ImmutableMap` and `ImmutableSet` are banned by forbidden-apis + (`config/forbidden-apis`), which fails the build, in every module but the SPI: `FormatterService` keeps returning + `ImmutableList` for compatibility, and the methods that implement it carry their module's `@SuppressForbidden`. - **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 diff --git a/README.md b/README.md index 5ec478a27..5e3d29ef2 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ fixes made the output differ from upstream, that numbering lost its meaning. ```bash mise trust && mise install -./gradlew test # what the CI build job runs +./gradlew check # what the CI build job runs: the tests, Checkstyle and forbidden-apis ``` `-PjavaRuntime=25` runs the same tests on JDK 25, as CI's `jdk` jobs do for 25, 26 and 27, and for diff --git a/build.gradle b/build.gradle index b7bcaa2b9..a387faf52 100644 --- a/build.gradle +++ b/build.gradle @@ -83,6 +83,11 @@ subprojects { // Java toolchains, javac and test settings; Error Prone. Both in buildSrc/src/main/groovy. apply plugin: 'open-java-format.java-conventions' apply plugin: 'open-java-format.error-prone-conventions' + // Bans Guava's immutable collections, but not in the SPI: FormatterService.getFormatReplacements keeps + // returning ImmutableList, so that code compiled against an older SPI still links. + if (path != ':open-java-format-spi') { + apply plugin: 'open-java-format.forbidden-apis-conventions' + } dependencies { // Gives a version to the JUnit artifacts that useJUnitJupiter() adds without one. diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index a7335dad8..a565b5a7e 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -13,5 +13,6 @@ repositories { dependencies { implementation 'net.ltgt.gradle:gradle-errorprone-plugin:5.2.0' implementation 'net.ltgt.gradle:gradle-nullaway-plugin:3.3.0' + implementation 'de.thetaphi:forbiddenapis:3.11' implementation 'org.jreleaser:org.jreleaser.gradle.plugin:1.26.0' } 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 6e798f00e..0b8e66b63 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 @@ -27,6 +27,7 @@ tasks.withType(JavaCompile).configureEach { } error('CanonicalAnnotationSyntax') error('CollectorMutability') + error('DefaultCharset') error('DirectReturn') error('EffectivelyPrivate') error('FormatStringConcatenation') diff --git a/buildSrc/src/main/groovy/open-java-format.forbidden-apis-conventions.gradle b/buildSrc/src/main/groovy/open-java-format.forbidden-apis-conventions.gradle new file mode 100644 index 000000000..c3b6c56ae --- /dev/null +++ b/buildSrc/src/main/groovy/open-java-format.forbidden-apis-conventions.gradle @@ -0,0 +1,13 @@ +// Bans Guava's immutable collections in favour of java.util ones; the list is config/forbidden-apis. +plugins { + id 'java' + id 'de.thetaphi.forbiddenapis' +} + +forbiddenApis { + signaturesFiles = files(rootProject.file('config/forbidden-apis/guava-immutables.txt')) + // A module without Guava on its classpath cannot use the classes anyway. + ignoreSignaturesOfMissingClasses = true + // A module's own package-private SuppressForbidden, so the code does not depend on forbidden-apis. + suppressAnnotations = ['**.SuppressForbidden'] +} diff --git a/config/forbidden-apis/guava-immutables.txt b/config/forbidden-apis/guava-immutables.txt new file mode 100644 index 000000000..8cf6138be --- /dev/null +++ b/config/forbidden-apis/guava-immutables.txt @@ -0,0 +1,4 @@ +@defaultMessage Use java.util collections: List.of, List.copyOf, Map.of, Stream.toList() +com.google.common.collect.ImmutableList +com.google.common.collect.ImmutableMap +com.google.common.collect.ImmutableSet diff --git a/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/PalantirJavaFormatIdeaPlugin.java b/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/PalantirJavaFormatIdeaPlugin.java index 7269badb5..ee02d678a 100644 --- a/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/PalantirJavaFormatIdeaPlugin.java +++ b/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/PalantirJavaFormatIdeaPlugin.java @@ -17,7 +17,6 @@ package com.palantir.javaformat.gradle; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; import java.util.stream.Stream; import org.gradle.StartParameter; import org.gradle.api.Plugin; @@ -80,9 +79,8 @@ public void apply(Project rootProject) { // Adds the tasks to the Gradle start parameters, so they run with whatever the build was asked to do. private static void runWithEveryBuild(Project rootProject, TaskProvider... tasks) { StartParameter startParameter = rootProject.getGradle().getStartParameter(); - startParameter.setTaskNames(ImmutableList.builder() - .addAll(startParameter.getTaskNames()) - .addAll(Stream.of(tasks).map(task -> ":" + task.getName()).toList()) - .build()); + startParameter.setTaskNames(Stream.concat( + startParameter.getTaskNames().stream(), Stream.of(tasks).map(task -> ":" + task.getName())) + .toList()); } } diff --git a/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/XmlUtils.java b/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/XmlUtils.java index d3ba622cd..7225f7414 100644 --- a/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/XmlUtils.java +++ b/gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/XmlUtils.java @@ -16,7 +16,6 @@ package com.palantir.javaformat.gradle; -import com.google.common.collect.ImmutableMap; import com.google.common.io.Files; import groovy.util.Node; import groovy.xml.XmlNodePrinter; @@ -26,6 +25,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.Charset; +import java.util.Map; import java.util.function.Consumer; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; @@ -41,7 +41,7 @@ public static void updateIdeaXmlFile(File configurationFile, Consumer conf throw new RuntimeException("Couldn't parse existing configuration file: " + configurationFile, e); } } else { - rootNode = new Node(null, "project", ImmutableMap.of("version", "4")); + rootNode = new Node(null, "project", Map.of("version", "4")); } configure.accept(rootNode); 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 ec4fb6abd..e38e6b934 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 @@ -22,7 +22,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; @@ -110,7 +109,7 @@ private static void format(FormatterService formatter, SingleFileDiff diff) { try { System.err.println("Formatting " + diff.path); - ImmutableList replacements = formatter.getFormatReplacements(input, charRanges.asRanges()); + List replacements = formatter.getFormatReplacements(input, charRanges.asRanges()); String output = applyReplacements(input, replacements); Files.write(diff.path, output.getBytes(UTF_8)); } catch (IOException | FormatterException e) { @@ -136,8 +135,8 @@ private static String gitCommand(Path dir, String... args) throws IOException, I Preconditions.checkState(process.waitFor(30, TimeUnit.SECONDS), "git diff took too long to terminate"); if (process.exitValue() != 0) { throw new RuntimeException("Expected return code of 0 but got " + process.exitValue() - + "\n stdout: " + new String(process.getInputStream().readAllBytes()) - + "\n stderr: " + new String(process.getErrorStream().readAllBytes())); + + "\n stdout: " + new String(process.getInputStream().readAllBytes(), UTF_8) + + "\n stderr: " + new String(process.getErrorStream().readAllBytes(), UTF_8)); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); process.getInputStream().transferTo(baos); diff --git a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatSpotlessPlugin.java b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatSpotlessPlugin.java index 1b981a18f..11c8a3e63 100644 --- a/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatSpotlessPlugin.java +++ b/gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/PalantirJavaFormatSpotlessPlugin.java @@ -16,7 +16,7 @@ package com.palantir.javaformat.gradle; import com.diffplug.gradle.spotless.SpotlessExtension; -import com.google.common.collect.ImmutableList; +import java.util.List; import org.gradle.api.Action; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -25,8 +25,8 @@ public abstract class PalantirJavaFormatSpotlessPlugin implements Plugin { // The spotless gradle plugin got renamed to 'com.diffplug.spotless' at version 5.0.0 - private static final ImmutableList SPOTLESS_PLUGINS = - ImmutableList.of("com.diffplug.gradle.spotless", "com.diffplug.spotless"); + private static final List SPOTLESS_PLUGINS = + List.of("com.diffplug.gradle.spotless", "com.diffplug.spotless"); @Override public void apply(Project project) { 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 21fdd5075..a0ebb03d2 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 @@ -21,7 +21,6 @@ import com.google.common.base.Preconditions; import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; import com.palantir.javaformat.bootstrap.BootstrappingFormatterService; import com.palantir.javaformat.bootstrap.NativeImageFormatterService; import com.palantir.javaformat.java.FormatterService; @@ -80,10 +79,10 @@ void reformat_a_subpath_of_a_git_directory_for_only_changed_lines(FormatterServi Files.createDirectories(subdir); Path reformatMe = subdir.resolve("ReformatMe.java"); - Files.write(reformatMe, ImmutableList.of(" class ReformatMe {}"), UTF_8); + Files.write(reformatMe, List.of(" class ReformatMe {}"), UTF_8); Path dontTouchMe = repo.resolve("DontTouchMe.java"); - Files.write(dontTouchMe, ImmutableList.of(" class DontTouchMe {}"), UTF_8); + Files.write(dontTouchMe, List.of(" class DontTouchMe {}"), UTF_8); runCommandInRepo("git", "add", "-N", "."); 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 995f53955..83c875cad 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 @@ -14,12 +14,9 @@ package com.palantir.javaformat.java; -import static com.google.common.collect.ImmutableList.toImmutableList; - import com.google.common.base.CharMatcher; import com.google.common.base.Preconditions; import com.google.common.collect.DiscreteDomain; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; @@ -93,7 +90,7 @@ private static List> offsetRanges(List> ranges, in * Runs the Google Java formatter on the given source, with only the given * ranges specified. */ - public ImmutableList format( + public List format( SnippetKind kind, String source, List> ranges, int initialIndent, boolean includeComments) throws FormatterException { RangeSet rangeSet = TreeRangeSet.create(); @@ -115,7 +112,7 @@ public ImmutableList format( return toReplacements(source, replacement).stream() .filter(r -> rangeSet.encloses(r.getReplaceRange())) - .collect(toImmutableList()); + .toList(); } /** 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 abe5dee8a..ccb1c5a8d 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 @@ -16,7 +16,9 @@ package com.palantir.javaformat.intellij; -import com.google.common.collect.ImmutableList; +import static java.util.Comparator.comparing; +import static java.util.Optional.ofNullable; + import com.google.common.collect.Range; import com.intellij.formatting.service.AsyncDocumentFormattingService; import com.intellij.formatting.service.AsyncFormattingRequest; @@ -33,16 +35,12 @@ import com.palantir.javaformat.java.FormatterException; import com.palantir.javaformat.java.FormatterService; import com.palantir.javaformat.java.Replacement; -import org.jspecify.annotations.Nullable; - import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.Set; - -import static java.util.Comparator.comparing; -import static java.util.Optional.ofNullable; +import org.jspecify.annotations.Nullable; class PalantirJavaFormatFormattingService extends AsyncDocumentFormattingService implements PluginAware { private static final Logger logger = Logger.getInstance(PalantirJavaFormatFormattingService.class); @@ -191,12 +189,11 @@ private static Collection> toRanges(AsyncFormattingRequest reques if (isWholeFile(request)) { // The IDE sometimes passes invalid ranges when the file is unsaved before invoking the // formatter. So this is a workaround for that issue. - return ImmutableList.of( - Range.closedOpen(0, request.getDocumentText().length())); + return List.of(Range.closedOpen(0, request.getDocumentText().length())); } return request.getFormattingRanges().stream() .map(textRange -> Range.closedOpen(textRange.getStartOffset(), textRange.getEndOffset())) - .collect(ImmutableList.toImmutableList()); + .toList(); } private static boolean isWholeFile(AsyncFormattingRequest request) { 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 acecabc06..78b14e9ef 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 @@ -29,6 +29,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -51,6 +52,7 @@ public BootstrappingFormatterService(Path jdkPath, Integer jdkMajorVersion, List } @Override + @SuppressForbidden(reason = "FormatterService, kept in the SPI for compatibility, returns ImmutableList") public ImmutableList getFormatReplacements(String input, Collection> ranges) { try { return getFormatReplacementsInternal(input, ranges); @@ -77,6 +79,7 @@ public String fixImports(String input) throws FormatterException { } } + @SuppressForbidden(reason = "FormatterService, kept in the SPI for compatibility, returns ImmutableList") private ImmutableList getFormatReplacementsInternal(String input, Collection> ranges) throws IOException { FormatterCliArgs command = new FormatterCliArgs( @@ -125,27 +128,26 @@ record FormatterCliArgs( List characterRanges) { List toArgs() { - ImmutableList.Builder args = ImmutableList.builder() - .add(jdkPath.toAbsolutePath().toString()) - .addAll(jvmArgs) - .add( - "-cp", - implementationClasspath.stream() - .map(path -> path.toAbsolutePath().toString()) - .collect(Collectors.joining(System.getProperty("path.separator")))) - .add(FORMATTER_MAIN_CLASS); + var args = new ArrayList(); + args.add(jdkPath.toAbsolutePath().toString()); + args.addAll(jvmArgs); + args.add("-cp"); + args.add(implementationClasspath.stream() + .map(path -> path.toAbsolutePath().toString()) + .collect(Collectors.joining(System.getProperty("path.separator")))); + args.add(FORMATTER_MAIN_CLASS); if (!characterRanges.isEmpty()) { - args.add("--character-ranges", Joiner.on(',').join(characterRanges)); + args.add("--character-ranges"); + args.add(Joiner.on(',').join(characterRanges)); } if (outputReplacements) { args.add("--output-replacements"); } - return args - // Trailing "-" enables formatting stdin -> stdout - .add("-") - .build(); + // Trailing "-" enables formatting stdin -> stdout + args.add("-"); + return List.copyOf(args); } } } 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 cfe4e102d..25b08fdff 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 @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -42,6 +43,7 @@ public NativeImageFormatterService(Path nativeImagePath) { } @Override + @SuppressForbidden(reason = "FormatterService, kept in the SPI for compatibility, returns ImmutableList") public ImmutableList getFormatReplacements(String input, Collection> ranges) { Optional output = Optional.empty(); try { @@ -91,20 +93,20 @@ private String runFormatterCommand(String input) throws IOException { record FormatterNativeImageArgs(Path nativeImagePath, boolean outputReplacements, List characterRanges) { List toArgs() { - ImmutableList.Builder args = ImmutableList.builder() - .add(nativeImagePath.toAbsolutePath().toString()); + var args = new ArrayList(); + args.add(nativeImagePath.toAbsolutePath().toString()); if (!characterRanges.isEmpty()) { - args.add("--character-ranges", Joiner.on(',').join(characterRanges)); + args.add("--character-ranges"); + args.add(Joiner.on(',').join(characterRanges)); } if (outputReplacements) { args.add("--output-replacements"); } - return args - // Trailing "-" enables formatting stdin -> stdout - .add("-") - .build(); + // Trailing "-" enables formatting stdin -> stdout + args.add("-"); + return List.copyOf(args); } } } diff --git a/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/SuppressForbidden.java b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/SuppressForbidden.java new file mode 100644 index 000000000..61f1fa598 --- /dev/null +++ b/open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/SuppressForbidden.java @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.palantir.javaformat.bootstrap; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Lets forbidden-apis accept a use of an API that config/forbidden-apis bans, for the reason given. */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) +@interface SuppressForbidden { + String reason(); +} 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 7626cf4ee..5821fade2 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 @@ -20,7 +20,6 @@ import com.google.common.base.Preconditions; import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Range; import com.palantir.javaformat.Utils; import com.palantir.javaformat.java.FormatterException; @@ -44,7 +43,7 @@ void can_format_file_with_replacement(FormatterService formatterService) throws String input = getTestResourceContent("format.input"); String expectedOutput = getTestResourceContent("format.output"); - ImmutableList replacements = + List replacements = formatterService.getFormatReplacements(input, List.of(Range.open(0, input.length()))); assertThat(replacements).hasSize(1); @@ -73,7 +72,7 @@ void can_format_large_input_file(FormatterService formatterService) throws Forma + " }\n" + "}\n"; - ImmutableList replacements = + List replacements = formatterService.getFormatReplacements(input, List.of(Range.open(0, input.length()))); assertThat(replacements).singleElement().satisfies(replacement -> { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/FormattingError.java b/open-java-format/src/main/java/com/palantir/javaformat/FormattingError.java index 6e67022a1..b6cab0146 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/FormattingError.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/FormattingError.java @@ -15,24 +15,26 @@ package com.palantir.javaformat; import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; import com.palantir.javaformat.java.FormatterDiagnostic; +import java.util.List; +import java.util.stream.StreamSupport; /** An unchecked formatting error. */ public class FormattingError extends RuntimeException { - private final ImmutableList diagnostics; + private final List diagnostics; public FormattingError(FormatterDiagnostic diagnostic) { - this(ImmutableList.of(diagnostic)); + this(List.of(diagnostic)); } public FormattingError(Iterable diagnostics) { super(Joiner.on("\n").join(diagnostics) + "\n"); - this.diagnostics = ImmutableList.copyOf(diagnostics); + this.diagnostics = + StreamSupport.stream(diagnostics.spliterator(), false).toList(); } - public ImmutableList diagnostics() { + public List diagnostics() { return diagnostics; } } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/Input.java b/open-java-format/src/main/java/com/palantir/javaformat/Input.java index e114e28a4..36a757364 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/Input.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/Input.java @@ -15,11 +15,11 @@ package com.palantir.javaformat; import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableRangeMap; +import com.google.common.collect.RangeMap; import com.google.errorprone.annotations.Immutable; import com.palantir.javaformat.java.FormatterDiagnostic; +import java.util.List; +import java.util.Map; /** An input to the formatter. */ public abstract class Input extends InputOutput { @@ -77,7 +77,6 @@ public interface Tok { } /** A {@code Token} is a language-level token. */ - @Immutable public interface Token { /** * Get the token's {@link Tok}. @@ -91,14 +90,14 @@ public interface Token { * * @return the earlier {@link Tok}s assigned to this {@code Token} */ - ImmutableList getToksBefore(); + List getToksBefore(); /** * Get the later {@link Tok}s assigned to this {@code Token}. * * @return the later {@link Tok}s assigned to this {@code Token} */ - ImmutableList getToksAfter(); + List getToksAfter(); } /** @@ -106,12 +105,12 @@ public interface Token { * * @return the input tokens */ - public abstract ImmutableList getTokens(); + public abstract List getTokens(); /** A map from [start, end] position ranges to {@link Token}s. */ - public abstract ImmutableRangeMap getPositionTokenMap(); + public abstract RangeMap getPositionTokenMap(); - public abstract ImmutableMap getPositionToColumnMap(); + public abstract Map getPositionToColumnMap(); public abstract String getText(); diff --git a/open-java-format/src/main/java/com/palantir/javaformat/InputOutput.java b/open-java-format/src/main/java/com/palantir/javaformat/InputOutput.java index f5c95fc22..642bda60c 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/InputOutput.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/InputOutput.java @@ -15,7 +15,6 @@ package com.palantir.javaformat; import com.google.common.collect.DiscreteDomain; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Range; import java.util.ArrayList; import java.util.HashMap; @@ -24,13 +23,13 @@ /** This interface defines methods common to an {@link Input} or an {@link Output}. */ public abstract class InputOutput { - private ImmutableList lines = ImmutableList.of(); + private List lines = List.of(); protected static final Range EMPTY_RANGE = Range.closedOpen(-1, -1); private static final DiscreteDomain INTEGERS = DiscreteDomain.integers(); /** Set the lines. */ - protected final void setLines(ImmutableList lines) { + protected final void setLines(List lines) { this.lines = lines; } @@ -53,7 +52,10 @@ public final String getLine(int lineI) { return lines.get(lineI); } - /** The {@link Range}s of the tokens or comments lying on each line, in any part. */ + /** + * The {@link Range}s of the tokens or comments lying on each line, in any part: a {@code /*} comment can lie on + * several. With the same for the formatted output, they give the correspondence between input and output lines. + */ protected final List> ranges = new ArrayList<>(); private static void addToRanges(List> ranges, int i, int k) { 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 4f9eed64b..a8a95ab28 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 @@ -15,9 +15,9 @@ package com.palantir.javaformat; import com.google.common.base.CharMatcher; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterators; import java.util.Iterator; +import java.util.List; import java.util.NoSuchElementException; import org.jspecify.annotations.Nullable; @@ -36,7 +36,8 @@ public static int firstBreak(String input) { return it.hasNext() ? it.next() : -1; } - private static final ImmutableSet BREAKS = ImmutableSet.of("\r\n", "\n", "\r"); + // Ordered: "\r\n" has to be tried before "\r" and "\n". + private static final List BREAKS = List.of("\r\n", "\n", "\r"); /** Returns true if the entire input string is a recognized line break. */ public static boolean isNewline(String input) { 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 25234ff67..eb6682dc5 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 @@ -19,10 +19,8 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; -import com.google.errorprone.annotations.Immutable; import com.palantir.javaformat.Indent.Const; import com.palantir.javaformat.Input.Tok; import com.palantir.javaformat.doc.Break; @@ -45,6 +43,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.StreamSupport; /** An {@code OpsBuilder} creates a list of {@link Op}s, which is turned into a {@link Doc} by {@link DocBuilder}. */ public final class OpsBuilder { @@ -85,7 +84,6 @@ public Integer actualStartColumn(int position) { } /** A request to add or remove a blank line in the output. */ - @Immutable public abstract static class BlankLineWanted { /** Always emit a blank line. */ @@ -108,7 +106,7 @@ public abstract static class BlankLineWanted { /** Emit a blank line if the given break is taken. */ public static BlankLineWanted conditional(BreakTag breakTag) { - return new ConditionalBlankLine(ImmutableList.of(breakTag)); + return new ConditionalBlankLine(List.of(breakTag)); } private static final class SimpleBlankLine extends BlankLineWanted { @@ -131,10 +129,10 @@ public BlankLineWanted merge(BlankLineWanted other) { private static final class ConditionalBlankLine extends BlankLineWanted { - private final ImmutableList tags; + private final List tags; ConditionalBlankLine(Iterable tags) { - this.tags = ImmutableList.copyOf(tags); + this.tags = StreamSupport.stream(tags.spliterator(), false).toList(); } @Override @@ -233,7 +231,7 @@ public FormatterDiagnostic diagnostic(String message) { */ public void sync(int inputPosition) { if (inputPosition > this.inputPosition) { - ImmutableList tokens = input.getTokens(); + List tokens = input.getTokens(); int tokensN = tokens.size(); this.inputPosition = inputPosition; if (tokenI < tokensN && inputPosition > tokens.get(tokenI).getTok().getPosition()) { @@ -249,7 +247,7 @@ public void sync(int inputPosition) { public void drain() { int inputPosition = input.getText().length() + 1; if (inputPosition > this.inputPosition) { - ImmutableList tokens = input.getTokens(); + List tokens = input.getTokens(); int tokensN = tokens.size(); while (tokenI < tokensN && inputPosition > tokens.get(tokenI).getTok().getPosition()) { @@ -341,7 +339,7 @@ public boolean mostRecentTokenFollowedByNewline() { /** Return the text of an upcoming {@link Input.Token}, or absent if there is none. */ public Optional peekToken(int skip) { - ImmutableList tokens = input.getTokens(); + List tokens = input.getTokens(); int idx = tokenI + skip; return idx < tokens.size() ? Optional.of(tokens.get(idx).getTok().getOriginalText()) : Optional.empty(); } @@ -361,7 +359,7 @@ public void token( Token.RealOrImaginary realOrImaginary, Indent plusIndentCommentsBefore, Optional breakAndIndentTrailingComment) { - ImmutableList tokens = input.getTokens(); + List tokens = input.getTokens(); if (token.equals(peekToken().orElse(null))) { // Found the input token. Output it. add(Token.make( tokens.get(tokenI++), @@ -521,7 +519,7 @@ private static int getI(Input.Token token) { private static final NonBreakingSpace SPACE = NonBreakingSpace.make(); - public record OpsOutput(ImmutableList ops, InputMetadata inputMetadata) {} + public record OpsOutput(List ops, InputMetadata inputMetadata) {} /** Build a list of {@link Op}s from the {@code OpsBuilder}. */ public OpsOutput build() { @@ -677,7 +675,7 @@ public OpsOutput build() { * Construct new list of ops, splicing in the comments. If a comment is inserted immediately * before a space, suppress the space. */ - ImmutableList.Builder newOps = ImmutableList.builder(); + var newOps = new ArrayList(); boolean afterForcedBreak = false; // Was the last Op a forced break? If so, suppress spaces. for (int i = 0; i < opsN; i++) { newOps.addAll(reservations.get(i)); @@ -709,7 +707,7 @@ public OpsOutput build() { afterForcedBreak = isForcedBreak(op); } } - return new OpsOutput(newOps.build(), inputMetadataBuilder.build()); + return new OpsOutput(List.copyOf(newOps), inputMetadataBuilder.build()); } private static boolean isNonNlsComment(Input.Tok tokAfter) { 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 176616b06..5b69d4507 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 @@ -21,7 +21,6 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Range; import com.palantir.javaformat.BreakBehaviour; import com.palantir.javaformat.BreakBehaviour.BreakOnlyIfInnerLevelsThenFitOnOneLine; @@ -661,20 +660,20 @@ private State tryToLayOutLevelOnOneLine( } private static SplitsBreaks splitByBreaks(List docs) { - ImmutableList.Builder> splits = ImmutableList.builder(); - ImmutableList.Builder breaks = ImmutableList.builder(); - ImmutableList.Builder currentSplit = ImmutableList.builder(); + var splits = new ArrayList>(); + var breaks = new ArrayList(); + var currentSplit = new ArrayList(); for (Doc doc : docs) { if (doc instanceof Break b) { - splits.add(currentSplit.build()); - currentSplit = ImmutableList.builder(); + splits.add(List.copyOf(currentSplit)); + currentSplit = new ArrayList<>(); breaks.add(b); } else { currentSplit.add(doc); } } - splits.add(currentSplit.build()); - return new SplitsBreaks(splits.build(), breaks.build()); + splits.add(List.copyOf(currentSplit)); + return new SplitsBreaks(List.copyOf(splits), List.copyOf(breaks)); } /** Compute breaks for a {@link Level} that spans multiple lines. */ @@ -686,7 +685,7 @@ private State computeBroken( state = state.withBrokenLevel(); } - ImmutableList splitDocs = splitsBreaks.splits().get(0); + List splitDocs = splitsBreaks.splits().get(0); state = computeBreakAndSplit( commentsHelper, maxWidth, state, /* optBreakDoc= */ Optional.empty(), splitDocs, explorationNode); @@ -874,5 +873,5 @@ public String toString() { * @param splits groups of {@link Doc}s that are children of the current level, separated by breaks * @param breaks the breaks between those groups */ - record SplitsBreaks(ImmutableList> splits, ImmutableList breaks) {} + record SplitsBreaks(List> splits, List breaks) {} } diff --git a/open-java-format/src/main/java/com/palantir/javaformat/doc/Token.java b/open-java-format/src/main/java/com/palantir/javaformat/doc/Token.java index 0f2078cc5..6a55d3bbd 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/doc/Token.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/doc/Token.java @@ -18,7 +18,6 @@ import com.google.common.base.MoreObjects; import com.google.common.collect.Range; -import com.google.errorprone.annotations.Immutable; import com.palantir.javaformat.CommentsHelper; import com.palantir.javaformat.Indent; import com.palantir.javaformat.Input; @@ -28,7 +27,6 @@ import java.util.Optional; /** A leaf {@link Doc} for a token. */ -@Immutable public final class Token extends Doc implements Op { /** Is a Token a real token, or imaginary (e.g., a token generated incorrectly, or an EOF)? */ public enum RealOrImaginary { diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptions.java b/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptions.java index f36722b94..b0797c203 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptions.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/CommandLineOptions.java @@ -14,10 +14,11 @@ package com.palantir.javaformat.java; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableRangeSet; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; /** @@ -27,13 +28,13 @@ */ final class CommandLineOptions { - private final ImmutableList files; + private final List files; private final boolean inPlace; private final ImmutableRangeSet lines; private final ImmutableRangeSet characterRanges; - private final ImmutableList offsets; - private final ImmutableList lengths; - private final ImmutableList unsupportedFlags; + private final List offsets; + private final List lengths; + private final List unsupportedFlags; private final boolean version; private final boolean help; private final boolean stdin; @@ -47,13 +48,13 @@ final class CommandLineOptions { private final boolean outputReplacements; CommandLineOptions( - ImmutableList files, + List files, boolean inPlace, ImmutableRangeSet lines, ImmutableRangeSet characterRanges, - ImmutableList offsets, - ImmutableList lengths, - ImmutableList unsupportedFlags, + List offsets, + List lengths, + List unsupportedFlags, boolean version, boolean help, boolean stdin, @@ -86,7 +87,7 @@ final class CommandLineOptions { } /** The files to format. */ - ImmutableList files() { + List files() { return files; } @@ -106,17 +107,17 @@ ImmutableRangeSet characterRanges() { } /** Character offsets for partial formatting, paired with {@code lengths}. */ - ImmutableList offsets() { + List offsets() { return offsets; } /** Partial formatting region lengths, paired with {@code offsets}. */ - ImmutableList lengths() { + List lengths() { return lengths; } /** Flags that are accepted and ignored, in the order they were given: the style flags of earlier versions. */ - ImmutableList unsupportedFlags() { + List unsupportedFlags() { return unsupportedFlags; } @@ -184,14 +185,14 @@ static Builder builder() { static final class Builder { - private final ImmutableList.Builder files = ImmutableList.builder(); + private final List files = new ArrayList<>(); // A TreeRangeSet merges ranges that touch or overlap, which ImmutableRangeSet.Builder rejects private final RangeSet lines = TreeRangeSet.create(); private final ImmutableRangeSet.Builder characterRanges = ImmutableRangeSet.builder(); - private final ImmutableList.Builder offsets = ImmutableList.builder(); - private final ImmutableList.Builder lengths = ImmutableList.builder(); + private final List offsets = new ArrayList<>(); + private final List lengths = new ArrayList<>(); private boolean inPlace = false; - private final ImmutableList.Builder unsupportedFlags = ImmutableList.builder(); + private final List unsupportedFlags = new ArrayList<>(); private boolean version = false; private boolean help = false; private boolean stdin = false; @@ -206,7 +207,7 @@ static final class Builder { private Builder() {} - ImmutableList.Builder filesBuilder() { + List files() { return files; } @@ -295,13 +296,13 @@ Builder outputReplacements(boolean outputReplacements) { CommandLineOptions build() { return new CommandLineOptions( - files.build(), + List.copyOf(files), inPlace, ImmutableRangeSet.copyOf(lines), characterRanges.build(), - offsets.build(), - lengths.build(), - unsupportedFlags.build(), + List.copyOf(offsets), + List.copyOf(lengths), + List.copyOf(unsupportedFlags), version, help, stdin, 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 658833405..92025322c 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 @@ -63,7 +63,9 @@ static CommandLineOptions parse(Iterable options) { while (it.hasNext()) { String option = it.next(); if (!option.startsWith("-")) { - optionsBuilder.filesBuilder().add(option).addAll(it); + var files = optionsBuilder.files(); + files.add(option); + it.forEachRemaining(files::add); break; } String flag; 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 11656fb8c..2091ae280 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 @@ -22,7 +22,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.collect.ImmutableList; import com.google.common.hash.Hashing; import com.palantir.javaformat.CloseOp; import com.palantir.javaformat.Input; @@ -42,6 +41,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import java.util.stream.Collectors; public class DebugRenderer { @@ -96,7 +96,7 @@ private static String outputAsString(JavaOutput javaOutput) { private static String opsJson(OpsOutput opsOutput) { ArrayNode arrayNode = OBJECT_MAPPER.createArrayNode(); - ImmutableList ops = opsOutput.ops(); + List ops = opsOutput.ops(); for (Op op : ops) { if (op instanceof Token token) { Input.Token inputToken = token.getToken(); 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 3e01962d6..ab5d38011 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 @@ -14,7 +14,6 @@ package com.palantir.javaformat.java; -import com.google.common.collect.ImmutableList; import com.sun.source.tree.AnnotatedTypeTree; import com.sun.source.tree.AnnotationTree; import com.sun.source.tree.ArrayTypeTree; @@ -22,6 +21,7 @@ import com.sun.tools.javac.tree.JCTree; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Deque; import java.util.List; @@ -42,9 +42,9 @@ static class TypeWithDims { @Nullable final Tree node; - final ImmutableList> dims; + final List> dims; - public TypeWithDims(@Nullable Tree node, ImmutableList> dims) { + public TypeWithDims(@Nullable Tree node, List> dims) { this.node = node; this.dims = dims; } @@ -59,13 +59,13 @@ enum SortedDims { static TypeWithDims extractDims(Tree node, SortedDims sorted) { Deque> builder = new ArrayDeque<>(); node = extractDims(builder, node); - Iterable> dims; + Collection> dims; if (sorted == SortedDims.YES) { dims = reorderBySourcePosition(builder); } else { dims = builder; } - return new TypeWithDims(node, ImmutableList.copyOf(dims)); + return new TypeWithDims(node, List.copyOf(dims)); } /** @@ -79,7 +79,7 @@ static TypeWithDims extractDims(Tree node, SortedDims sorted) { *

This doesn't handle cases with un-annotated dimension specifiers, so the formatting logic checks the token * stream to figure out which side of the method name they appear on. */ - private static Iterable> reorderBySourcePosition(Deque> dims) { + private static Collection> reorderBySourcePosition(Deque> dims) { int lastAnnotation = -1; int lastPos = -1; int idx = 0; @@ -113,7 +113,7 @@ private static Tree extractDims(Deque> dims, Tree node) { yield node; } node = extractDims(dims, annotatedTypeTree.getUnderlyingType()); - dims.addFirst(ImmutableList.copyOf(annotatedTypeTree.getAnnotations())); + dims.addFirst(List.copyOf(annotatedTypeTree.getAnnotations())); yield 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 8e05831d7..c3da6ce96 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 @@ -17,7 +17,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; @@ -212,7 +211,7 @@ static JCCompilationUnit parseJcCompilationUnit(Context context, String sourceTe JCCompilationUnit unit; JavacFileManager fileManager = new JavacFileManager(context, true, UTF_8); try { - fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, ImmutableList.of()); + fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, List.of()); } catch (IOException e) { // impossible throw new UncheckedIOException(e); @@ -291,7 +290,7 @@ public void formatSource(CharSource input, CharSink output) throws FormatterExce * @throws FormatterException if the input string cannot be parsed */ public String formatSource(String input) throws FormatterException { - return formatSource(input, ImmutableList.of(Range.closedOpen(0, input.length()))); + return formatSource(input, List.of(Range.closedOpen(0, input.length()))); } /** @@ -346,7 +345,7 @@ public String formatSource(String input, Collection> characterRan * @return a list of {@link Replacement}s, sorted from low index to high index, without overlaps * @throws FormatterException if the input string cannot be parsed */ - public ImmutableList getFormatReplacements(String input, Collection> characterRanges) + public List getFormatReplacements(String input, Collection> characterRanges) throws FormatterException { JavaInput javaInput = new JavaInput(input); diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/FormatterServiceImpl.java b/open-java-format/src/main/java/com/palantir/javaformat/java/FormatterServiceImpl.java index 75f7c9011..08681da2e 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/FormatterServiceImpl.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/FormatterServiceImpl.java @@ -33,9 +33,10 @@ public FormatterServiceImpl() { } @Override + @SuppressForbidden(reason = "FormatterService, kept in the SPI for compatibility, returns ImmutableList") public ImmutableList getFormatReplacements(String text, Collection> toRanges) throws FormatterException { - return formatter.getFormatReplacements(text, toRanges); + return ImmutableList.copyOf(formatter.getFormatReplacements(text, toRanges)); } @Override 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 02963dcc3..774aac031 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 @@ -21,16 +21,17 @@ import com.google.common.base.CharMatcher; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; import com.palantir.javaformat.Newlines; import com.palantir.javaformat.java.JavaInput.Tok; import com.sun.tools.javac.parser.Tokens.TokenKind; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.function.BiFunction; import java.util.stream.Stream; @@ -46,7 +47,7 @@ public final class ImportOrderer { * @throws FormatterException if the input could not be parsed. */ public static String reorderImports(String text, Style style) throws FormatterException { - ImmutableList toks = buildToks(text, CLASS_START); + List toks = buildToks(text, CLASS_START); return new ImportOrderer(text, toks, style).reorderImports(); } @@ -108,16 +109,14 @@ private String reorderImports() throws FormatterException { * {@link TokenKind}s that indicate the start of a type definition. We use this to avoid scanning the whole file, * since we know that imports must precede any type definition. */ - private static final ImmutableSet CLASS_START = - ImmutableSet.of(TokenKind.CLASS, TokenKind.INTERFACE, TokenKind.ENUM); + private static final Set CLASS_START = Set.of(TokenKind.CLASS, TokenKind.INTERFACE, TokenKind.ENUM); /** * We use this set to find the first import, and again to check that there are no imports after the place we stopped * gathering them. An annotation definition ({@code @interface}) is two tokens, the second which is * {@code interface}, so we don't need a separate entry for that. */ - private static final ImmutableSet IMPORT_OR_CLASS_START = - ImmutableSet.of("import", "class", "interface", "enum"); + private static final Set IMPORT_OR_CLASS_START = Set.of("import", "class", "interface", "enum"); /** * A {@link Comparator} that orders {@link Import}s by Google Style, defined at @@ -176,13 +175,13 @@ private static boolean shouldInsertBlankLineAosp(Import prev, Import curr) { } private final String text; - private final ImmutableList toks; + private final List toks; private final String lineSeparator; private final Comparator importComparator; private final BiFunction shouldInsertBlankLineFn; @SuppressWarnings("deprecation") - private ImportOrderer(String text, ImmutableList toks, Style style) { + private ImportOrderer(String text, List toks, Style style) { this.text = text; this.toks = toks; this.lineSeparator = Newlines.guessLineSeparator(text); @@ -347,10 +346,10 @@ private String tokString(int start, int end) { } private static class ImportsAndIndex { - final ImmutableSortedSet imports; + final SortedSet imports; final int index; - ImportsAndIndex(ImmutableSortedSet imports, int index) { + ImportsAndIndex(SortedSet imports, int index) { this.imports = imports; this.index = index; } @@ -376,7 +375,7 @@ private static class ImportsAndIndex { */ private ImportsAndIndex scanImports(int i) throws FormatterException { int afterLastImport = i; - ImmutableSortedSet.Builder imports = ImmutableSortedSet.orderedBy(importComparator); + var imports = new TreeSet(importComparator); String leading = ""; // JavaInput.buildToks appends a zero-width EOF token after all tokens. It won't match any // of our tests here and protects us from running off the end of the toks list. Since it is @@ -457,11 +456,11 @@ private ImportsAndIndex scanImports(int i) throws FormatterException { i = next; } } - return new ImportsAndIndex(imports.build(), afterLastImport); + return new ImportsAndIndex(Collections.unmodifiableSortedSet(imports), afterLastImport); } // Produces the sorted output based on the imports we have scanned. - private String reorderedImportsString(ImmutableSortedSet imports) { + private String reorderedImportsString(SortedSet imports) { Preconditions.checkArgument(!imports.isEmpty(), "imports"); // Pretend that the first import was preceded by another import of the same kind, so we don't @@ -538,7 +537,7 @@ private StringAndIndex scanImported(int start, Declaration declaration) throws F * @param start the index to start looking at * @param identifiers the identifiers to look for */ - private Optional findIdentifier(int start, ImmutableSet identifiers) { + private Optional findIdentifier(int start, Set identifiers) { for (int i = start; i < toks.size(); i++) { if (isIdentifierToken(i)) { String id = tokenAt(i); diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadata.java b/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadata.java index feeb1307c..16303ae09 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadata.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/InputMetadata.java @@ -15,10 +15,9 @@ */ package com.palantir.javaformat.java; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableRangeSet; -import com.google.errorprone.annotations.Immutable; import com.palantir.javaformat.OpsBuilder.BlankLineWanted; +import java.util.Map; /** * Records metadata about the input, namely existing blank lines that we might want to preserve, as well as what ranges @@ -29,6 +28,4 @@ * @param partialFormatRanges marks regions that can be partially formatted, used to determine the actual ranges that * will be formatted when ranges are requested */ -@Immutable -public record InputMetadata( - ImmutableMap blankLines, ImmutableRangeSet partialFormatRanges) {} +public record InputMetadata(Map blankLines, ImmutableRangeSet partialFormatRanges) {} 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 6ded45a09..0a23d41a2 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 @@ -15,7 +15,6 @@ */ package com.palantir.javaformat.java; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableRangeSet; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; @@ -58,6 +57,6 @@ public Range regionContaining(int k) { } public InputMetadata build() { - return new InputMetadata(ImmutableMap.copyOf(blankLines), ImmutableRangeSet.copyOf(partialFormatRanges)); + return new InputMetadata(Map.copyOf(blankLines), ImmutableRangeSet.copyOf(partialFormatRanges)); } } 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 1a2de78d9..1a75378db 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 @@ -15,7 +15,6 @@ package com.palantir.javaformat.java; import com.google.common.base.CharMatcher; -import com.google.common.collect.ImmutableSet; import com.palantir.javaformat.CommentsHelper; import com.palantir.javaformat.Input.Tok; import com.palantir.javaformat.Newlines; @@ -23,6 +22,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jspecify.annotations.Nullable; @@ -131,7 +131,7 @@ private boolean isJBangHeaderLine(Tok tok) { } // The directive names JBang knows, from dev.jbang.source.parser.Directives.Names. - private static final ImmutableSet JBANG_DIRECTIVE_NAMES = ImmutableSet.of( + private static final Set JBANG_DIRECTIVE_NAMES = Set.of( "CDS", "COMPILE_OPTIONS", "DEPS", 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 e46b20818..cb946f05d 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 @@ -22,13 +22,10 @@ import com.google.common.base.Suppliers; import com.google.common.base.Verify; import com.google.common.collect.DiscreteDomain; -import com.google.common.collect.ImmutableCollection; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableRangeMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterators; import com.google.common.collect.Range; +import com.google.common.collect.RangeMap; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; import com.google.errorprone.annotations.Immutable; @@ -48,9 +45,13 @@ import java.net.URI; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.DiagnosticListener; @@ -197,11 +198,10 @@ public TokenKind kind() { * {@link Tok}s, each preceded by the texts of its {@code toksBefore} and followed by the texts of its * {@code toksAfter}, equals the input. */ - @Immutable static final class Token implements Input.Token { private final Tok tok; - private final ImmutableList toksBefore; - private final ImmutableList toksAfter; + private final List toksBefore; + private final List toksAfter; /** * Token constructor. @@ -211,9 +211,9 @@ static final class Token implements Input.Token { * @param toksAfter the later non-token {link Tok}s assigned to this {@code Token} */ Token(List toksBefore, Tok tok, List toksAfter) { - this.toksBefore = ImmutableList.copyOf(toksBefore); + this.toksBefore = List.copyOf(toksBefore); this.tok = tok; - this.toksAfter = ImmutableList.copyOf(toksAfter); + this.toksAfter = List.copyOf(toksAfter); } /** @@ -232,7 +232,7 @@ public Tok getTok() { * @return the earlier {@link Tok}s assigned to this {@code Token} */ @Override - public ImmutableList getToksBefore() { + public List getToksBefore() { return toksBefore; } @@ -242,7 +242,7 @@ public ImmutableList getToksBefore() { * @return the later {@link Tok}s assigned to this {@code Token} */ @Override - public ImmutableList getToksAfter() { + public List getToksAfter() { return toksAfter; } @@ -260,17 +260,9 @@ public String toString() { private final Supplier lineSeparator = Suppliers.memoize(() -> Newlines.guessLineSeparator(getText())); private int kN; // The number of numbered toks (tokens or comments), excluding the EOF. - /* - * The following lists record the sequential indices of the {@code Tok}s on each input line. (Only - * tokens and comments have sequential indices.) Tokens and {@code //} comments lie on just one - * line; {@code /*} comments can lie on multiple lines. These data structures (along with - * equivalent ones for the formatted output) let us compute correspondences between the input and - * output. - */ - - private final ImmutableMap positionToColumnMap; // Map Tok position to column. + private final Map positionToColumnMap; // Map Tok position to column. - private final ImmutableList tokens; // The Tokens for this input. + private final List tokens; // The Tokens for this input. private final ImmutableRangeMap positionTokenMap; // Map position to Token. /** Map from Tok index to the associated Token. */ @@ -284,8 +276,10 @@ public String toString() { */ public JavaInput(String text) throws FormatterException { this.text = checkNotNull(text); - setLines(ImmutableList.copyOf(Newlines.lineIterator(text))); - ImmutableList toks = buildToks(text); + var lines = new ArrayList(); + Newlines.lineIterator(text).forEachRemaining(lines::add); + setLines(List.copyOf(lines)); + List toks = buildToks(text); positionToColumnMap = makePositionToColumnMap(toks); tokens = buildTokens(toks); ImmutableRangeMap.Builder tokenLocations = ImmutableRangeMap.builder(); @@ -318,12 +312,8 @@ public JavaInput(String text) throws FormatterException { } } - private static ImmutableMap makePositionToColumnMap(List toks) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Tok tok : toks) { - builder.put(tok.getPosition(), tok.getColumn()); - } - return builder.buildOrThrow(); + private static Map makePositionToColumnMap(List toks) { + return toks.stream().collect(Collectors.toUnmodifiableMap(Tok::getPosition, Tok::getColumn)); } /** @@ -337,7 +327,7 @@ public String getText() { } @Override - public ImmutableMap getPositionToColumnMap() { + public Map getPositionToColumnMap() { return positionToColumnMap; } @@ -346,8 +336,8 @@ public String getLineSeparator() { } /** Lex the input and build the list of toks. */ - private ImmutableList buildToks(String text) throws FormatterException { - ImmutableList toks = buildToks(text, ImmutableSet.of()); + private List buildToks(String text) throws FormatterException { + List toks = buildToks(text, Set.of()); kN = getLast(toks).getIndex(); computeRanges(toks); return toks; @@ -360,11 +350,9 @@ 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. */ - static ImmutableList buildToks(String text, ImmutableSet stopTokens) throws FormatterException { - stopTokens = ImmutableSet.builder() - .addAll(stopTokens) - .add(TokenKind.EOF) - .build(); + static List buildToks(String text, Set stopTokens) throws FormatterException { + var stopAt = new HashSet<>(stopTokens); + stopAt.add(TokenKind.EOF); Context context = new Context(); Options.instance(context).put("--enable-preview", "true"); new JavacFileManager(context, true, UTF_8); @@ -378,16 +366,16 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept } }); DeferredDiagnosticHandler diagnostics = new DeferredDiagnosticHandler(log); - ImmutableList rawToks = JavacTokens.getTokens(text, context, stopTokens); + List rawToks = JavacTokens.getTokens(text, context, stopAt); if (getDiagnostics(diagnostics).stream().anyMatch(d -> d.getKind() == Diagnostic.Kind.ERROR)) { - return ImmutableList.of(new Tok(0, "", "", 0, 0, true, null)); // EOF + return List.of(new Tok(0, "", "", 0, 0, true, null)); // EOF } int kN = 0; List toks = new ArrayList<>(); int charI = 0; int columnI = 0; for (RawTok t : rawToks) { - if (stopTokens.contains(t.kind())) { + if (stopAt.contains(t.kind())) { break; } int charI0 = t.pos(); @@ -476,7 +464,7 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept } } toks.add(new Tok(kN, "", "", charI, columnI, true, null)); // EOF tok. - return ImmutableList.copyOf(toks); + return List.copyOf(toks); } /** @@ -564,13 +552,13 @@ private static int updateColumn(int columnI, String originalTokText) { return columnI; } - private static ImmutableList buildTokens(List toks) { - ImmutableList.Builder tokens = ImmutableList.builder(); + private static List buildTokens(List toks) { + var tokens = new ArrayList(); int k = 0; int kN = toks.size(); // Remaining non-tokens before the token go here. - ImmutableList.Builder toksBefore = ImmutableList.builder(); + var toksBefore = new ArrayList(); OUTERMOST: while (k < kN) { @@ -587,7 +575,7 @@ private static ImmutableList buildTokens(List toks) { Tok tok = toks.get(k++); // Non-tokens starting on the same line go here too. - ImmutableList.Builder toksAfter = ImmutableList.builder(); + var toksAfter = new ArrayList(); OUTER: while (k < kN && !toks.get(k).isToken()) { // Don't attach inline comments to certain leading tokens, e.g. for `f(/*flag1=*/true). @@ -614,8 +602,9 @@ private static ImmutableList buildTokens(List toks) { } } if (isParamComment(toks.get(k))) { - tokens.add(new Token(toksBefore.build(), tok, toksAfter.build())); - toksBefore = ImmutableList.builder().add(toks.get(k++)); + tokens.add(new Token(List.copyOf(toksBefore), tok, List.copyOf(toksAfter))); + toksBefore = new ArrayList<>(); + toksBefore.add(toks.get(k++)); // drop newlines after parameter comments while (toks.get(k).isNewline()) { k++; @@ -628,10 +617,10 @@ private static ImmutableList buildTokens(List toks) { break; } } - tokens.add(new Token(toksBefore.build(), tok, toksAfter.build())); - toksBefore = ImmutableList.builder(); + tokens.add(new Token(List.copyOf(toksBefore), tok, List.copyOf(toksAfter))); + toksBefore = new ArrayList<>(); } - return tokens.build(); + return List.copyOf(tokens); } private static boolean isParamComment(Tok tok) { @@ -659,7 +648,7 @@ Range characterRangeToTokenRange(int offset, int length) throws Formatt // 0 stands for "format the line under the cursor" length = 1; } - ImmutableCollection enclosed = getPositionTokenMap() + Collection enclosed = getPositionTokenMap() .subRangeMap(Range.closedOpen(offset, offset + length)) .asMapOfRanges() .values(); @@ -695,7 +684,7 @@ Token getToken(int k) { * @return the input tokens */ @Override - public ImmutableList getTokens() { + public List getTokens() { return tokens; } @@ -706,7 +695,7 @@ public ImmutableList getTokens() { * @return the navigable map from position to {@link Token} */ @Override - public ImmutableRangeMap getPositionTokenMap() { + public RangeMap getPositionTokenMap() { return positionTokenMap; } 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 a3717902f..f399b3c92 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 @@ -40,15 +40,13 @@ import com.google.common.base.Throwables; import com.google.common.base.Verify; import com.google.common.collect.HashMultiset; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableRangeMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.google.common.collect.Multiset; import com.google.common.collect.PeekingIterator; +import com.google.common.collect.RangeMap; import com.google.common.collect.Streams; import com.palantir.javaformat.BreakBehaviour; import com.palantir.javaformat.CloseOp; @@ -287,20 +285,19 @@ boolean isYes() { protected final Indent.Const plusTwo; protected final Indent.Const plusFour; - private static ImmutableList breakList(Optional breakTag) { - return ImmutableList.of(Break.make(FillMode.UNIFIED, " ", ZERO, breakTag)); + private static List breakList(Optional breakTag) { + return List.of(Break.make(FillMode.UNIFIED, " ", ZERO, breakTag)); } - private static ImmutableList breakFillList(Optional breakTag) { - return ImmutableList.of( - OpenOp.make(ZERO), Break.make(FillMode.INDEPENDENT, " ", ZERO, breakTag), CloseOp.make()); + private static List breakFillList(Optional breakTag) { + return List.of(OpenOp.make(ZERO), Break.make(FillMode.INDEPENDENT, " ", ZERO, breakTag), CloseOp.make()); } - private static ImmutableList forceBreakList(Optional breakTag) { - return ImmutableList.of(Break.make(FillMode.FORCED, "", Indent.Const.ZERO, breakTag)); + private static List forceBreakList(Optional breakTag) { + return List.of(Break.make(FillMode.FORCED, "", Indent.Const.ZERO, breakTag)); } - private static final ImmutableList EMPTY_LIST = ImmutableList.of(); + private static final List EMPTY_LIST = List.of(); /** * Allow multi-line filling (of array initializers, argument lists, and boolean expressions) for items with length @@ -323,7 +320,7 @@ public JavaInputAstVisitor(OpsBuilder builder, int indentMultiplier) { } /** A record of whether we have visited into an expression. */ - private final Deque inExpression = new ArrayDeque<>(ImmutableList.of(false)); + private final Deque inExpression = new ArrayDeque<>(List.of(false)); private boolean inExpression() { return inExpression.peekLast(); @@ -465,7 +462,7 @@ public Void visitNewArray(NewArrayTree node, Void unused) { Deque dimExpressions = new ArrayDeque<>(node.getDimensions()); Deque> annotations = new ArrayDeque<>(); - annotations.add(ImmutableList.copyOf(node.getAnnotations())); + annotations.add(List.copyOf(node.getAnnotations())); annotations.addAll(node.getDimAnnotations()); annotations.addAll(extractedDims.dims); @@ -966,7 +963,7 @@ public Void visitExpressionStatement(ExpressionStatementTree node, Void unused) @Override public Void visitVariable(VariableTree node, Void unused) { sync(node); - visitVariables(ImmutableList.of(node), DeclarationKind.NONE, inlineAnnotationDirection(node.getModifiers())); + visitVariables(List.of(node), DeclarationKind.NONE, inlineAnnotationDirection(node.getModifiers())); return null; } @@ -1252,7 +1249,7 @@ protected void visitLambdaExpression(LambdaExpressionTree node, boolean statemen // A lambda parameter is a parameter: its annotations stay on its line, as a method parameter's do. The // vertical direction, a forced break after an annotation with arguments, is for local variable // declarations. - visitVariables(ImmutableList.of(parameter), DeclarationKind.NONE, Direction.HORIZONTAL); + visitVariables(List.of(parameter), DeclarationKind.NONE, Direction.HORIZONTAL); first = false; } if (parens) { @@ -1406,7 +1403,7 @@ private static boolean isCompactSourceFile(Tree type) { public Void visitMethod(MethodTree node, Void unused) { sync(node); List annotations = node.getModifiers().getAnnotations(); - List returnTypeAnnotations = ImmutableList.of(); + List returnTypeAnnotations = List.of(); boolean isRecordConstructor = (((JCTree.JCMethodDecl) node).mods.flags & COMPACT_RECORD_CONSTRUCTOR) == COMPACT_RECORD_CONSTRUCTOR; @@ -1611,11 +1608,11 @@ private boolean handleLogStatement(MethodInvocationTree node) { return false; } parts.addFirst(curr); - visitDotWithPrefix(ImmutableList.copyOf(parts), false, ImmutableList.of(parts.size() - 1), INDEPENDENT); + visitDotWithPrefix(List.copyOf(parts), false, List.of(parts.size() - 1), INDEPENDENT); return true; } - static final ImmutableSet LOG_METHODS = ImmutableSet.of( + static final Set LOG_METHODS = Set.of( "at", "atConfig", "atDebug", @@ -2285,8 +2282,8 @@ private List visitModifiers( builder.close(); // pjf specific: record params should take into consideration the columnLimit - ImmutableList trailingBreak = isRecordParameter - ? ImmutableList.of(Break.builder() + List trailingBreak = isRecordParameter + ? List.of(Break.builder() .fillMode(FillMode.UNIFIED) .flat(" ") .plusIndent(ZERO) @@ -3050,7 +3047,7 @@ private boolean shouldHaveColumnLimit(ExpressionTree expr) { /** Returns the simple names of expressions in a "." chain. */ private List simpleNames(Deque stack) { - ImmutableList.Builder simpleNames = ImmutableList.builder(); + var simpleNames = new ArrayList(); OUTER: for (ExpressionTree expression : stack) { boolean isArray = expression instanceof ArrayAccessTree; @@ -3074,7 +3071,7 @@ private List simpleNames(Deque stack) { break OUTER; } } - return simpleNames.build(); + return List.copyOf(simpleNames); } private void dotExpressionUpToArgs(ExpressionTree expression, Optional tyargTag) { @@ -3436,7 +3433,7 @@ private Integer actualColumn(ExpressionTree expression) { /** How many lines does this node take up in the input. Returns at least 1. */ int lineSpan(Tree node) { - ImmutableRangeMap positionTokenMap = + RangeMap positionTokenMap = builder.getInput().getPositionTokenMap(); int startPosition = getStartPosition(node); @@ -3845,7 +3842,7 @@ private void addBodyDeclarations( /** Gets the permits clause for the given node. This is only available in Java 15 and later. */ protected List getPermitsClause(ClassTree node) { - return ImmutableList.of(); + return List.of(); } private void classDeclarationTypeList(String token, List types) { 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 5ddeefca5..954d23fcc 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 @@ -19,7 +19,6 @@ import com.google.common.base.CharMatcher; import com.google.common.base.MoreObjects; import com.google.common.collect.DiscreteDomain; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; @@ -234,7 +233,7 @@ void flush() { ranges.add(Formatter.EMPTY_RANGE); } ranges.add(eofRange); - setLines(ImmutableList.copyOf(mutableLines)); + setLines(List.copyOf(mutableLines)); } // The following methods can be used after the Output has been built. @@ -244,8 +243,8 @@ void flush() { * * @return a list of {@link Replacement}s, sorted by start index, without overlaps */ - public ImmutableList getFormatReplacements(RangeSet iRangeSet0) { - ImmutableList.Builder result = ImmutableList.builder(); + public List getFormatReplacements(RangeSet iRangeSet0) { + var result = new ArrayList(); Map> kToJ = JavaOutput.makeKToIJ(this); // Expand the token ranges to align with re-formattable boundaries. @@ -348,7 +347,7 @@ public ImmutableList getFormatReplacements(RangeSet iRange result.add(Replacement.create(replaceFrom, replaceTo, replacement.toString())); } - return result.build(); + return List.copyOf(result); } /** 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 77baf2c3b..55748cc76 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 @@ -16,7 +16,6 @@ import static com.google.common.base.Preconditions.checkArgument; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.sun.tools.javac.parser.JavaTokenizer; import com.sun.tools.javac.parser.Scanner; @@ -27,6 +26,8 @@ import com.sun.tools.javac.parser.Tokens.TokenKind; import com.sun.tools.javac.parser.UnicodeReader; import com.sun.tools.javac.util.Context; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import org.jspecify.annotations.Nullable; @@ -79,14 +80,14 @@ public String stringVal() { } /** Lex the input and return a list of {@link RawTok}s. */ - public static ImmutableList getTokens(String source, Context context, Set stopTokens) { + public static List getTokens(String source, Context context, Set stopTokens) { if (source == null) { - return ImmutableList.of(); + return List.of(); } ScannerFactory fac = ScannerFactory.instance(context); char[] buffer = (source + EOF_COMMENT).toCharArray(); Scanner scanner = new AccessibleScanner(fac, new CommentSavingTokenizer(fac, buffer, buffer.length)); - ImmutableList.Builder tokens = ImmutableList.builder(); + var tokens = new ArrayList(); int end = source.length(); int last = 0; do { @@ -121,7 +122,7 @@ public static ImmutableList getTokens(String source, Context context, Se if (last < end) { tokens.add(new RawTok(null, null, last, end)); } - return tokens.build(); + return List.copyOf(tokens); } /** A {@link JavaTokenizer} that saves comments. */ 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 6366f1200..f6c421ed9 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 @@ -21,7 +21,6 @@ import static com.google.common.collect.Iterables.getLast; import com.google.common.base.Enums; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Ordering; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; @@ -42,7 +41,7 @@ final class ModifierOrderer { /** Reorders all modifiers in the given text to be in JLS order. */ static JavaInput reorderModifiers(String text) throws FormatterException { - return reorderModifiers(new JavaInput(text), ImmutableList.of(Range.closedOpen(0, text.length()))); + return reorderModifiers(new JavaInput(text), List.of(Range.closedOpen(0, text.length()))); } /** @@ -50,20 +49,20 @@ static JavaInput reorderModifiers(String text) throws FormatterException { * contains a {@code -} (e.g. {@code non-sealed}) is lexed as three tokens. */ static final class ModifierTokens implements Comparable { - private final ImmutableList tokens; + private final List tokens; @Nullable private final Modifier modifier; - static ModifierTokens create(ImmutableList tokens) { + static ModifierTokens create(List tokens) { return new ModifierTokens(tokens, asModifier(tokens)); } static ModifierTokens empty() { - return new ModifierTokens(ImmutableList.of(), null); + return new ModifierTokens(List.of(), null); } - private ModifierTokens(ImmutableList tokens, @Nullable Modifier modifier) { + private ModifierTokens(List tokens, @Nullable Modifier modifier) { this.tokens = tokens; this.modifier = modifier; } @@ -77,7 +76,7 @@ Modifier modifier() { return modifier; } - ImmutableList tokens() { + List tokens() { return tokens; } @@ -97,11 +96,11 @@ int endPosition() { return last().getTok().getPosition() + last().getTok().length(); } - ImmutableList getToksBefore() { + List getToksBefore() { return first().getToksBefore(); } - ImmutableList getToksAfter() { + List getToksAfter() { return last().getToksAfter(); } @@ -164,7 +163,7 @@ static JavaInput reorderModifiers(JavaInput javaInput, Collection return applyReplacements(javaInput, replacements); } - private static void addTrivia(StringBuilder replacement, ImmutableList toks) { + private static void addTrivia(StringBuilder replacement, List toks) { for (Tok tok : toks) { replacement.append(tok.getText()); } @@ -176,10 +175,10 @@ private static void addTrivia(StringBuilder replacement, ImmutableList it) { Token token = it.next(); - ImmutableList.Builder result = ImmutableList.builder(); + var result = new ArrayList(); result.add(token); if (!token.getTok().getText().equals("non")) { - return ModifierTokens.create(result.build()); + return ModifierTokens.create(List.copyOf(result)); } if (!it.hasNext()) { return ModifierTokens.empty(); @@ -190,11 +189,11 @@ private static ModifierTokens getModifierTokens(Iterator it) { return ModifierTokens.empty(); } result.add(it.next()); - return ModifierTokens.create(result.build()); + return ModifierTokens.create(List.copyOf(result)); } @Nullable - private static Modifier asModifier(ImmutableList tokens) { + private static Modifier asModifier(List tokens) { if (tokens.size() == 1) { return asModifier(tokens.get(0)); } 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 e7cd74b3a..c6a54eb3a 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 @@ -19,8 +19,6 @@ import com.google.common.base.CharMatcher; import com.google.common.base.Verify; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeMap; @@ -43,12 +41,15 @@ import com.sun.tools.javac.util.Position.LineMap; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import org.jspecify.annotations.Nullable; @@ -130,9 +131,8 @@ private static String wrapOnce(final int columnLimit, String input, Formatter fo return result; } - private static ImmutableSet> rangesAfterAppliedReplacements( - TreeRangeMap replacements) { - ImmutableSet.Builder> outputRanges = ImmutableSet.builder(); + private static Set> rangesAfterAppliedReplacements(TreeRangeMap replacements) { + var outputRanges = new LinkedHashSet>(); int offset = 0; for (Map.Entry, String> entry : replacements.asMapOfRanges().entrySet()) { @@ -147,7 +147,7 @@ private static ImmutableSet> rangesAfterAppliedReplacements( int newLength = upper - lower; offset += newLength - originalLength; } - return outputRanges.build(); + return Collections.unmodifiableSet(outputRanges); } public static TreeRangeMap getReflowReplacements( @@ -343,12 +343,12 @@ private void indentTextBlocks(TreeRangeMap replacements, List initialLines = text.lines().collect(ImmutableList.toImmutableList()); + List initialLines = text.lines().toList(); String stripped = initialLines.stream() .skip(1) .collect(joining(separator)) .stripIndent(); - ImmutableList lines = stripped.lines().collect(ImmutableList.toImmutableList()); + List lines = stripped.lines().toList(); // pjf specific: try to indent the text block, unless the text block will be indented more than the // starting quotes @@ -521,7 +521,7 @@ private void wrapLongStrings( int trailing = lineEnd - end; // Get the original source text of the string literals, excluding `"` and `+`. - ImmutableList components = stringComponents(input, unit, flat); + List components = stringComponents(input, unit, flat); var plain = reflow( columnLimit, continuationIndent, @@ -719,9 +719,8 @@ private static boolean onSameLineAsParent(LineMap lineMap, TreePath path) { * Returns the source text of the given string literal trees, excluding the leading and trailing double-quotes and * the `+` operator. */ - private static ImmutableList stringComponents( - String input, JCTree.JCCompilationUnit unit, List flat) { - ImmutableList.Builder result = ImmutableList.builder(); + private static List stringComponents(String input, JCTree.JCCompilationUnit unit, List flat) { + var result = new ArrayList(); StringBuilder piece = new StringBuilder(); for (Tree tree : flat) { // adjust for leading and trailing double quotes @@ -756,7 +755,7 @@ private static ImmutableList stringComponents( if (piece.length() > 0) { result.add(piece.toString()); } - return result.build(); + return List.copyOf(result); } static int hasEscapedWhitespaceAt(String input, int idx) { @@ -810,7 +809,7 @@ private static List reflow( int columnLimit, int continuationIndent, int trailing, - ImmutableList components, + List components, boolean first0, int textStartColumn, int firstLineStartColumn, @@ -904,7 +903,7 @@ && noComments(input, unit, flat.get(endIdx - 1), flat.get(endIdx))) { } firstInChain.set(startIdx == 0); - return ImmutableList.copyOf(flat.subList(startIdx, endIdx)); + return List.copyOf(flat.subList(startIdx, endIdx)); } /** diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/SuppressForbidden.java b/open-java-format/src/main/java/com/palantir/javaformat/java/SuppressForbidden.java new file mode 100644 index 000000000..6a6b41224 --- /dev/null +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/SuppressForbidden.java @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.palantir.javaformat.java; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Lets forbidden-apis accept a use of an API that config/forbidden-apis bans, for the reason given. */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) +@interface SuppressForbidden { + String reason(); +} 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 0fac3c4a7..096c701b5 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 @@ -16,10 +16,7 @@ package com.palantir.javaformat.java.java14; -import static com.google.common.collect.ImmutableList.toImmutableList; - import com.google.common.base.Verify; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.palantir.javaformat.Op; import com.palantir.javaformat.OpsBuilder; @@ -197,7 +194,7 @@ public void visitRecordDeclaration(ClassTree node) { if (!node.getTypeParameters().isEmpty()) { typeParametersRest(node.getTypeParameters(), hasSuperInterfaceTypes ? plusFour : ZERO); } - ImmutableList parameters = recordVariables(node); + List parameters = recordVariables(node); token("("); if (!parameters.isEmpty()) { // Break before args. @@ -227,20 +224,20 @@ public void visitRecordDeclaration(ClassTree node) { if (node.getMembers() == null) { token(";"); } else { - List members = node.getMembers().stream() + var members = node.getMembers().stream() .filter(t -> (TreeInfo.flags((JCTree) t) & Flags.GENERATED_MEMBER) == 0) - .collect(toImmutableList()); + .toList(); addBodyDeclarations(members, BracesOrNot.YES, FirstDeclarationsOrNot.YES); } dropEmptyDeclarations(); } - private static ImmutableList recordVariables(ClassTree node) { + private static List recordVariables(ClassTree node) { return node.getMembers().stream() .filter(JCTree.JCVariableDecl.class::isInstance) .map(JCTree.JCVariableDecl.class::cast) .filter(m -> (m.mods.flags & RECORD) == RECORD) - .collect(toImmutableList()); + .toList(); } @Override diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocFormatter.java b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocFormatter.java index 02aceca80..62695849d 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocFormatter.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocFormatter.java @@ -21,7 +21,6 @@ import static java.util.regex.Pattern.CASE_INSENSITIVE; import static java.util.regex.Pattern.compile; -import com.google.common.collect.ImmutableList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -46,7 +45,7 @@ public JavadocFormatter(int maxLineLength) { * the same characters. */ public String formatJavadoc(String input, int blockIndent) { - ImmutableList tokens; + List tokens; try { tokens = lex(input); } catch (LexException e) { 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 72a899b06..f7fcfe2e7 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 @@ -54,7 +54,6 @@ import com.google.common.base.CharMatcher; import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; import com.google.common.collect.PeekingIterator; import java.util.ArrayDeque; import java.util.ArrayList; @@ -66,7 +65,7 @@ /** Lexer for the Javadoc formatter. */ final class JavadocLexer { /** Takes a Javadoc comment, including ∕✱✱ and ✱∕, and returns tokens, including ∕✱✱ and ✱∕. */ - static ImmutableList lex(String input) throws LexException { + static List lex(String input) throws LexException { /* * TODO(cpovirk): In theory, we should interpret Unicode escapes (yet output them in their * original form). This would mean mean everything from an encoded ∕✱✱ to an encoded

 tag,
@@ -154,8 +153,8 @@ private JavadocLexer(CharStream input) {
         this.input = checkNotNull(input);
     }
 
-    private ImmutableList generateTokens() throws LexException {
-        ImmutableList.Builder tokens = ImmutableList.builder();
+    private List generateTokens() throws LexException {
+        var tokens = new ArrayList();
 
         Token token = new Token(BEGIN_JAVADOC, "/**");
         tokens.add(token);
@@ -170,7 +169,7 @@ private ImmutableList generateTokens() throws LexException {
         token = new Token(END_JAVADOC, "*/");
         tokens.add(token);
 
-        ImmutableList result = tokens.build();
+        List result = List.copyOf(tokens);
         result = joinAdjacentLiteralsAndAdjacentWhitespace(result);
         result = inferParagraphTags(result);
         result = optionalizeSpacesAfterLinks(result);
@@ -319,7 +318,7 @@ private void checkMatchingTags() throws LexException {
      *
      * 

Note that we do not merge a literal token and a whitespace token together. */ - private static ImmutableList joinAdjacentLiteralsAndAdjacentWhitespace(List input) { + private static List joinAdjacentLiteralsAndAdjacentWhitespace(List input) { /* * Note: Our final token is always END_JAVADOC. This saves us some trouble: * @@ -327,7 +326,7 @@ private static ImmutableList joinAdjacentLiteralsAndAdjacentWhitespace(Li * * - We don't need to check for leftover accumulated literals after we exit the loop. */ - ImmutableList.Builder output = ImmutableList.builder(); + var output = new ArrayList(); StringBuilder accumulated = new StringBuilder(); NestingCounter inlineTagDepth = new NestingCounter(); boolean lastTagWasInlineTagStart = false; @@ -400,7 +399,7 @@ && isWordStart(tokens.peek().getValue()) // We have another token coming, possibly of type OTHER. Leave it for the next iteration. } - return output.build(); + return List.copyOf(output); } private static boolean isHyphenatedWordEnd(CharSequence cs) { @@ -426,8 +425,8 @@ 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. */ - private static ImmutableList inferParagraphTags(List input) { - ImmutableList.Builder output = ImmutableList.builder(); + private static List inferParagraphTags(List input) { + var output = new ArrayList(); for (PeekingIterator tokens = peekingIterator(input.iterator()); tokens.hasNext(); ) { if (tokens.peek().getType() == LITERAL) { @@ -447,7 +446,7 @@ && hasMultipleNewlines(tokens.peek().getValue())) { } } - return output.build(); + return List.copyOf(output); /* * Note: We do not want to insert

tags inside

. Fortunately, the formatter gets that
@@ -464,8 +463,8 @@ && hasMultipleNewlines(tokens.peek().getValue())) {
      * 

This method must be called after {@link #joinAdjacentLiteralsAndAdjacentWhitespace}, as it assumes that * adjacent whitespace tokens have already been joined. */ - private static ImmutableList optionalizeSpacesAfterLinks(List input) { - ImmutableList.Builder output = ImmutableList.builder(); + private static List optionalizeSpacesAfterLinks(List input) { + var output = new ArrayList(); for (PeekingIterator tokens = peekingIterator(input.iterator()); tokens.hasNext(); ) { if (tokens.peek().getType() == LITERAL && tokens.peek().getValue().matches("^href=[^>]*>")) { @@ -479,7 +478,7 @@ private static ImmutableList optionalizeSpacesAfterLinks(List inpu } } - return output.build(); + return List.copyOf(output); /* * Note: We do not want to insert

tags inside

. Fortunately, the formatter gets that
@@ -493,8 +492,8 @@ private static ImmutableList optionalizeSpacesAfterLinks(List inpu
      *
      * 

Also trim leading and trailing blank lines, and move the trailing `}` to its own line. */ - private static ImmutableList deindentPreCodeBlocks(List input) { - ImmutableList.Builder output = ImmutableList.builder(); + private static List deindentPreCodeBlocks(List input) { + var output = new ArrayList(); for (PeekingIterator tokens = peekingIterator(input.iterator()); tokens.hasNext(); ) { if (tokens.peek().getType() != PRE_OPEN_TAG) { output.add(tokens.next()); @@ -514,10 +513,10 @@ private static ImmutableList deindentPreCodeBlocks(List input) { deindentPreCodeBlock(output, tokens); } - return output.build(); + return List.copyOf(output); } - private static void deindentPreCodeBlock(ImmutableList.Builder output, PeekingIterator tokens) { + private static void deindentPreCodeBlock(List output, PeekingIterator tokens) { Deque saved = new ArrayDeque<>(); output.add(new Token(LITERAL, tokens.next().getValue().trim())); while (tokens.hasNext() && tokens.peek().getType() != PRE_CLOSE_TAG) { 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 b9071173a..0767ce813 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 @@ -26,9 +26,9 @@ import static com.palantir.javaformat.java.javadoc.Token.Type.LIST_ITEM_OPEN_TAG; import static com.palantir.javaformat.java.javadoc.Token.Type.PARAGRAPH_OPEN_TAG; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Ordering; import java.util.List; +import java.util.Set; /** * Stateful object that accepts "requests" and "writes," producing formatted Javadoc. @@ -410,6 +410,6 @@ private void appendSpaces(int count) { * The special pinning here is necessary because these tokens are not of type LITERAL (because they require other * special handling). */ - private static final ImmutableSet START_OF_LINE_TOKENS = + private static final Set START_OF_LINE_TOKENS = immutableEnumSet(LIST_ITEM_OPEN_TAG, PARAGRAPH_OPEN_TAG, HEADER_OPEN_TAG); } diff --git a/open-java-format/src/test/java/com/palantir/javaformat/NewlinesTest.java b/open-java-format/src/test/java/com/palantir/javaformat/NewlinesTest.java index d00742fe2..cdf5e5ff0 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/NewlinesTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/NewlinesTest.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.fail; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.Streams; import com.google.common.truth.Truth; import java.util.Iterator; import java.util.NoSuchElementException; @@ -27,37 +27,41 @@ final class NewlinesTest { @Test void offsets() { - Truth.assertThat(ImmutableList.copyOf(Newlines.lineOffsetIterator("foo\nbar\n"))) + Truth.assertThat(Streams.stream(Newlines.lineOffsetIterator("foo\nbar\n")) + .toList()) .containsExactly(0, 4, 8); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineOffsetIterator("foo\nbar"))) + Truth.assertThat(Streams.stream(Newlines.lineOffsetIterator("foo\nbar")).toList()) .containsExactly(0, 4); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineOffsetIterator("foo\rbar\r"))) + Truth.assertThat(Streams.stream(Newlines.lineOffsetIterator("foo\rbar\r")) + .toList()) .containsExactly(0, 4, 8); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineOffsetIterator("foo\rbar"))) + Truth.assertThat(Streams.stream(Newlines.lineOffsetIterator("foo\rbar")).toList()) .containsExactly(0, 4); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineOffsetIterator("foo\r\nbar\r\n"))) + Truth.assertThat(Streams.stream(Newlines.lineOffsetIterator("foo\r\nbar\r\n")) + .toList()) .containsExactly(0, 5, 10); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineOffsetIterator("foo\r\nbar"))) + Truth.assertThat(Streams.stream(Newlines.lineOffsetIterator("foo\r\nbar")) + .toList()) .containsExactly(0, 5); } @Test void lines() { - Truth.assertThat(ImmutableList.copyOf(Newlines.lineIterator("foo\nbar\n"))) + Truth.assertThat(Streams.stream(Newlines.lineIterator("foo\nbar\n")).toList()) .containsExactly("foo\n", "bar\n"); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineIterator("foo\nbar"))) + Truth.assertThat(Streams.stream(Newlines.lineIterator("foo\nbar")).toList()) .containsExactly("foo\n", "bar"); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineIterator("foo\rbar\r"))) + Truth.assertThat(Streams.stream(Newlines.lineIterator("foo\rbar\r")).toList()) .containsExactly("foo\r", "bar\r"); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineIterator("foo\rbar"))) + Truth.assertThat(Streams.stream(Newlines.lineIterator("foo\rbar")).toList()) .containsExactly("foo\r", "bar"); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineIterator("foo\r\nbar\r\n"))) + Truth.assertThat(Streams.stream(Newlines.lineIterator("foo\r\nbar\r\n")).toList()) .containsExactly("foo\r\n", "bar\r\n"); - Truth.assertThat(ImmutableList.copyOf(Newlines.lineIterator("foo\r\nbar"))) + Truth.assertThat(Streams.stream(Newlines.lineIterator("foo\r\nbar")).toList()) .containsExactly("foo\r\n", "bar"); } diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/AospImportStyleTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/AospImportStyleTest.java index f568f8d9e..b65e11287 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/AospImportStyleTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/AospImportStyleTest.java @@ -19,8 +19,8 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; -import com.google.common.collect.ImmutableList; import com.palantir.javaformat.jupiter.ParameterizedClass; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.TestTemplate; @@ -351,9 +351,9 @@ public static List parameters() { }, }, }; - ImmutableList.Builder builder = ImmutableList.builder(); + var builder = new ArrayList(); Arrays.stream(inputsOutputs).forEach(input -> builder.add(ImportOrdererUtils.createRow(input))); - return builder.build(); + return List.copyOf(builder); } @TestTemplate diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java b/open-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java index 6a631bb42..138b162cf 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java @@ -23,13 +23,12 @@ import com.google.common.collect.ImmutableMultimap; import com.google.common.io.CharStreams; -import com.google.common.reflect.ClassPath; -import com.google.common.reflect.ClassPath.ResourceInfo; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UncheckedIOException; +import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -74,12 +73,32 @@ public static void assumeJavaVersionForTest(String testName) { Formatter.getRuntimeVersion() >= version, String.format("Not running on jdk %d or later", version))); } + /** The names of the resources under {@link #resourcePrefix}, in every directory of the class path that has it. */ + private List resourceNames(ClassLoader classLoader) throws IOException { + var names = new ArrayList(); + var roots = classLoader.getResources(resourcePrefix.toString().replace('\\', '/')); + while (roots.hasMoreElements()) { + Path root; + try { + root = Path.of(roots.nextElement().toURI()); + } catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + try (var files = Files.walk(root)) { + files.filter(Files::isRegularFile) + .map(file -> + resourcePrefix.resolve(root.relativize(file)).toString()) + .forEach(names::add); + } + } + return names; + } + public List paramsAsNameInputOutput() throws IOException { ClassLoader classLoader = testClass.getClassLoader(); Map inputs = new TreeMap<>(); Map outputs = new TreeMap<>(); - for (ResourceInfo resourceInfo : ClassPath.from(classLoader).getResources()) { - String resourceName = resourceInfo.getResourceName(); + for (String resourceName : resourceNames(classLoader)) { Path resourceNamePath = Paths.get(resourceName); if (resourceNamePath.startsWith(resourcePrefix)) { Path subPath = resourcePrefix.relativize(resourceNamePath); diff --git a/open-java-format/src/test/java/com/palantir/javaformat/java/GoogleImportStyleTest.java b/open-java-format/src/test/java/com/palantir/javaformat/java/GoogleImportStyleTest.java index 44b9b34e5..0eed77640 100644 --- a/open-java-format/src/test/java/com/palantir/javaformat/java/GoogleImportStyleTest.java +++ b/open-java-format/src/test/java/com/palantir/javaformat/java/GoogleImportStyleTest.java @@ -19,8 +19,8 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; -import com.google.common.collect.ImmutableList; import com.palantir.javaformat.jupiter.ParameterizedClass; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.TestTemplate; @@ -815,9 +815,9 @@ public static List parameters() { }, }; - ImmutableList.Builder builder = ImmutableList.builder(); + var builder = new ArrayList(); Arrays.stream(inputsOutputs).forEach(input -> builder.add(ImportOrdererUtils.createRow(input))); - return builder.build(); + return List.copyOf(builder); } @TestTemplate 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 47a9f817c..fe059ece9 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 @@ -19,7 +19,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; import com.google.common.io.ByteStreams; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; @@ -33,7 +32,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.PosixFilePermission; +import java.util.ArrayList; import java.util.EnumSet; +import java.util.List; import java.util.Locale; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; @@ -45,7 +46,7 @@ @Execution(ExecutionMode.CONCURRENT) final class MainTest { - private static final ImmutableList ADD_EXPORTS = ImmutableList.of( + private static final List ADD_EXPORTS = List.of( "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", @@ -675,7 +676,7 @@ void commentBetweenImportsMovesWithTheImportAfterIt() throws Exception { String[] expected = { "// why we need A", "import a.A;", "import b.B;", "", "class T {", " A a;", " B b;", "}", "", }; - for (String[] source : ImmutableList.of(input, expected)) { + for (String[] source : List.of(input, expected)) { StringWriter out = new StringWriter(); Main main = new Main( new PrintWriter(out, true), @@ -687,18 +688,15 @@ void commentBetweenImportsMovesWithTheImportAfterIt() throws Exception { } private static ProcessBuilder formatterMain(String... args) { - return new ProcessBuilder(ImmutableList.builder() - .add(Paths.get(System.getProperty("java.home")) - .resolve("bin/java") - .toString()) - .addAll(ADD_EXPORTS) - .add("-cp", System.getProperty("java.class.path")) - .add(Main.class.getName()) - .add("-n") - .add("--set-exit-if-changed") - .add(args) - .build()) - .redirectError(Redirect.PIPE) - .redirectOutput(Redirect.PIPE); + var command = new ArrayList(); + command.add( + Paths.get(System.getProperty("java.home")).resolve("bin/java").toString()); + command.addAll(ADD_EXPORTS); + command.addAll(List.of("-cp", System.getProperty("java.class.path"))); + command.add(Main.class.getName()); + command.add("-n"); + command.add("--set-exit-if-changed"); + command.addAll(List.of(args)); + return new ProcessBuilder(command).redirectError(Redirect.PIPE).redirectOutput(Redirect.PIPE); } } 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 72be6cf1c..544ac3d61 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 @@ -18,7 +18,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ObjectArrays; import com.google.common.collect.Range; import com.palantir.javaformat.jupiter.ParameterizedClass; @@ -43,7 +42,7 @@ public final class PartialFormattingTest { @ParameterizedClass.Parameters public static List parameters() { - return ImmutableList.copyOf(new Object[][] {{"\n"}, {"\r"}, {"\r\n"}}); + return List.of(new Object[][] {{"\n"}, {"\r"}, {"\r\n"}}); } @TempDir @@ -321,8 +320,7 @@ public void onlyPackage() throws Exception { } private static String doGetFormatReplacements(String input, int characterILo, int characterIHi) throws Exception { - return Formatter.create() - .formatSource(input, ImmutableList.of(Range.closedOpen(characterILo, characterIHi + 1))); + return Formatter.create().formatSource(input, List.of(Range.closedOpen(characterILo, characterIHi + 1))); } @TestTemplate @@ -576,7 +574,7 @@ public void emptyFile() throws Exception { lines( "", // ""), - ImmutableList.of(Range.closedOpen(0, 1))); + List.of(Range.closedOpen(0, 1))); } @TestTemplate @@ -590,8 +588,8 @@ public void testGetFormatReplacementRanges() throws Exception { ""); // Claim to have modified the parentheses. int start = input.indexOf("() {"); - ImmutableList ranges = - Formatter.create().getFormatReplacements(input, ImmutableList.of(Range.closedOpen(start, start + 1))); + List ranges = + Formatter.create().getFormatReplacements(input, List.of(Range.closedOpen(start, start + 1))); assertThat(ranges).hasSize(1); Replacement replacement = ranges.get(0); assertThat(replacement.getReplacementString()) @@ -794,7 +792,7 @@ public void testReplacementsSorted() throws Exception { ranges.add(Range.closedOpen(idx, idx + 1)); } - ImmutableList replacements = Formatter.create().getFormatReplacements(input, ranges); + List replacements = Formatter.create().getFormatReplacements(input, ranges); // expect replacements in ascending order, by start position List startPositions = new ArrayList<>(); @@ -814,7 +812,7 @@ public void testReplacementsSorted_DescendingInput() throws Exception { ranges.add(Range.closedOpen(idx, idx + 1)); } - ImmutableList replacements = Formatter.create().getFormatReplacements(input, ranges); + List replacements = Formatter.create().getFormatReplacements(input, ranges); // expect replacements in ascending order, by start position List startPositions = new ArrayList<>(); @@ -920,7 +918,7 @@ public void noTrailingWhitespace() throws Exception { "}", ""); int start = input.indexOf(newline + "}}"); - ImmutableList> ranges = ImmutableList.of(Range.closedOpen(start, start + newline.length() + 2)); + List> ranges = List.of(Range.closedOpen(start, start + newline.length() + 2)); String output = Formatter.create().formatSource(input, ranges); Assertions.assertThat(output).describedAs("bad output").isEqualTo(expected); } @@ -948,7 +946,7 @@ public void trailingNonBreakingWhitespace() throws Exception { String match = "int x;"; int start = input.indexOf(match); int end = start + match.length(); - ImmutableList> ranges = ImmutableList.of(Range.closedOpen(start, end)); + List> ranges = List.of(Range.closedOpen(start, end)); String output = Formatter.create().formatSource(input, ranges); Assertions.assertThat(output).describedAs("bad output").isEqualTo(expected); } @@ -1176,7 +1174,7 @@ public void onNewline() throws Exception { for (; length <= line1.length() + newline.length(); length++) { Range range = Range.closedOpen(startOffset, startOffset + length); - String output = Formatter.create().formatSource(input, ImmutableList.of(range)); + String output = Formatter.create().formatSource(input, List.of(range)); Assertions.assertThat(output).describedAs("bad output").isEqualTo(expectedFormatLine1); } @@ -1189,7 +1187,7 @@ public void onNewline() throws Exception { for (; length <= line1.length() + line2.length() + 2 * newline.length(); length++) { Range range = Range.closedOpen(startOffset, startOffset + length); - String output = Formatter.create().formatSource(input, ImmutableList.of(range)); + String output = Formatter.create().formatSource(input, List.of(range)); Assertions.assertThat(output).describedAs("bad output").isEqualTo(expectedFormatLine1And2); } } @@ -1226,7 +1224,7 @@ public void afterNewline() throws Exception { // formatting a range that touches non-whitespace characters in line2 should format line2 for (start = nonWhitespaceLine2Start; start > (line2Start - newline.length()); start--) { Range range = Range.closedOpen(start, nonWhitespaceLine2Start + newline.length()); - String output = Formatter.create().formatSource(input, ImmutableList.of(range)); + String output = Formatter.create().formatSource(input, List.of(range)); assertThat(output).isEqualTo(expectedFormatLine2); } // formatting a range that touches whitespace characters between line1 and line2 should @@ -1235,7 +1233,7 @@ public void afterNewline() throws Exception { int line1End = input.indexOf(line1) + line1.length(); for (; start >= line1End; start--) { Range range = Range.closedOpen(start, line2Start); - String output = Formatter.create().formatSource(input, ImmutableList.of(range)); + String output = Formatter.create().formatSource(input, List.of(range)); assertThat(output).isEqualTo(input); } // formatting a range that touches non-whitespace characters in line1 should format line1 @@ -1243,7 +1241,7 @@ public void afterNewline() throws Exception { int line1Start = input.indexOf(line1); for (; start >= line1Start; start--) { Range range = Range.closedOpen(start, line2Start); - String output = Formatter.create().formatSource(input, ImmutableList.of(range)); + String output = Formatter.create().formatSource(input, List.of(range)); assertThat(output).isEqualTo(expectedFormatLine1); } } @@ -1354,7 +1352,7 @@ public void endOfLine() throws Exception { Formatter formatter = Formatter.createFormatter(JavaFormatterOptions.builder() .style(JavaFormatterOptions.Style.OJF) .build()); - assertThat(formatter.formatSource(in, ImmutableList.of(Range.closedOpen(start, start)))) + assertThat(formatter.formatSource(in, List.of(Range.closedOpen(start, start)))) .isEqualTo(lines(expected)); assertThat(formatMain(lines(input), "-offset", String.valueOf(start), "-length", "0")) @@ -1390,7 +1388,7 @@ public void endOfLineStatement() throws Exception { }; String in = lines(input); int idx = in.indexOf(';'); - assertThat(Formatter.create().formatSource(in, ImmutableList.of(Range.closedOpen(idx, idx)))) + assertThat(Formatter.create().formatSource(in, List.of(Range.closedOpen(idx, idx)))) .isEqualTo(lines(expected)); } @@ -1405,7 +1403,7 @@ public void endOfLineStatementNewline() throws Exception { }; String in = lines(input); int idx = in.indexOf(';'); - assertThat(Formatter.create().formatSource(in, ImmutableList.of(Range.closedOpen(idx + 1, idx + 1)))) + assertThat(Formatter.create().formatSource(in, List.of(Range.closedOpen(idx + 1, idx + 1)))) .isEqualTo(in); } @@ -1534,7 +1532,7 @@ public void trailing() throws Exception { " int e = 7 +4;", " }", "}"); - String actual = Formatter.create().formatSource(input, ImmutableList.of(rangeOf(input, "int c = 7 +4"))); + String actual = Formatter.create().formatSource(input, List.of(rangeOf(input, "int c = 7 +4"))); assertThat(actual).isEqualTo(expected); }