From 14d3ed049f601e3dafd5bc03da63eb973fad4f3e Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Thu, 12 Nov 2026 19:26:04 +0300 Subject: [PATCH 1/6] Replace Guava's immutable collections with java.util ones ImmutableList, ImmutableMap, ImmutableSet and ImmutableSortedSet give way to List.of, List.copyOf, Map.of, Stream.toList() and, where a builder filled them, an ArrayList or a TreeSet handed out with List.copyOf or an unmodifiable view. FileBasedTests lists its test resources with Files.walk rather than Guava's ClassPath, whose getResources() returns an ImmutableSet. What differs between the two kinds of collection decided three places: - Newlines.BREAKS is a List: it is tried in order, "\r\n" before "\n", and Set.of keeps no order. StringWrapper's ranges are a LinkedHashSet for the same reason. - JavaInput.buildToks asks its stop tokens whether they contain the kind of a comment token, which is null, and Set.of throws on contains(null). They are a HashSet. - Error Prone's @Immutable cannot prove a java.util List or Map immutable, so it is gone from Input.Token, JavaInput.Token, OpsBuilder.BlankLineWanted, InputMetadata and doc.Token. The SPI does not change. FormatterService.getFormatReplacements still returns ImmutableList, so that code compiled against an older SPI keeps linking, and its three implementations still declare it: FormatterServiceImpl copies Formatter's list into one. Formatter's own getFormatReplacements, Input.getPositionTokenMap (a RangeMap now) and SnippetFormatter.format return java.util types. --- .../gradle/PalantirJavaFormatIdeaPlugin.java | 8 +- .../palantir/javaformat/gradle/XmlUtils.java | 4 +- .../javaformat/gradle/FormatDiff.java | 3 +- .../PalantirJavaFormatSpotlessPlugin.java | 6 +- .../javaformat/gradle/FormatDiffTest.java | 5 +- .../javaformat/java/SnippetFormatter.java | 7 +- .../PalantirJavaFormatFormattingService.java | 15 ++-- .../BootstrappingFormatterService.java | 28 +++--- .../NativeImageFormatterService.java | 15 ++-- .../bootstrap/FormatterServicesTest.java | 5 +- .../palantir/javaformat/FormattingError.java | 12 +-- .../java/com/palantir/javaformat/Input.java | 17 ++-- .../com/palantir/javaformat/InputOutput.java | 5 +- .../com/palantir/javaformat/Newlines.java | 5 +- .../com/palantir/javaformat/OpsBuilder.java | 24 +++-- .../com/palantir/javaformat/doc/Level.java | 19 ++-- .../com/palantir/javaformat/doc/Token.java | 2 - .../javaformat/java/CommandLineOptions.java | 45 +++++----- .../java/CommandLineOptionsParser.java | 4 +- .../javaformat/java/DebugRenderer.java | 4 +- .../javaformat/java/DimensionHelpers.java | 14 +-- .../palantir/javaformat/java/Formatter.java | 7 +- .../javaformat/java/FormatterServiceImpl.java | 2 +- .../javaformat/java/ImportOrderer.java | 31 ++++--- .../javaformat/java/InputMetadata.java | 7 +- .../javaformat/java/InputMetadataBuilder.java | 3 +- .../javaformat/java/JavaCommentsHelper.java | 4 +- .../palantir/javaformat/java/JavaInput.java | 87 +++++++++---------- .../javaformat/java/JavaInputAstVisitor.java | 45 +++++----- .../palantir/javaformat/java/JavaOutput.java | 9 +- .../palantir/javaformat/java/JavacTokens.java | 11 +-- .../javaformat/java/ModifierOrderer.java | 27 +++--- .../javaformat/java/StringWrapper.java | 29 +++---- .../java/java14/Java14InputAstVisitor.java | 12 ++- .../java/javadoc/JavadocFormatter.java | 3 +- .../javaformat/java/javadoc/JavadocLexer.java | 35 ++++---- .../java/javadoc/JavadocWriter.java | 4 +- .../com/palantir/javaformat/NewlinesTest.java | 30 ++++--- .../javaformat/java/AospImportStyleTest.java | 6 +- .../javaformat/java/FileBasedTests.java | 27 +++++- .../java/GoogleImportStyleTest.java | 6 +- .../palantir/javaformat/java/MainTest.java | 30 +++---- .../java/PartialFormattingTest.java | 38 ++++---- 43 files changed, 345 insertions(+), 355 deletions(-) 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..ba4390ada 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) { 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..546730f5f 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; @@ -125,27 +126,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..553d50168 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; @@ -91,20 +92,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/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..b662f7516 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; } 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..d6fa5ea77 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 @@ -35,7 +35,7 @@ public FormatterServiceImpl() { @Override 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..4d2027d2e 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; } @@ -268,9 +268,9 @@ public String toString() { * 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 +284,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 +320,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 +335,7 @@ public String getText() { } @Override - public ImmutableMap getPositionToColumnMap() { + public Map getPositionToColumnMap() { return positionToColumnMap; } @@ -346,8 +344,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 +358,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 +374,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 +472,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 +560,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 +583,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 +610,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 +625,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 +656,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 +692,7 @@ Token getToken(int k) { * @return the input tokens */ @Override - public ImmutableList getTokens() { + public List getTokens() { return tokens; } @@ -706,7 +703,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/java14/Java14InputAstVisitor.java b/open-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java index 0fac3c4a7..0dd233404 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; @@ -46,6 +43,7 @@ import java.lang.reflect.Method; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import javax.lang.model.element.Name; import org.jspecify.annotations.Nullable; @@ -197,7 +195,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. @@ -229,18 +227,18 @@ public void visitRecordDeclaration(ClassTree node) { } else { List members = node.getMembers().stream() .filter(t -> (TreeInfo.flags((JCTree) t) & Flags.GENERATED_MEMBER) == 0) - .collect(toImmutableList()); + .collect(Collectors.toUnmodifiableList()); 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); } From 40df976d5c93ac013633bd8ecc6935808ba0795f Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Thu, 12 Nov 2026 19:26:23 +0300 Subject: [PATCH 2/6] Ban Guava's immutable collections outside the SPI forbidden-apis 3.11 checks the bytecode of every module but the SPI against config/forbidden-apis/guava-immutables.txt, which names ImmutableList, ImmutableMap and ImmutableSet, and fails the build on a use of one. Error Prone has no check that bans a class, and Picnic's error-prone-support pushes towards Guava's immutables rather than away. The check sees what a source-level ban would miss: a var whose type is one of them, a subclass such as ImmutableSortedSet, and a call on what a Guava method like ClassPath.getResources() returns. The SPI is left out because FormatterService.getFormatReplacements returns ImmutableList for compatibility. The methods that implement it in open-java-format and open-java-format-jdk-bootstrap carry @SuppressForbidden, an annotation of each module's own: the default one would put forbidden-apis on their compile classpath. Code that calls the method and keeps the result as a List passes the check. ignoreSignaturesOfMissingClasses, because the benchmarks have no Guava on their classpath and would otherwise fail to parse the signatures. --- CLAUDE.md | 6 +++-- build.gradle | 5 ++++ buildSrc/build.gradle | 1 + ...a-format.forbidden-apis-conventions.gradle | 13 ++++++++++ config/forbidden-apis/guava-immutables.txt | 4 +++ .../BootstrappingFormatterService.java | 2 ++ .../NativeImageFormatterService.java | 1 + .../bootstrap/SuppressForbidden.java | 26 +++++++++++++++++++ .../javaformat/java/FormatterServiceImpl.java | 1 + .../javaformat/java/SuppressForbidden.java | 26 +++++++++++++++++++ 10 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 buildSrc/src/main/groovy/open-java-format.forbidden-apis-conventions.gradle create mode 100644 config/forbidden-apis/guava-immutables.txt create mode 100644 open-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/SuppressForbidden.java create mode 100644 open-java-format/src/main/java/com/palantir/javaformat/java/SuppressForbidden.java diff --git a/CLAUDE.md b/CLAUDE.md index 3ed0f72fc..ae9c33a69 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,8 +6,10 @@ Building and testing: the README's "Building and testing locally" section. Gradl ## 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/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.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/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 546730f5f..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 @@ -52,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); @@ -78,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( 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 553d50168..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 @@ -43,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 { 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/src/main/java/com/palantir/javaformat/java/FormatterServiceImpl.java b/open-java-format/src/main/java/com/palantir/javaformat/java/FormatterServiceImpl.java index d6fa5ea77..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,6 +33,7 @@ public FormatterServiceImpl() { } @Override + @SuppressForbidden(reason = "FormatterService, kept in the SPI for compatibility, returns ImmutableList") public ImmutableList getFormatReplacements(String text, Collection> toRanges) throws FormatterException { return ImmutableList.copyOf(formatter.getFormatReplacements(text, toRanges)); 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(); +} From ed5bf348b4f0fb5521d0db2b08e3093f2413b8d9 Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Thu, 12 Nov 2026 19:26:34 +0300 Subject: [PATCH 3/6] Run check in CI's build job The build job ran ./gradlew test, and forbidden-apis hangs off check, so the previous commit's ban would never have failed a pull request. check also runs Checkstyle and the Gradle plugin's validatePlugins, which pass. The jdk jobs, which run the same code on other JDKs, keep running only the tests. The README and CLAUDE.md say what CI runs. --- .github/workflows/ci.yml | 2 +- CLAUDE.md | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 ae9c33a69..e2eada00d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,7 +1,7 @@ # 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 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 From 7a2bac9dc8f9a163272a6a0c83ad5eae8b5fc3f2 Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Thu, 12 Nov 2026 20:04:56 +0300 Subject: [PATCH 4/6] Collect a record's members with Stream.toList() Collectors.toUnmodifiableList() was there only because the list was declared List, and Stream.toList() on getMembers(), a List, gives a list of the wildcard's capture. addBodyDeclarations takes a List, so the variable is a var and the stream ends in toList(), as CLAUDE.md asks. --- .../javaformat/java/java14/Java14InputAstVisitor.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 0dd233404..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 @@ -43,7 +43,6 @@ import java.lang.reflect.Method; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import javax.lang.model.element.Name; import org.jspecify.annotations.Nullable; @@ -225,9 +224,9 @@ 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(Collectors.toUnmodifiableList()); + .toList(); addBodyDeclarations(members, BracesOrNot.YES, FirstDeclarationsOrNot.YES); } dropEmptyDeclarations(); From 8e2626337e8201756b5bd6d67e2e70e804378410 Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Thu, 12 Nov 2026 20:08:52 +0300 Subject: [PATCH 5/6] Make DefaultCharset an error FormatDiff decoded what a failed git command printed to stdout and stderr in the platform's charset, while the output of one that succeeds, three lines further down, is read as UTF-8. Both are UTF-8 now. --- .../groovy/open-java-format.error-prone-conventions.gradle | 1 + .../main/java/com/palantir/javaformat/gradle/FormatDiff.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) 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/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 ba4390ada..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 @@ -135,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); From ef69118283b03bf036e234175400491179a88493 Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Thu, 12 Nov 2026 20:37:56 +0300 Subject: [PATCH 6/6] Move JavaInput's comment on line ranges to InputOutput.ranges The block comment above JavaInput's fields described "the following lists" of tok indices on each line, which live in InputOutput.ranges, and Error Prone's AlmostJavadoc flagged its {@code} tags. What it said that the field's Javadoc did not, that a /* comment spans lines and that the lists give the correspondence between input and output, is in that Javadoc now. --- .../main/java/com/palantir/javaformat/InputOutput.java | 5 ++++- .../main/java/com/palantir/javaformat/java/JavaInput.java | 8 -------- 2 files changed, 4 insertions(+), 9 deletions(-) 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 b662f7516..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 @@ -52,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/java/JavaInput.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInput.java index 4d2027d2e..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 @@ -260,14 +260,6 @@ 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 Map positionToColumnMap; // Map Tok position to column. private final List tokens; // The Tokens for this input.