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:
- 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.
- 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
//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
What happens
JBang reads its configuration from line comments that must start with
//immediately followed by the keyword://DEPS,//JAVA,//SOURCES,//FILES,//JAVA_OPTIONSand 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:
becomes
Three separate things go wrong:
//DEPSbecomes// DEPS. JBang no longer sees the directive: the dependencies, the Java version and the options are silently dropped, and the script stops compiling./// usr/bin/env …, which breaks running the script directly from a shell.Why
JavaCommentsHelper.wrapLineCommentsadds the missing space withLINE_COMMENT_MISSING_SPACE_PREFIX, which exempts only//noinspectionand//$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/envline exactly as written: no inserted space, no wrapping.The rule has to be narrow. A blanket "do not touch
//WORD" would stop//TODOfrom becoming// TODOand change the output of ordinary code. Two ways to keep it narrow://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
///first line.// DEPSinstead. It was closed with the view that a formatter should not add a space where there was none.mainmethods, which JBang scripts use a lot.