google-java-format icon indicating copy to clipboard operation
google-java-format copied to clipboard

Intellij plugin seems to stop working when Java 14/15 features are used

Open fhediger opened this issue 5 years ago • 11 comments

I use the latest google-java-format Intellij plugin based on google-java-format 1.9. As I understand it, this version should support Java 14/15 features like switch expressions and text blocks. In our case if any of the mentioned language features are used formatting stops working.

Just wanted to ask whether this may be a bug in my setup or if you're seeing the same problems?

Intellij IDEA Version: Ultimate Edition 2020.2.3 (Build #IU-202.7660.26, built on October 6, 2020)

Operating System: Ubuntu 20.04.1 LTS

Here is a small example:

public class FormatTest {
  enum Test {
    A, B
  }
  public static void main(String[] args) {
    String foo =                  "This should not be here";
    Test t = Test.A;
    String foobar = switch(t) {
      case A -> "foobar";
      case B -> "barfoo";
    };
    String xyz = """
            """;
  }
}

When I try to format this inside the IDE nothing happens. It shows that it's reformatting the code but the formatting doesn't change.There is no error as far as I can see.

However, formatting it with google-java-format-1.9-all-deps.jar it outputs correctly:

public class FormatTest {
  enum Test {
    A,
    B
  }

  public static void main(String[] args) {
    String foo = "This should not be here";
    Test t = Test.A;
    String foobar =
        switch (t) {
          case A -> "foobar";
          case B -> "barfoo";
        };
    String xyz = """
            """;
  }
}

Any help concerning this issue would be very much appreciated! Thanks for your great work!

fhediger avatar Oct 16 '20 09:10 fhediger

@plumpy seems like #517 didn't fix that?

andrej-urvantsev avatar Oct 16 '20 13:10 andrej-urvantsev

Can report the same (using google-java-format plugin 1.9.0.0 and intellij 2020.2).

I think this is because the default Intellij runtime still uses jdk 11 (at least for 2020.2 and lower). Based on that, the formatter will not load the Java14InputAstVisitor (code ref).

After manually switching my intellij runtime to one that uses jdk 15 (following this guide), the formatter worked as expected with java 14 language features. However this is not recommended as there are minor differences in the intellij runtime.

fawind avatar Nov 18 '20 13:11 fawind

Thank you @fawind, worked fine here! :)

rosanas88 avatar Jan 21 '21 20:01 rosanas88

@fawind Tried following the guide you mentioned, but the Choose Runtime approach isn't giving me any success. Did you follow the steps for manually changing your runtime version, or if not, what version of the runtime did you use? 🤔

linuswillner avatar Mar 01 '21 18:03 linuswillner

As an alternative workaround to changing IntelliJ's runtime JDK version, we can also use IntelliJ's External Tool feature to run the formatter as an external command using a different JDK:

Arguments:

-Xmx256m
-XX:TieredStopAtLevel=1
--add-exports jdk.compiler/com.sun.tools.javac.api=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
-jar <download-the-latest-all-deps-jar>/google-java-format-1.10.0-all-deps.jar
--replace $FilePath$

In the above screenshot, it's configured to use the same JDK as the one used to compile the project to run the formatter ($JDKPath$), added -XX:TieredStopAtLevel=1 too as it seems to make it run quicker for me, since the format process will be short lived.

Then under Keymap in IntelliJ's main settings, bind it to a keyboard shortcut to invoke it.

laech avatar Jun 27 '21 21:06 laech

I don't know if this is a stupid question but why should the version of JVM running the formatter be assumed to be the same version as the code it's formatting? Is there something in Java14InputAstVisitor that can't run on Java 11? Even if it was behind a flag I don't understand why it shouldn't just load the rules. IntelliJ itself obviously doesn't have this problem.

chadselph avatar Jul 28 '21 21:07 chadselph

As an alternative workaround to changing IntelliJ's runtime JDK version, we can also use IntelliJ's External Tool feature to run the formatter as an external command using a different JDK:

Arguments:

-Xmx256m
-XX:TieredStopAtLevel=1
--add-exports jdk.compiler/com.sun.tools.javac.api=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
-jar <download-the-latest-all-deps-jar>/google-java-format-1.10.0-all-deps.jar
--replace $FilePath$

In the above screenshot, it's configured to use the same JDK as the one used to compile the project to run the formatter ($JDKPath$), added -XX:TieredStopAtLevel=1 too as it seems to make it run quicker for me, since the format process will be short lived.

Then under Keymap in IntelliJ's main settings, bind it to a keyboard shortcut to invoke it.

Thanks for the external tools, working great.

farnots avatar Aug 13 '21 11:08 farnots

the same problem occurs if you run the gradle spotless plugin and configure google java format with java 17 source code and gradle using java 11.

bjrke avatar Sep 17 '21 09:09 bjrke

@bjrke for some reason intellij does not by default use the project JVM for the build tool; you can set it here https://www.jetbrains.com/help/idea/gradle-settings.html#gradle_jvm

chadselph avatar Sep 17 '21 15:09 chadselph

@chadselph I think it's different - for me gradle builds works fine, it's when you try to format code using built-in formatter, then it does not work(probably because IDEA is still on java 11)

andrej-urvantsev avatar Sep 18 '21 07:09 andrej-urvantsev

In our fork of google-java-format, we solved this with the workaround of bootstrapping a new JVM to run the formatter in (code example). In the Intellij plugin, we retrieve the path of the project JDK and and use this JDK to run the formatter main class. This allows us to also set the additional --add-export flags that are now required at runtime for Java 16+ (ref).

The downside is that it adds some latency to each format action but this has been tolerable so far and unblocks projects that want to use newer language features.

Might be worth considering doing something similar here. Happy to contribute this back if wanted!

fawind avatar Nov 15 '21 14:11 fawind

Apparently this is tied to the runtime version of IntelliJ itself. According to this table starting with version 2022.2 IntelliJ uses JDK 17. Therefore, once you upgrade to that version or newer, I think this issue is resolved?

TimvdLippe avatar Mar 01 '23 13:03 TimvdLippe

Note that you'll have to update IntelliJ's configuration to add custom VM options; see #787

tbroyer avatar Mar 01 '23 14:03 tbroyer

This should be fixed if you use the newest version of the plugin (1.16.0.0) with Intellij 2022.3.

plumpy avatar Mar 03 '23 20:03 plumpy