Git Product home page Git Product logo

google-java-format's Introduction

google-java-format

google-java-format is a program that reformats Java source code to comply with Google Java Style.

Using the formatter

From the command-line

Download the formatter and run it with:

java -jar /path/to/google-java-format-${GJF_VERSION?}-all-deps.jar <options> [files...]

The formatter can act on whole files, on limited lines (--lines), on specific offsets (--offset), passing through to standard-out (default) or altered in-place (--replace).

To reformat changed lines in a specific patch, use google-java-format-diff.py.

Note: There is no configurability as to the formatter's algorithm for formatting. This is a deliberate design decision to unify our code formatting on a single format.

IntelliJ, Android Studio, and other JetBrains IDEs

A google-java-format IntelliJ plugin is available from the plugin repository. To install it, go to your IDE's settings and select the Plugins category. Click the Marketplace tab, search for the google-java-format plugin, and click the Install button.

The plugin will be disabled by default. To enable it in the current project, go to File→Settings...→google-java-format Settings (or IntelliJ IDEA→Preferences...→Other Settings→google-java-format Settings on macOS) and check the Enable google-java-format checkbox. (A notification will be presented when you first open a project offering to do this for you.)

To enable it by default in new projects, use File→Other Settings→Default Settings....

When enabled, it will replace the normal Reformat Code and Optimize Imports actions.

IntelliJ JRE Config

The google-java-format plugin uses some internal classes that aren't available without extra configuration. To use the plugin, go to Help→Edit Custom VM Options... and paste in these lines:

--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

Once you've done that, restart the IDE.

Eclipse

The latest version of the google-java-format Eclipse plugin can be downloaded from the releases page. Drop it into the Eclipse drop-ins folder to activate the plugin.

The plugin adds a google-java-format formatter implementation that can be configured in Window > Preferences > Java > Code Style > Formatter > Formatter Implementation.

Third-party integrations

as a library

The formatter can be used in software which generates java to output more legible java code. Just include the library in your maven/gradle/etc. configuration.

google-java-format uses internal javac APIs for parsing Java source. The following JVM flags are required when running on JDK 16 and newer, due to JEP 396: Strongly Encapsulate JDK Internals by Default:

--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

Maven

<dependency>
  <groupId>com.google.googlejavaformat</groupId>
  <artifactId>google-java-format</artifactId>
  <version>${google-java-format.version}</version>
</dependency>

Gradle

dependencies {
  implementation 'com.google.googlejavaformat:google-java-format:$googleJavaFormatVersion'
}

You can then use the formatter through the formatSource methods. E.g.

String formattedSource = new Formatter().formatSource(sourceString);

or

CharSource source = ...
CharSink output = ...
new Formatter().formatSource(source, output);

Your starting point should be the instance methods of com.google.googlejavaformat.java.Formatter.

Building from source

mvn install

Contributing

Please see the contributors guide for details.

License

Copyright 2015 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.

google-java-format's People

Contributors

alicederyn avatar awturner avatar brendandouglas avatar cgdecker avatar cgruber avatar cgrushko avatar chenrui333 avatar cpovirk avatar csamak avatar cushon avatar dependabot[bot] avatar eaftan avatar eamonnmcmanus avatar java-team-github-bot avatar jbduncan avatar jpd236 avatar kluever avatar mkanat avatar nakulj avatar netdpb avatar nreid260 avatar perezd avatar plumpy avatar ronshapiro avatar sherter avatar sormuras avatar timvdlippe avatar vorburger avatar winteryoung avatar wolfiemario avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

google-java-format's Issues

AOSP style should have an option for two space continuations

Problem

When formatting code to meet the AOSP style, the indention applied to code blocks with many continuations can make the code difficult to read. Here is an example inspired by code I have worked with:

    @Test
    public void fooTest() throws Exception {
        reaperThread.runOperationWhileReaperPaused(
                () -> {
                    try {
                        assertThat(
                                        storageService
                                                .listZfsHolds(firstLongVariableName, secondLongVariableName.method())
                                                .isEmpty())
                                .isTrue();
                    } catch (DatasetNotFoundException e) {
                        Throwables.propagate(e);
                    }
                });
    }

