Skip to content

Do not rewrite JBang directives: //DEPS becomes // DEPS and the script loses its dependencies #24

Description

@abashev

What happens

JBang reads its configuration from line comments that must start with // immediately followed by the keyword: //DEPS, //JAVA, //SOURCES, //FILES, //JAVA_OPTIONS and so on. A script usually also starts with ///usr/bin/env jbang "$0" "$@" ; exit $?, which makes the file runnable from a shell and is still a comment for javac.

The formatter rewrites all of them. Reproduced with 2.98.0.1, jar and native binary alike:

///usr/bin/env jbang "$0" "$@" ; exit $?
//JAVA 21+
//DEPS info.picocli:picocli:4.7.6
//DEPS com.fasterxml.jackson.core:jackson-databind:2.17.2 org.slf4j:slf4j-simple:2.0.13 com.squareup.okhttp3:okhttp:4.12.0 org.jsoup:jsoup:1.18.1
//JAVA_OPTIONS -Xmx512m

becomes

/// usr/bin/env jbang "$0" "$@" ; exit $?
// JAVA 21+
// DEPS info.picocli:picocli:4.7.6
// DEPS com.fasterxml.jackson.core:jackson-databind:2.17.2 org.slf4j:slf4j-simple:2.0.13
// com.squareup.okhttp3:okhttp:4.12.0 org.jsoup:jsoup:1.18.1
// JAVA_OPTIONS -Xmx512m

Three separate things go wrong:

  1. A space is added after the slashes, so //DEPS becomes // DEPS. JBang no longer sees the directive: the dependencies, the Java version and the options are silently dropped, and the script stops compiling.
  2. The first line gets a space too, /// usr/bin/env …, which breaks running the script directly from a shell.
  3. A long directive is wrapped at 120 columns. Even without the space, the second half of the dependency list would end up in an ordinary comment.

Why

JavaCommentsHelper.wrapLineComments adds the missing space with LINE_COMMENT_MISSING_SPACE_PREFIX, which exempts only //noinspection and //$NON-NLS-n$, and then wraps every line comment that is too long. doc/Comment.computeFlat() adds the same space on the path where the helper is not called at all, see #23.

Today's workaround

Exclude the scripts. The GitHub Action and the pre-commit hook read .open-java-format-exclude, and their README uses exactly this case as the example. That keeps CI green but leaves JBang scripts unformatted.

Proposal

Leave JBang directives and the ///usr/bin/env line exactly as written: no inserted space, no wrapping.

The rule has to be narrow. A blanket "do not touch //WORD" would stop //TODO from becoming // TODO and change the output of ordinary code. Two ways to keep it narrow:

  • a fixed list of JBang keywords, taken from JBang's documentation, or
  • any //KEYWORD line, but only in a file that JBang would treat as a script, for example one that starts with the ///usr/bin/env jbang line or contains //DEPS or //JAVA.

Compatibility

For a JBang script the current output is a broken script, so nobody depends on it. With a narrow rule nothing else changes. It still differs from palantir-java-format 2.98.0 for these files, which the 2.x promise has to allow for explicitly.

Related

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions