Skip to content

Commit 4f5ffd0

Browse files
plumpygoogle-java-format Team
authored and
google-java-format Team
committed
Link to instructions for properly configuring the IDE's JRE.
Pop up this warning once per-project per-launch, only when the Formatter is enabled (or at startup if the formatter is already enabled in the project). PiperOrigin-RevId: 513822794
1 parent 32a6c00 commit 4f5ffd0

File tree

8 files changed

+145
-14
lines changed

8 files changed

+145
-14
lines changed

README.md

+19-8
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,25 @@ presented when you first open a project offering to do this for you.)
4444
To enable it by default in new projects, use `File→Other Settings→Default
4545
Settings...`.
4646

47-
When enabled, it will replace the normal `Reformat Code` action, which can be
48-
triggered from the `Code` menu or with the Ctrl-Alt-L (by default) keyboard
49-
shortcut.
50-
51-
The import ordering is not handled by this plugin, unfortunately. To fix the
52-
import order, download the
53-
[IntelliJ Java Google Style file](https://raw.githubusercontent.com/google/styleguide/gh-pages/intellij-java-google-style.xml)
54-
and import it into File→Settings→Editor→Code Style.
47+
When enabled, it will replace the normal `Reformat Code` and `Optimize Imports`
48+
actions.
49+
50+
#### IntelliJ JRE Config
51+
52+
The google-java-format plugin uses some internal classes that aren't available
53+
without extra configuration. To use the plugin, go to `Help→Edit Custom VM
54+
Options...` and paste in these lines:
55+
56+
```
57+
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
58+
--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
59+
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
60+
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
61+
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
62+
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
63+
```
64+
65+
Once you've done that, restart the IDE.
5566

5667
### Eclipse
5768

idea_plugin/build.gradle

+6-4
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ publishPlugin {
5151
}
5252

5353
tasks.withType(Test).configureEach {
54-
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED"
55-
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED"
56-
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED"
57-
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"
54+
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"
55+
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"
56+
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED"
57+
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED"
58+
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED"
59+
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"
5860
}
5961

6062
dependencies {

idea_plugin/src/main/java/com/google/googlejavaformat/intellij/GoogleJavaFormatFormattingService.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ private static Formatter createFormatter(Style style, boolean canChangeWhiteSpac
7575
@Override
7676
public boolean canFormat(@NotNull PsiFile file) {
7777
return JavaFileType.INSTANCE.equals(file.getFileType())
78-
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled();
78+
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled()
79+
&& JreConfigurationChecker.checkJreConfiguration(file.getProject());
7980
}
8081

8182
@Override

idea_plugin/src/main/java/com/google/googlejavaformat/intellij/GoogleJavaFormatImportOptimizer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public class GoogleJavaFormatImportOptimizer implements ImportOptimizer {
3535
@Override
3636
public boolean supports(@NotNull PsiFile file) {
3737
return JavaFileType.INSTANCE.equals(file.getFileType())
38-
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled();
38+
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled()
39+
&& JreConfigurationChecker.checkJreConfiguration(file.getProject());
3940
}
4041

4142
@Override

idea_plugin/src/main/java/com/google/googlejavaformat/intellij/GoogleJavaFormatSettings.java

+9
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,14 @@
3030
storages = {@Storage("google-java-format.xml")})
3131
class GoogleJavaFormatSettings implements PersistentStateComponent<GoogleJavaFormatSettings.State> {
3232

33+
private final Project project;
34+
3335
private State state = new State();
3436

37+
GoogleJavaFormatSettings(Project project) {
38+
this.project = project;
39+
}
40+
3541
static GoogleJavaFormatSettings getInstance(Project project) {
3642
return ServiceManager.getService(project, GoogleJavaFormatSettings.class);
3743
}
@@ -56,6 +62,9 @@ void setEnabled(boolean enabled) {
5662
}
5763

5864
void setEnabled(EnabledState enabled) {
65+
if (enabled.equals(EnabledState.ENABLED)) {
66+
JreConfigurationChecker.checkJreConfiguration(project);
67+
}
5968
state.enabled = enabled;
6069
}
6170

idea_plugin/src/main/java/com/google/googlejavaformat/intellij/InitialConfigurationStartupActivity.java

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public void runActivity(@NotNull Project project) {
3737
if (settings.isUninitialized()) {
3838
settings.setEnabled(false);
3939
displayNewUserNotification(project, settings);
40+
} else if (settings.isEnabled()) {
41+
JreConfigurationChecker.checkJreConfiguration(project);
4042
}
4143
}
4244

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright 2023 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.googlejavaformat.intellij;
18+
19+
import com.google.common.base.Suppliers;
20+
import com.intellij.ide.ui.IdeUiService;
21+
import com.intellij.notification.Notification;
22+
import com.intellij.notification.NotificationType;
23+
import com.intellij.openapi.diagnostic.Logger;
24+
import com.intellij.openapi.project.Project;
25+
import java.util.function.Supplier;
26+
27+
class JreConfigurationChecker {
28+
29+
private final Supplier<Boolean> hasAccess = Suppliers.memoize(this::checkJreConfiguration);
30+
31+
private final Project project;
32+
private final Logger logger = Logger.getInstance(JreConfigurationChecker.class);
33+
34+
public JreConfigurationChecker(Project project) {
35+
this.project = project;
36+
}
37+
38+
static boolean checkJreConfiguration(Project project) {
39+
return project.getService(JreConfigurationChecker.class).hasAccess.get();
40+
}
41+
42+
/**
43+
* Determine whether the JRE is configured to work with the google-java-format plugin. If not,
44+
* display a notification with instructions and return false.
45+
*/
46+
private boolean checkJreConfiguration() {
47+
try {
48+
boolean hasAccess =
49+
testClassAccess(
50+
"com.sun.tools.javac.api.JavacTrees",
51+
"com.sun.tools.javac.code.Flags",
52+
"com.sun.tools.javac.file.JavacFileManager",
53+
"com.sun.tools.javac.parser.JavacParser",
54+
"com.sun.tools.javac.tree.JCTree",
55+
"com.sun.tools.javac.util.Log");
56+
if (!hasAccess) {
57+
displayConfigurationErrorNotification();
58+
}
59+
return hasAccess;
60+
} catch (ClassNotFoundException e) {
61+
logger.error("Error checking jre configuration for google-java-format", e);
62+
return false;
63+
}
64+
}
65+
66+
private boolean testClassAccess(String... classNames) throws ClassNotFoundException {
67+
for (String className : classNames) {
68+
if (!testClassAccess(className)) {
69+
return false;
70+
}
71+
}
72+
return true;
73+
}
74+
75+
private boolean testClassAccess(String className) throws ClassNotFoundException {
76+
Class<?> klass = Class.forName(className);
77+
return klass
78+
.getModule()
79+
// isExported returns true if the package is either open or exported. Either one is
80+
// sufficient
81+
// to run the google-java-format code (even though the documentation specifies --add-opens).
82+
.isExported(klass.getPackageName(), getClass().getClassLoader().getUnnamedModule());
83+
}
84+
85+
private void displayConfigurationErrorNotification() {
86+
Notification notification =
87+
new Notification(
88+
"Configure JRE for google-java-format",
89+
"Configure the JRE for google-java-format",
90+
"The google-java-format plugin needs additional configuration before it can be used. "
91+
+ "<a href=\"instructions\">Follow the instructions here</a>.",
92+
NotificationType.INFORMATION);
93+
notification.setListener(
94+
(n, e) -> {
95+
IdeUiService.getInstance()
96+
.browse(
97+
"https://github.com/google/google-java-format/blob/master/README.md#intellij-jre-config");
98+
n.expire();
99+
});
100+
notification.notify(project);
101+
}
102+
}

idea_plugin/src/main/resources/META-INF/plugin.xml

+3
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@
7575
displayName="google-java-format Settings"/>
7676
<projectService
7777
serviceImplementation="com.google.googlejavaformat.intellij.GoogleJavaFormatSettings"/>
78+
<projectService serviceImplementation="com.google.googlejavaformat.intellij.JreConfigurationChecker"/>
7879
<notificationGroup displayType="STICKY_BALLOON" id="Enable google-java-format"
7980
isLogByDefault="false"/>
81+
<notificationGroup displayType="STICKY_BALLOON" id="Configure JRE for google-java-format"
82+
isLogByDefault="true"/>
8083
<notificationGroup displayType="BALLOON" id="google-java-format parsing error"
8184
isLogByDefault="false"/>
8285
</extensions>

0 commit comments

Comments
 (0)