There are a few elements of this formatting which makes the code difficult to read:

  • The argument list for the lambda is on a separate line than the function to which it is passed. This makes it difficult to determine how the lambda is used. This issue is already described in Issue 19 odd formatting for lambdas.
  • The storageService variable is indented five spaces beyond the opening parenthesis of the argument list it is a part of. This makes it difficult to recognize that the storageService variable is the start of the expression which is passed to assertThat().
  • The isTrue() call is indented 27 spaces less than the expression on which it is invoked, and more jarringly, ends 6 spaces before the start of the previous line. This makes it difficult to determine the expression on which isTrue() is invoked. While in this specific instance the use of isTrue() could be avoided entirely by calling IterableSubject::isEmpty, it serves to illustrate the point at hand.

Taken as a whole, this code is difficult to read because the indentation used leads to closely-related segments of code being separated by lots of whitespace. This obfuscates the relationships between these code segments.

Proposed solution

A reasonable solution to this problem is to use two-space continuations rather than eight-space continuations when formatting code in the AOSP style. Before detailing the arguments in favor of this approach, I first present the above code, reformatted to use two-space continuations:

    @Test
    public void fooTest() throws Exception {
        reaperThread.runOperationWhileReaperPaused(
          () -> {
              try {
                  assertThat(
                      storageService
                        .listZfsHolds(firstLongVariableName, secondLongVariableName.method()).isEmpty())
                    .isTrue();
              } catch (DatasetNotFoundException e) {
                  Throwables.propagate(e);
              }
          });
    }

This does not solve the first problem listed above, but it does help with the other two. storageService is now quickly identifiable as the start of the expression passed to assertThat(), and while isTrue() still has slightly confusing indentation, it is no longer completely separated by whitespace from the expression it is invoked on.

I now turn to the general arguments for this solution.

Arguments for proposal

The first argument in favor of this proposal is that using two-space tabs for continuations reduces the overall number of continuations. This is because the second half of the continuation can be an additional six characters long before hitting the line length limit, reducing the likelihood that a second continuation will be required. Notice how isEmpty() is on its own line in the first code snippet, but is not in the second.

The second argument in favor of this proposal is that two-space continuations are just as effective as eight-space continuations. The purpose of using a separate tab width for a continuation is to indicate to the reader that the second half of the continuation is not the start of a new statement, but is, in fact, a continuation. It is not necessary to double the width of a standard tab to accomplish this. Rather, the tab width for a continuation must merely be different than the standard tab width; in this case, continuations must not be four spaces wide.

There is precedent for using a continuation tab width half that of that used for standard tabs. The C Style and Coding Standards for SunOS from Sun mandates exactly this. Section 13, Continuation Lines, specifies that a continuation "should be further indented by half a tab stop" than the above line. Given that the standard width of a tab stop in the SunOS source code is 8 spaces, it is easy to see why halving, rather than doubling, this width was desirable for continuation tabs. Given the extent to which expressions can be deeply nested in modern Java, the same can be said for continuations in the AOSP style.

Empty line between annotation and member is not removed

The code

public class Test {

  @Nullable

  public int f;  

  @Override

  public void m() {}
}

is output by google-java-format without changes, but I would expect it to remove the empty lines between the annotations and the members.

Should not delete wildcard imports

The tool deletes wildcard imports without leaving anything in their place, thus leading to uncompilable code.

Consider this code:

import java.util.*;

class UseList {
  List l;
}

which is transformed to this:


class UseList {
  List l;
}

JDK 9 module-info.java handling

Having a module-info.java in the source set leads to unexpected format exceptions starting with

src/main/java/module-info.java:1:1: error: Syntax error on token "module", package expected

Solution 1

Skip module-info.java although it ends with .java Line Main.java:118 already skips non-Java files. Could easily be handled here.

Solution 2

Support module-info.java syntax and reformat it as well.

google-java-format-diff.py is unusable without rolling your own wrapper script

