Skip to content

Fix the imports before the layout or after it? #224

Open

Description

@abashev

The question

Should the imports be fixed before the code is laid out, or after it? Every route has to do it in the same order, or the same file comes out differently (#219). #220 makes them all fix the imports after formatting, as the command line, the native binary and the GitHub Action already did. google-java-format has just gone the other way: google/google-java-format@633ce6be (2026-10-20) runs unused-import removal, modifier reordering and import sorting as one pass before the layout, on the command line too, and remaps the requested character ranges through each of its edits.

What depends on the order

ImportOrderer moves a comment along with its import, and RemoveUnusedImports leaves the comment of an import it removes behind, so the order decides where that comment ends up. It also decides whether an extraneous semicolon between imports is dropped or fails the file. Over 3,865 real files, as they are and with an unused import added to each, the two orders differ in one, CharsetEncoder of JDK 21; each order passes its check on what the other wrote. Four cases, ready for test-cases/imports in #225, pin the differences: commentOfARemovedImportGoesWithTheImportAboveIt, commentOfARemovedOwnPackageImportGoesWithTheImportAboveIt, commentUnderARemovedImportStaysOnTheClass and semicolonAfterTheLastImportStaysOnALineOfItsOwn.

For and against

Before the layout (google-java-format now, formatSourceAndFixImports before #220) After the layout (#220, the command line, the native binary, the GitHub Action)
Output of the command line and the GitHub Action changes in the rare cases above stays as it is
Porting from google-java-format follows its Cleanups conflicts with it
import a.B;; followed by another import formatted: ImportOrderer drops the semicolon fails with extraneous semicolon, as javac 21 does with --release 21
A comment under a removed import a blank line stays between it and the class stays on the class
Reformat Code with "Optimize imports" in IntelliJ IDEA (#222) the same order: the IDE runs the optimizer first differs, unless a whole-file Reformat runs in one pass
Ranges (--lines, --output-replacements, IntelliJ IDEA, formatDiff) the ranges have to be remapped through the import edits, as google-java-format does the ranges are offsets into the input and work as they are
Work ImportOrderer and RemoveUnusedImports return replacements instead of text; the import commit of #220 is redone done in #220

Proposal

Keep "after" for now: the command line is what every check compares with, and it does not change. Revisit when porting google-java-format's Cleanups, which would bring "before" together with the range remapping it needs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions