Skip to content

Commit

Permalink
Link to instructions for properly configuring the IDE's JRE.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
plumpy authored and google-java-format Team committed Mar 3, 2023
1 parent 32a6c00 commit 4f5ffd0
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 14 deletions.
27 changes: 19 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,25 @@ 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` action, which can be
triggered from the `Code` menu or with the Ctrl-Alt-L (by default) keyboard
shortcut.

The import ordering is not handled by this plugin, unfortunately. To fix the
import order, download the
[IntelliJ Java Google Style file](https://raw.githubusercontent.com/google/styleguide/gh-pages/intellij-java-google-style.xml)
and import it into File→Settings→Editor→Code Style.
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

Expand Down
10 changes: 6 additions & 4 deletions idea_plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ publishPlugin {
}

tasks.withType(Test).configureEach {
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED"
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED"
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED"
jvmArgs += "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED"
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED"
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED"
jvmArgs += "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ private static Formatter createFormatter(Style style, boolean canChangeWhiteSpac
@Override
public boolean canFormat(@NotNull PsiFile file) {
return JavaFileType.INSTANCE.equals(file.getFileType())
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled();
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled()
&& JreConfigurationChecker.checkJreConfiguration(file.getProject());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public class GoogleJavaFormatImportOptimizer implements ImportOptimizer {
@Override
public boolean supports(@NotNull PsiFile file) {
return JavaFileType.INSTANCE.equals(file.getFileType())
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled();
&& GoogleJavaFormatSettings.getInstance(file.getProject()).isEnabled()
&& JreConfigurationChecker.checkJreConfiguration(file.getProject());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,14 @@
storages = {@Storage("google-java-format.xml")})
class GoogleJavaFormatSettings implements PersistentStateComponent<GoogleJavaFormatSettings.State> {

private final Project project;

private State state = new State();

GoogleJavaFormatSettings(Project project) {
this.project = project;
}

static GoogleJavaFormatSettings getInstance(Project project) {
return ServiceManager.getService(project, GoogleJavaFormatSettings.class);
}
Expand All @@ -56,6 +62,9 @@ void setEnabled(boolean enabled) {
}

void setEnabled(EnabledState enabled) {
if (enabled.equals(EnabledState.ENABLED)) {
JreConfigurationChecker.checkJreConfiguration(project);
}
state.enabled = enabled;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public void runActivity(@NotNull Project project) {
if (settings.isUninitialized()) {
settings.setEnabled(false);
displayNewUserNotification(project, settings);
} else if (settings.isEnabled()) {
JreConfigurationChecker.checkJreConfiguration(project);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2023 Google Inc. All Rights Reserved.
*
* 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.
*/

package com.google.googlejavaformat.intellij;

import com.google.common.base.Suppliers;
import com.intellij.ide.ui.IdeUiService;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import java.util.function.Supplier;

class JreConfigurationChecker {

private final Supplier<Boolean> hasAccess = Suppliers.memoize(this::checkJreConfiguration);

private final Project project;
private final Logger logger = Logger.getInstance(JreConfigurationChecker.class);

public JreConfigurationChecker(Project project) {
this.project = project;
}

static boolean checkJreConfiguration(Project project) {
return project.getService(JreConfigurationChecker.class).hasAccess.get();
}

/**
* Determine whether the JRE is configured to work with the google-java-format plugin. If not,
* display a notification with instructions and return false.
*/
private boolean checkJreConfiguration() {
try {
boolean hasAccess =
testClassAccess(
"com.sun.tools.javac.api.JavacTrees",
"com.sun.tools.javac.code.Flags",
"com.sun.tools.javac.file.JavacFileManager",
"com.sun.tools.javac.parser.JavacParser",
"com.sun.tools.javac.tree.JCTree",
"com.sun.tools.javac.util.Log");
if (!hasAccess) {
displayConfigurationErrorNotification();
}
return hasAccess;
} catch (ClassNotFoundException e) {
logger.error("Error checking jre configuration for google-java-format", e);
return false;
}
}

private boolean testClassAccess(String... classNames) throws ClassNotFoundException {
for (String className : classNames) {
if (!testClassAccess(className)) {
return false;
}
}
return true;
}

private boolean testClassAccess(String className) throws ClassNotFoundException {
Class<?> klass = Class.forName(className);
return klass
.getModule()
// isExported returns true if the package is either open or exported. Either one is
// sufficient
// to run the google-java-format code (even though the documentation specifies --add-opens).
.isExported(klass.getPackageName(), getClass().getClassLoader().getUnnamedModule());
}

private void displayConfigurationErrorNotification() {
Notification notification =
new Notification(
"Configure JRE for google-java-format",
"Configure the JRE for google-java-format",
"The google-java-format plugin needs additional configuration before it can be used. "
+ "<a href=\"instructions\">Follow the instructions here</a>.",
NotificationType.INFORMATION);
notification.setListener(
(n, e) -> {
IdeUiService.getInstance()
.browse(
"https://github.com/google/google-java-format/blob/master/README.md#intellij-jre-config");
n.expire();
});
notification.notify(project);
}
}
3 changes: 3 additions & 0 deletions idea_plugin/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,11 @@
displayName="google-java-format Settings"/>
<projectService
serviceImplementation="com.google.googlejavaformat.intellij.GoogleJavaFormatSettings"/>
<projectService serviceImplementation="com.google.googlejavaformat.intellij.JreConfigurationChecker"/>
<notificationGroup displayType="STICKY_BALLOON" id="Enable google-java-format"
isLogByDefault="false"/>
<notificationGroup displayType="STICKY_BALLOON" id="Configure JRE for google-java-format"
isLogByDefault="true"/>
<notificationGroup displayType="BALLOON" id="google-java-format parsing error"
isLogByDefault="false"/>
</extensions>
Expand Down

0 comments on commit 4f5ffd0

Please sign in to comment.