google-java-format-diff.py assumes there is an executable in $PATH named "google-java-format", which is not part of any published releases. The basic instructions say to run with "java -jar", so to make this work, someone has to write a wrapper script. I am capable of rolling my own but it really seems like this should be part of the distribution.

Provide IntelliJ Code Styles XML

Square has a GitHub project that configures IntelliJ just the way we like it:
https://github.com/square/java-code-styles

Since a lot of users of this project will also be IntelliJ users, it would be quite excellent if the two tools would not conflict with each other on mechanical reformatting. The Square styles above are almost exactly perfect, though there are some tiny differences.

Like these:
new String[] { "a" }
new String[]{ "a" }

A definitive single source of truth for IntelliJ would be handy.

Windows support

The formatter makes some assumptions that don't work on Windows.

  • File.renameTo() is not portable (see #32)
  • The output always uses \n as a line terminator, we should probably use the platform terminator

Crash on annotated fully-qualified class names

The tool crashes on annotated fully-qualified class names.
Consider this test case:

import org.checkerframework.checker.nullness.qual.*;

public class FullyQualified {

    public void format1(java.lang.String a1, java.lang. @Nullable Object... a2) {
        // body
    }

}

Handle type annotations

We always want to format type annotations in-line:

@Nullable Object foo() {}

This is tricky in contexts where type annotations could be mixed together with declaration annotations, such as field, method, and variable declarations. There's no syntactic information to we can use to distinguish between @NullableType Object foo() {} and @Deprecated Object foo() {}, but we want to output the first annotation in-line, and the second vertically.

Currently, we output ambiguous annotations as declaration annotations. This is fine for Java 7, and has the advantage of never incorrectly formatting a declaration annotation as a type annotation.

Here are some possible heuristics we could use to support this case for Java 8:

  1. If the annotation occurs before a regular modifier, it's probably a declaration annotation:
@Deprecated
static Object foo() {}
  1. If the annotation occurs after regular modifiers, and it isn't on a void-returning method, it's probably a type annotation:
static @Nullable Object foo() {}
  1. If the declaration isn't a void-returning method, and it has no regular modifiers, consider the existing formatting: type annotations are probably on the same line as the type, declaration annotations are probably vertical. (The risk here is that we'd preserve things like @Override Object foo() {}.)

  2. If the declaration is named @Override, it's probably a declaration annotation. This would offset the disadvantage of (3), but it could be confusing if @Override behaves differently than other annotations.

  3. An annotation with parameters is unlikely to be a type annotation, and should probably be formatted vertically.

Regression in handling multi-line varargs

It seems a097084 introduced a regression.

Consider this Test.java:

import java.util.Arrays;

class Test {
  Wrapper w = new Wrapper(
    Arrays.asList(
      "a", "b",
      "c", "d",
      "e" 
    ), 2); 
}

Running the formatter built from the aforementioned revision against this file yields:

$ java -jar google-java-format/core/target/google-java-format-1.1-SNAPSHOT-all-deps.jar Test.java
Test.java: error: 9:8: error: did not generate token ""e""
java.lang.AssertionError: 9:8: error: did not generate token ""e""
    at com.google.googlejavaformat.OpsBuilder.sync(OpsBuilder.java:188)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.sync(JavaInputAstVisitor.java:3622)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.visit(JavaInputAstVisitor.java:1480)
    at org.eclipse.jdt.core.dom.NumberLiteral.accept0(NumberLiteral.java:136)
    at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.argList(JavaInputAstVisitor.java:3011)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.addArguments(JavaInputAstVisitor.java:2995)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.visit(JavaInputAstVisitor.java:731)
    at org.eclipse.jdt.core.dom.ClassInstanceCreation.accept0(ClassInstanceCreation.java:302)
    at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.declareOne(JavaInputAstVisitor.java:3303)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.addDeclaration(JavaInputAstVisitor.java:3401)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.visit(JavaInputAstVisitor.java:1007)
    at org.eclipse.jdt.core.dom.FieldDeclaration.accept0(FieldDeclaration.java:281)
    at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.addBodyDeclarations(JavaInputAstVisitor.java:3474)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.visit(JavaInputAstVisitor.java:1957)
    at org.eclipse.jdt.core.dom.TypeDeclaration.accept0(TypeDeclaration.java:453)
    at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
    at com.google.googlejavaformat.java.JavaInputAstVisitor.visit(JavaInputAstVisitor.java:404)
    at com.google.googlejavaformat.java.Formatter.format(Formatter.java:122)
    at com.google.googlejavaformat.java.Formatter.getFormatReplacements(Formatter.java:188)
    at com.google.googlejavaformat.java.Formatter.formatSource(Formatter.java:166)
    at com.google.googlejavaformat.java.FormatFileCallable.call(FormatFileCallable.java:55)
    at com.google.googlejavaformat.java.FormatFileCallable.call(FormatFileCallable.java:28)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Interestingly, if one removes the second argument to Wrapper another exception occurs. I.e., given this file (notice the absence of ", 2"):

