Using google-java-format with VS Code

Visual Studio Code, Java Posted on

I have been doing some Java development recently, and my preferred editors of choice bounce between Visual Studio Code and Neovim. My vim setup is configured to format Java source files using google-java-format, but I was struggling to achieve the same behavior in Visual Studio Code. This post explores how to format Java source files using google-java-format in VS Code.

TL;DR

Install emeraldwalk/vscode-runonsave:

$ code --install-extension emeraldwalk.RunOnSave

Install google-java-format for your system:

# Example using Homebrew on OS X
$ brew install google-java-format

Configure RunOnSave in Visual Studio Code settings:

{
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "\\.java$",
        "cmd": "google-java-format --replace ${file}"
      },
    ],
  },
}

Background

Google publishes a verbose Google Java style guide as well as google-java-format which reformats Java code according to that style guide. The formatter is available as a Java JAR and via popular package managers. For example, to install the formatter on OS X:

$ brew install google-java-format

Then, to format Java source files, pass them as arguments to the command:

$ google-java-format -i ./MyClass.java

Existing work

There are already popular plugins for google-java-format for IDEs like Eclipse and IntelliJ. Unfortunately no official ones exist for Visual Studio Code at the time of this writing. Before coming up with my own solution, I did some Internet searching.

The most popular answer comes from redhat-developer/vscode-java#419 which directs us to a Wiki page with instructions to edit some Visual Studio Code configuration:

{
  "java.format.settings.profile": "GoogleStyle",
  "java.format.settings.url": "https://raw.githubusercontent.com/google/styleguide/gh-pages/eclipse-java-google-style.xml",
}

This will instruct the editor to use the "GoogleStyle" when formatting code instead of the built-in style. This seemed like a great fit, since I am already using RedHat's Java Language Support.

While this does change the default format of the code, in my testing it did not match the output of running google-java-format directly from the command line. Worse, it modified things like license headers, rendering them invalid.

I also stumbled across Dev-Snippets/vscode-google-java-format-provider, which seemed promising, but I was unable to get it to register as a formatter (and I am not the only one).

Solution

I started down the path of writing my own Visual Studio Code plugin to run google-java-format as a formatter. After about 10 minutes into the exercise, I realized that this plugin was going to be quite dumb:

  1. Detect if the file is Java
  2. Run google-java-format -i ${file}
  3. Report any errors back to the user

Those steps are essentially "run a command on save", and it turns out someone has already written an extension! emeraldwalk/vscode-runonsave reads Visual Studio Code settings, matches files on a regular expression, and then runs a user-supplied command. This proved to be a minimal but perfect solution!

I installed RunOnSave and google-java-format on my Mac:

$ code --install-extension emeraldwalk.RunOnSave
$ brew install google-java-format

Then I configured RunOnSave to run google-java-format on files that end in .java in Visual Studio Code settings:

{
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "\\.java$",
        "cmd": "google-java-format --replace ${file}"
      },
    ],
  },
}

This requires google-java-format to be in my $PATH. If it was not, I could specify the full path to the binary instead:

{
  "cmd": "/usr/local/bin/google-java-format --replace ${file}"
}

After spending a few hours trying to reach parity between google-java-format and Visual Studio Code's formatOnSave, I feel like I have reached a perfect solution.

Hopefully this post was helpful. If you have questions or comments, please reach to me at @sethvargo Twitter.

About Seth

Seth Vargo is an engineer at Google. Previously he worked at HashiCorp, Chef Software, CustomInk, and some Pittsburgh-based startups. He is the author of Learning Chef and is passionate about reducing inequality in technology. When he is not writing, working on open source, teaching, or speaking at conferences, Seth advises non-profits.