# Formatting

> Format Java and Kotlin with `elide format`, which runs the bundled google-java-format (or the Netflix jfmt dialect) and ktfmt, or run `elide javaformat` or `elide ktfmt` alone.

Elide bundles google-java-format 1.37.0, Netflix jfmt 0.9.0 and ktfmt 0.65. `elide format` runs the Java and Kotlin
formatters; `elide javaformat` and `elide ktfmt` run one.

```bash
elide format -- src
elide javaformat -- Hello.java src/main/java
elide ktfmt -- Hello.kt src/main/kotlin
```

<img src="https://elide.help/assets/demos/format.gif" alt="Formatting Java and Kotlin source files with Elide" width="1591" height="1128" loading="lazy" decoding="async" class="rounded-lg border border-border my-6 w-full" />

Files and directories go after `--` and are rewritten in place. Each file is reported as unchanged, rewritten, would
be rewritten, or failed to parse. `javaformat` also accepts `-i`:

```bash
elide javaformat -- -i Hello.java
```

## Check formatting

`-n` or `--dry-run` after `--` writes nothing and exits 1 if a file would change. `--set-exit-if-changed` is
accepted; there is no `--check`.

```bash
elide format -- -n src
elide javaformat -- -n src/main/java
elide ktfmt -- -n src/main/kotlin
```

In check mode, two Elide options (before `--`) report what would change:

```bash
elide format --list-files -- -n src
elide format --list-diffs -- -n src
elide format --list-diffs=5 -- -n src
```

| Option | Output |
| --- | --- |
| `--list-files` | Paths that would change, one per line on stdout. |
| `--list-diffs=N` | Unified diffs when at most `N` files fail, otherwise paths. Use `=N`, not a separate value. |

Both work on `javaformat` and `ktfmt` too.

## Formatter flags

Everything after `--` is passed to the formatter, including argument files and style switches (`--google-style`,
`--kotlinlang-style`, `--aosp`):

```bash
elide ktfmt -- --google-style @kotlin-sources.txt
```

`elide javaformat --help` and `elide ktfmt --help` show Elide's options and how to show the formatter's help.

## Select project sources

With no paths after `--`, `elide format` formats the Java and Kotlin sources of the current project:

```bash
elide format
elide format --install -- --jfmt
elide format --install -- --jfmt -n
```

`--install` is an Elide option on `elide format`, before `--`. It runs the dependency installation step first and stops
if installation fails. Use it when jfmt needs project dependency types to resolve imports. To run only the Java
formatter with those dependencies, install first and name the Java sources:

```bash
elide install
elide javaformat -- --jfmt src/main/java
```

## jfmt dialect

`--jfmt` formats Java with [jfmt](https://github.com/Netflix/jfmt) instead of google-java-format: 4-space blocks,
8-space continuations, no column limit, braces around every statement body, and static imports after ordinary ones.

```bash
elide javaformat -- --jfmt src/main/java
elide format -- --jfmt -n src
```

Selecting jfmt changes Java formatting only; `elide format` still uses ktfmt for Kotlin files.

jfmt is a fixed style, so `--jfmt` cannot be combined with `--aosp`, `--fix-imports-only` or the `--skip-*` flags.

### Resolve and rewrite imports

Like upstream `jfmt`, Elide first runs jfmt's import pass over the files of a run: wildcard imports are expanded to the
types used and qualified type names are shortened. The pass attributes the files together with javac, so their
dependencies must be resolvable. Where upstream then fails the run, Elide warns, shows javac's errors and formats the
files without the pass. Name the dependencies with javac's options (`--class-path`, `--module-path`, `--release` and the
rest jfmt accepts). Without `--class-path`, each file is attributed against the class path `elide install` exported for
the project it belongs to; `elide format --install` runs `elide install` first, which returns quickly when nothing needs
installing. Classes from files outside the run resolve through the source roots the files' package declarations imply,
unless `--source-path` names others. Standard input is formatted without the pass, as upstream does.

For example, a file using `List` from `import java.util.*;` and declaring a field as
`java.time.Instant created = java.time.Instant.now();` receives explicit imports for `List` and `Instant`, and uses
`Instant` in the field declaration and initializer. This needs type resolution; ordinary whitespace formatting does not.
When the pass reports missing types, install the owning project's dependencies or pass an explicit classpath and rerun
to obtain the import rewrites. Formatting can otherwise succeed with the warning and leave those imports unresolved.

With no files named, `--source-path` selects every Java source under it, as `jfmt --source-path` does, in place of the
project's sources; `--module-source-path` only sets where the pass looks for sources.

```bash
elide javaformat -- --jfmt --class-path libs/widgets.jar src/main/java
elide format --install -- --jfmt
```

### Format a selection

`--lines`, `--offset` and `--length` select part of one file, as they do for google-java-format. jfmt formats only the
selected code, then sorts imports and removes unused ones over the whole file. Passes that rewrite the whole file are
skipped for a selection: the import pass above, adding braces around statement bodies, and repeating until the output
is stable.

```bash
elide javaformat -- --jfmt --lines 10:24 src/main/java/demo/Wild.java
elide javaformat -- --jfmt --offset 120 --length 80 src/main/java/demo/Wild.java
```

Line ranges are one-based and inclusive; offsets and lengths count characters. A selection is not a guarantee that
imports stay untouched: unused-import removal and import ordering still apply to the entire file. Run without selection
flags when you want the type-based import pass and brace insertion as well.