import java.util.Arrays;

class Test {
  Wrapper w = new Wrapper(
    Arrays.asList(
      "a", "b",
      "c", "d",
      "e" 
    )); 
}

We get this error:

$ java -jar google-java-format/core/target/google-java-format-1.1-SNAPSHOT-all-deps.jar Test.java
Test.java: error: null
java.lang.IllegalArgumentException
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:108)
    at com.google.googlejavaformat.FormatterDiagnostic.<init>(FormatterDiagnostic.java:26)
    at com.google.googlejavaformat.Input.createDiagnostic(Input.java:136)
    at com.google.googlejavaformat.OpsBuilder.sync(OpsBuilder.java:185)
    at com.google.googlejavaformat.java.Formatter.format(Formatter.java:123)
    at com.google.googlejavaformat.java.Formatter.getFormatReplacements(Formatter.java:188)
    at com.google.googlejavaformat.java.Formatter.formatSource(Formatter.java:166)
    at com.google.googlejavaformat.java.FormatFileCallable.call(FormatFileCallable.java:55)
    at com.google.googlejavaformat.java.FormatFileCallable.call(FormatFileCallable.java:28)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Re-flow /* */ comment blocks, including Javadoc

This is all intentionally disabled for now, but we should consider a project to outfit the formatter with a real Javadoc parser and let it fix up many aspects of Javadoc layout. And re-flow plain comments (only for /*, not groups of //).

Note that there is some amount of actual controversy about whether it should do this, so we should address that before doing too much work.

Rectangle rule indents lambdas 8 extra columns

Before: code in lambda is indented +2:

    transacter.executeWithRetries(session -> {
      boolean authenticated = appAuthenticator.isAuthenticated(session, appAuthorization);
      if (!authenticated) {
        logger.info("signOutApp failed for [appToken=%s]", appAuthorization.appToken);
        throw CashApiException.unauthorized();
      }
      appAuthenticator.revokeSession(session, appAuthorization.appToken, false);
    });

After: code in lambda is indented +10:

    transacter.executeWithRetries(
        session
            -> {
              boolean authenticated = appAuthenticator.isAuthenticated(session, appAuthorization);
              if (!authenticated) {
                logger.info("signOutApp failed for [appToken=%s]", appAuthorization.appToken);
                throw CashApiException.unauthorized();
              }
              appAuthenticator.revokeSession(session, appAuthorization.appToken, false);
            });

I think it's consistent with the rule, but this case seemed particularly harsh.

Sort imports

Are there any plans to add feature to sort and group imports as described on the style guide?

AssertionError for type annotations on arrays

google-java-format should handle type annotations on arrays, which are legal Java 8 syntax.

The following program compiles cleanly with javac (from JDK 8):

import java.lang.annotation.*;

@Target(ElementType.TYPE_USE)
@interface Interned {}

public class GjfTypeAnnotationOnArrayTest {

  public static void test() {
    String @Interned [] iarray1 = new String @Interned [2];
  }

}

However, when I run google-java-format on it, using this command:

java -jar google-java-format-1.0-all-deps.jar GjfTypeAnnotationOnArrayTest.java

google-java-format issues this message:

java.lang.AssertionError: GjfTypeAnnotationOnArrayTest.java:9:57: error: did not generate token "@"

Inconsistent treatment of **/ at end of Javadoc

After formatting, this:

public class DoubleTrailingAsterisk {

  /**
   * Here is a multi-line comment that ends with a double asterisk.
   **/
  public void m1() {}

  /** Here is a single-line comment that ends with a double asterisk. **/
  public void m2() {}
}

becomes this:

public class DoubleTrailingAsterisk {

  /** Here is a multi-line comment that ends with a double asterisk. */
  public void m1() {}

  /** Here is a single-line comment that ends with a double asterisk. * */
  public void m2() {}
}

where the second Javadoc comment contains an extra "*".

First comment is removed (partially)

Formatter formatter = new Formatter();
String result = formatter.formatSource(
  "/*\n" +
  " * my comment */");
System.out.println(result); // prints only "/*" (is the same for javadoc comments)

Seems like there is a problem if there is no \n after the first comment. If there is one (or any other valid source code) it works fine. It also seems to only effect the very first comment (or set of comments, if there is nothing else in between) in the file. Any further comment is printed as expected, even if there is no newline after it.

Should not compress all double spaces into one in Javadoc

The formatter removes all double spaces after colons and sentence-ending periods in Javadoc comments. In English, a sentence break implies a greater pause than between words, so well-formatted English text contains more space after a sentence-ending period. (Consider the output of LaTeX, for example.) Plaintext can be harder to read when authors do not conform to this long-standing convention.

I'm not proposing that google-java-format should put extra space after every period. However, I feel it should maintain double spaces after any period that has them, rather than removing them. That's what my text editor does when it fills paragraphs, and that works very well.

odd formatting for lambdas

are the extra newlines intentional?

before:

    Stream<ItemKey> itemIdsStream = stream(members)
        .flatMap(m -> m.getFieldValues()
            .entrySet()
            .stream()
            .filter(fv -> itemLinkFieldIds.contains(fv.getKey()))
            .flatMap(fv -> FieldDTO.deserializeStringToListOfStrings(fv.getValue())
                .stream()
                .map(id -> new ItemKey(fieldsById.get(fv.getKey()).getItemTypeId(), id))));

or even

    Stream<ItemKey> itemIdsStream =
        stream(members)
            .flatMap(
                m -> m.getFieldValues()
                    .entrySet()
                    .stream()
                    .filter(fv -> itemLinkFieldIds.contains(fv.getKey()))
                    .flatMap(
                        fv -> FieldDTO.deserializeStringToListOfStrings(fv.getValue())
                            .stream()
                            .map(
                                id -> new ItemKey(
                                    fieldsById.get(fv.getKey()).getItemTypeId(), id))));

after:

    // items
    Stream<ItemKey> itemIdsStream =
        stream(members)
            .flatMap(
                m ->
                    m.getFieldValues().entrySet().stream()
                        .filter(fv -> itemLinkFieldIds.contains(fv.getKey()))
                        .flatMap(
                            fv ->
                                FieldDTO.deserializeStringToListOfStrings(fv.getValue()).stream()
                                    .map(
                                        id ->
                                            new ItemKey(
                                                fieldsById.get(fv.getKey()).getItemTypeId(), id))));

Extra newlines on type annotations

Input: one group of fields:

    private DbIncomingEmail incomingEmail;
    private CreationMechanism creationMechanism;
    private @Nullable String creationUserAgent;
    private ClientId clientId;
    private Token externalId;

Output: three groups of fields, because the 3rd field has @Nullable.

    private DbIncomingEmail incomingEmail;
    private CreationMechanism creationMechanism;

    private @Nullable String creationUserAgent;

    private ClientId clientId;
    private Token externalId;

Is this a bug?

Crash on annotated nested class names

The tool crashes on annotated nested class names.
Consider this test case:

import org.checkerframework.checker.tainting.qual.*;
class Outer {
    class Nested {
        @Untainted Outer context(@Untainted Outer.@Untainted Nested this) {
            return Outer.this;
        }
    }
}

Does the formatter normalize its input?

In other words, if I insert/remove arbitrary whitespace before running the formatter, will I always get the same output? Or are there some things like line wrappings that the formatter will preserve if encountered but not insert itself? I haven't decided which approach I'd prefer but I'm sure you've thought about it.

Provide an artifact that shades or omits Guava and other dependencies

As noted in google/dagger#228 (comment) and the comment it replies to, the google-java-format jar contains classes from Guava and other dependencies. Those classes end up in Dagger, where they conflict with the version of Guava used by Dagger -- and, because of Maven's lack of support for -processorpath, with the version of Guava used by Dagger users like Caliper.

I don't know enough about Maven to say what the right thing here is. The easiest thing, I'd guess, is shading, but for all I know, this may be difficult with the Eclipse classes for some reason.

Should not remove HTML closing tags in Javadoc

I have written my Javadoc to contain HTML closing tags. For example, each time there is a <li> tag, my Javadoc contains a matching </li> tag. This is required by HTML/XML standards. I do recognize that many browsers can handle lack of these tags, but having the matching tags makes browsers run faster, enables use of other tools, and can help to find errors. Parts of my toolchain expect the closing tags.

google-java-format gratuitously removes these matching tags.

It would be preferable for google-java-format to insert the matching tags when they are missing. If this is not done, then when a closing tag is present, it should be maintained rather than deleted.

Here is a test case:

/**
 * The command-line options are as follows:
 *
 * <ul>
 * <li id="option:date">--date=string. first date to summarize [default today]</li>
 * <li id="option:days">--days=int. number of calendar days to summarize [default 8]</li>
 * </ul>
 */
public final class ClosingTag {}

Errors building intellij plugin

I've encountered a number of issues while attempting to build the intellij plugin. Let me know if you would like me to file all of these as separate issues.

  1. The install-idea-jars.sh script does not work on osx. It expects a path like /opt/jetbrains/idea-IU-141.178.9 but on osx the path is something like /Applications/IntelliJ\ IDEA\ 15\ CE.app/Contents/ Even a zip download is by default in this format ideaIU-14.1.6.zip
  2. The for loop in install-idea-jars.sh fails when the ideaHomeDir path contains spaces, like it will on osx.
  3. Building the plugin requires exactly 141.178.9 which corresponds to release 14.1.4, so you have to have exactly this version installed. install-idea-jars.sh will install the jars from any version of intellij, so this requirement is not clear up front. As far as I can tell, this release is not available from jetbrains anymore. The closest I could find is 14.1.6. I also tried checking out the source for 141.178.9, but that doesn't seem to include all of the necessary libraries. And compiling intellij from source is a project by itself.
  4. I tried installing the 14.1.6 libraries as 14.1.4 libraries, but I get this error when compiling:
    /Users/adamcook/code/google-java-format/idea_plugin/src/main/java/com/google/googlejavaformat/intellij/GoogleJavaFormatCodeStyleManager.java:47: error: GoogleJavaFormatCodeStyleManager is not abstract and does not override abstract method reformatTextWithContext(PsiFile,Collection<TextRange>) in CodeStyleManager public class GoogleJavaFormatCodeStyleManager extends CodeStyleManagerDecorator {
    This could just be because I am not actually using the right library version.

Thanks!

Inline array line wrapping is surprising

Array elements are +6 where I'd expect +8. (IntelliJ does +8).

        csvWriter.writeNext(
            new String[] {
              Rest.formatIso8601UtcDate(row.date),
              row.movementType.summary(),
              "",
              "",
              "",
              row.amount.currency().name(),
              Long.toString(row.amount.cents())
            });

Formatting of empty types is not idempotent

The code

public class Test {

}

is formatted by google-java-format to

public class Test {
}

and if it is run again on the result the output of the second run is

public class Test {}

I think this should be done in one step. It occurred originally for me on an annotation with no members.

Crash on annotated cast

The tool crashes on this input:

public class AnnotatedCast {

    public static @Sibling1 int convertSibling2ToSibling1(@Sibling2 int a) {
        return (@Sibling1 int) 1;
    }

}

Building the executable

Hi,

How do I generate the google-java-format executable/binary? I'm not familiar with Maven. I did run mvn compile though.

Documentation does not reflect API

The documentation states:

You can then use the formatter quite simply using the various formatSource methods. E.g.

String formattedSource = Formatter.formatSource(sourceString);

However formatSource is not a static method on Formatter.

I am unsure of the correct solution. Either the documentation should recommend using a Formatter instance and call the non-static method formatSource or the documentation should recommend using the static method format.

NullPointerException when removing unused imports

The stacktrace:

java.lang.NullPointerException
        at com.google.googlejavaformat.java.RemoveUnusedImports$UnusedImportScanner.recordSimpleName(RemoveUnusedImports.java:123)
        at com.google.googlejavaformat.java.RemoveUnusedImports$UnusedImportScanner.recordReference(RemoveUnusedImports.java:118)
        at com.google.googlejavaformat.java.RemoveUnusedImports$UnusedImportScanner.recordTag(RemoveUnusedImports.java:105)
        at com.google.googlejavaformat.java.RemoveUnusedImports$UnusedImportScanner.access$000(RemoveUnusedImports.java:77)
        at com.google.googlejavaformat.java.RemoveUnusedImports$UnusedImportScanner$1.visit(RemoveUnusedImports.java:88)
        at org.eclipse.jdt.core.dom.TagElement.accept0(TagElement.java:278)
        at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
        at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2782)
        at org.eclipse.jdt.core.dom.TagElement.accept0(TagElement.java:280)
        at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
        at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2782)
        at org.eclipse.jdt.core.dom.Javadoc.accept0(Javadoc.java:205)
        at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
        at com.google.googlejavaformat.java.RemoveUnusedImports$UnusedImportScanner.visit(RemoveUnusedImports.java:84)
        at org.eclipse.jdt.core.dom.Javadoc.accept0(Javadoc.java:202)
        at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
        at org.eclipse.jdt.core.dom.ASTNode.acceptChild(ASTNode.java:2759)
        at org.eclipse.jdt.core.dom.MethodDeclaration.accept0(MethodDeclaration.java:614)
        at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
        at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2782)
        at org.eclipse.jdt.core.dom.TypeDeclaration.accept0(TypeDeclaration.java:470)
        at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
        at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2782)
        at org.eclipse.jdt.core.dom.CompilationUnit.accept0(CompilationUnit.java:212)
        at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2711)
        at com.google.googlejavaformat.java.RemoveUnusedImports.removeUnusedImports(RemoveUnusedImports.java:153)
        at com.google.googlejavaformat.java.FormatFileCallable.call(FormatFileCallable.java:44)
        at com.google.googlejavaformat.java.FormatFileCallable.call(FormatFileCallable.java:28)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

