Javaimports updates Java import lines, adding missing ones.
Run it with:
java -jar /path/to/javaimports-1.0-all-deps.jar <options> file
Usage: javaimports [options] file
Options:
--assume-filename, -assume-filename
File name to use for diagnostics when importing standard input (default is .).
--fix-only
Do not format ouput, simply add and remove imports.
--metrics-datadog-port, -metrics-datadog-port
Port to use when --metrics-enable is set (default is 8125).
--metrics-datadog-host, -metrics-datadog-host
Host to use when --metrics-enable is set (default is "localhost").
--metrics-enable, -metrics-enable
Enable metrics reporting to a datadog agent running on the specified port and host.
--replace, -replace, -r, -w
Write result to source file instead of stdout.
--repository, -repository
Absolute path to the directory containing dependency JARs (default is /your/home/.m2/repository).
--telemetry-enable, -telemetry-enable
Enable telemetry. Shorthand for --tracing-enable and --metrics-enable.
--tracing-enable, -tracing-enable
Enable tracing reporting to a datadog agent listening at http://localhost:8126.
--verbose, -verbose, -v
Verbose logging.
--version, -version
Print the version.
--help, -help, -h
Print this usage statement.
File:
setting file equal to '-' will read from stdin
javaimports
will find imports using the following methods, by order of decreasing priority:
- mimicking imports from files in the same folder (if you're using
import my.custom.List
in a file of the same package,List<String> test;
will automatically importmy.custom.List
), - fetching imports from the standard java library (defined here for java 8 for instance).
- fetching imports from other files in the same project
- fetching imports from dependencies
For now, the only version of the standard library supported is Java 8. Steps after 3. use build-system-specific information, and currently only support Maven.
Javaimports comes with experimental support for
native-image
. This will considerably
speed up execution of javaimports
(including the formatting if not using --fix-only
), especially
in projects with few dependencies.
This comes at the price of dynamic version support: javaimports
built with native-image
will
only support language features of versions inferior or equal to the Graal JDK version used to build
it. This is because javaimports
(like google-java-format
) relies on the parser provided by the
jdk.
The current setup of javaimports
will work well with Java 17 using graalvm64-17.0.6
, that you
can download here.
To compile javaimports
with native-image
, make sure you are using the right java version, then
run mvn package -Pnative-image
. You will find the executable in
native-image/target/javaimports-native-image
. To run it, you need to pass it the path to your java
home, like so:
./javaimports-native-image -Djava.home=/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home [other flags] <file>"
Enjoy the blazing-fast formatting! 🎉
Dev note: You can validate that the native-image build is working correctly by running mvn verify -Pnative-image
which will run the native-image specific integration tests.
IMPORTANT:
Versions of javaimports
newer than 1.4-SNAPSHOT (rev. 5b66400)
come packaged with a feature
than will read .jar
files in order to find identifiers provided by parent classes. This feature
will NOT work with native-image
due to the following:
java.net.MalformedURLException: Accessing an URL protocol that was not enabled. The URL protocol jar is not tested and might not work as expected. It can be enabled by adding the --enable-url-protocols=jar option to the native-image command.
This is a known limitation, other javaimports
features will still work.
In order to help contributors debug and find bottlenecks, javaimports
can optionally emit traces
and metrics that will be picked up by a Datadog agent. This is disabled by default, see options to
enable it.
Before developing in Java, I used to work in Go, using VIM. During that time, I learned to love
command line tools such as gofmt
(an automatic code formatter) and goimports
(a tool that adds
and removes import
lines), that allowed me to focus on what I was writing and not how I was
organizing it. Moving on to Java, I found
google-java-format
to be a fit replacement for
gofmt
, but I unfortunately was not able to find the equivalent of goimports
. I then decided to
create javaimports
to fill this void.
Being a work in progress, any bug report or feature request for javaimports
is welcome! But there
are a few core principles that guide javaimports
's development, from which I won't deviate.
javaimports
will always be:
Unfortunately, compiling Java is often slow. But javaimports
should be convenient to use as a file
is being written. This means javaimports
does not rely on anything being compiled (except dependencies).
And it will stay that way.
Yes, I am aware that some tools exist that rely on a java language server. These are probably more
powerful, but the goal of javaimports
is to stay simple and stateless. I feel like most
everyday situations can be resolved without resorting to overly powerful solutions. And when the
need arises, manually writing one import line is still an option :)
The goal of javaimports
is to be runnable in the background (every time a file is saved, for
example). For this very reason, everything is decided without user input. This means that ambiguous
names will always be resolved without choice.
For example, consider a project using both JUnit4 and JUnit5. If you write a new file with @Test
,
javaimports
has no way to know if it should import org.junit.Test
or
org.junit.jupiter.api.Test
. One of the two will be picked arbitrarily!
Of course, the point of javaimports
is trying to be as smart as possible regarding such conflicts.
It will use all the information at its disposal to make the most sensible decision possible. For
instance, it will look at what you are using in other similar files, what you've already
imported, the other things you need to import, etc.
When there is no such information, the only way is to manually write the import line (javaimports
will never overwrite import lines). Fortunately, this should not happen too often.
When there is no other way, javaimports
will assume that the code it is being ran on follows some
widespread good practices, such as:
- Classes start with a capital letter, while package names do not contain capital letters
- Not relying on transitive dependencies to use non-explicitly-declared dependencies
Breaking the assumption won't stop javaimports
from doing its best, but it will break some
features. You have been warned!
javaimports
only does one thing, and that is adding missing import lines. It does not format
anything. For convenience, it comes packaged with
google-java-format
, but you are free to not use it
if you'd like (--fix-only
option of the CLI).