Repository navigation
Do not rewrite JBang directives: //DEPS becomes // DEPS and the script loses its dependencies #24
Description
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 -Xmx512mbecomes
/// 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 -Xmx512mThree separate things go wrong:
- A space is added after the slashes, so
//DEPSbecomes// DEPS. JBang no longer sees the directive: the dependencies, the Java version and the options are silently dropped, and the script stops compiling. - The first line gets a space too,
/// usr/bin/env …, which breaks running the script directly from a shell. - 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
//KEYWORDline, but only in a file that JBang would treat as a script, for example one that starts with the///usr/bin/env jbangline or contains//DEPSor//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
- avoid adding space on // comments? google/google-java-format#1217, by JBang's author, asks for the same thing there and is open.
- do not touch /// in first lines google/google-java-format#1218 and Comments starting with /// should not be reformatted as // / google/google-java-format#1215 are about the
///first line. - Allow detecting DEPS with the schema // DEPS jbangdev/jbang#1194 asked JBang to accept
// DEPSinstead. It was closed with the view that a formatter should not add a space where there was none. - Bring over upstream PRs #1707 (Java 25 syntax) and #1786 (JDK 27 end positions) #22 brings compact source files and instance
mainmethods, which JBang scripts use a lot.
Activity
Install open-java-format 2.98.0.5 and add JBang to the library rules
Check with open-java-format 2.98.0.5