The class where it happens:

package com.gabrielittner.db;

import java.io.Closeable;
import java.util.concurrent.TimeUnit;

/**
 * An in-progress database transaction.
 */
public interface Transaction extends Closeable {
    /**
     * End a transaction. See {@link ReactiveDatabase#newTransaction()} for notes about how to
     * use this and when transactions are committed and rolled back.
     */
    void end();

    /**
     * Marks the current transaction as successful. Do not do any more database work between
     * calling this and calling {@link #end()}. Do as little non-database work as possible in that
     * situation too. If any errors are encountered between this and {@link #end()} the transaction
     * will still be committed.
     */
    void markSuccessful();

    /**
     * Temporarily end the transaction to let other threads run. The transaction is assumed to be
     * successful so far. Do not call {@link #markSuccessful()} before calling this. When this
     * returns a new transaction will have been created but not marked as successful. This assumes
     * that there are no nested transactions (newTransaction has only been called once) and will
     * throw an exception if that is not the case.
     *
     * @return true if the transaction was yielded
     */
    boolean yieldIfContendedSafely();

    /**
     * Temporarily end the transaction to let other threads run. The transaction is assumed to be
     * successful so far. Do not call {@link #markSuccessful()} before calling this. When this
     * returns a new transaction will have been created but not marked as successful. This assumes
     * that there are no nested transactions (newTransaction has only been called once) and will
     * throw an exception if that is not the case.
     *
     * @param sleepAmount if > 0, sleep this long before starting a new transaction if
     *                    the lock was actually yielded. This will allow other background threads
     *                    to make some more progress than they would if we started the transaction
     *                    immediately.
     * @return true if the transaction was yielded
     */
    boolean yieldIfContendedSafely(long sleepAmount, TimeUnit sleepUnit);

    /**
     * Equivalent to calling {@link #end()}
     */
    @Override
    void close();
}

I've used a jar built from the latest commit 70ab4ac.

Unused static import not removed

Running google-java-format didn't remove this unused import import static java.util.stream.Collectors.toList. In that class a different non-static toList() method was used. After removing the usages of the other toList the unused import was removed by google-java-format.

Local classes produce - error: generated extra token ";"

Local classes generate a error: generated extra token ";" error and the file fails to be formatted.

Yes, I'm aware this isn't a healthy pattern, but it's what I have and barring a refactor I'm stuck with it for now. It is valid Java and I'm pretty sure the formatter shouldn't choke on it.

// some stuff
} else if (command.equals("Some command")) {
  JDialog dialog = new JDialog(this, "Launching Some command...");
  class ProgressWorker<JDialog,String> extends ProgressSwingWorker {
    public ProgressWorker(javax.swing.JDialog dialog,
        java.lang.String title) {
      super(dialog, title);
    }

    @Override
    public Object construct() {
      // TODO Auto-generated method stub
      return null;
    }
  }; // <=== this is the token that the formatter chokes on
  // some more stuff

In place format does not preserve file attributes

Steps to reproduce

  1. Create a Java file whose permissions do not match the default permissions for new files on your system. For example, if your Linux system's default permissions for new files are to not have the execute bit set, create a file with the execute bit set; or if your Windows system's default permissions for new files are to have the execute bit set, create a file with the execute bit not set.
  2. Run google-java-format with the -i option to format the file in place.

Expected result

The file is formatted in place and retains its non-default permissions.

Actual result

The file is formatted in place, but its permissions revert to the default permissions.

SortImports option is ignored

No matter which SortImports option I set (ONLY, ALSO or NO), the imports are never sorted and it always returns the same result. Am I missing something here?

public static void main(String[] args) throws FormatterException {
  JavaFormatterOptions options = new JavaFormatterOptions(JavadocFormatter.NONE, Style.GOOGLE, SortImports.ONLY);
  Formatter formatter = new Formatter(options);
  String result = formatter.formatSource("package com.google.example;\n" +
                "\n" +
                "import com.google.common.base.Preconditions;\n" +
                "\n" +
                "import org.junit.runner.RunWith;\n" +
                "import org.junit.runners.JUnit4;\n" +
                "\n" +
                "import java.util.List;\n" +
                "\n" +
                "import javax.annotations.Nullable;\n" +
                "\n" +
                "import static org.junit.Assert.fail;\n" +
                "import static com.google.truth.Truth.assertThat;\n" +
                "\n" +
                "@RunWith( JUnit4.class ) public class SomeTest  {}");
  System.out.println(result);
}

Maven plugin

Support using Google Java Format as part a build in Maven thru a plugin.
Google coding styles helps a great deal to apply a common scheme to a code
repository. Although, there are ways to share/automate workspace settings,
it essentially relies on developer to follow and apply the coding styles.
As a build plugin, the formatting of the source can be applied before
any commit, during builds on CI/CD servers and other applications.

Interest in GUI?

Obviously this tool is meant for developers, who should know how to use the terminal. Still, I think it would add a lot to the project if there were an option to use a GUI to select the code to format. If this is in line with project goals, I would definitely work to add one in.

Documentation about thread safety of formatter is missing

I couldn't find any information about the thread safety of the formatter in the documentation, so I'm asking here and suggest to improve the documentation in this regard.

Is it safe to use the same com.google.googlejavaformat.java.Formatter instance concurrently from multiple threads, assuming that I'm reading/writing different files?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.