Skip to content

Commit b853b9f

Browse files
authored
Merge pull request #81 from openjavaformat/plugin-descriptor-public-api
Take the plugin descriptor from PluginAware, not from PluginManager
2 parents 4479a4f + 789e9ea commit b853b9f

5 files changed

Lines changed: 76 additions & 32 deletions

File tree

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/FormatterProvider.java‎

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,44 +18,37 @@
1818

1919
import com.github.benmanes.caffeine.cache.Caffeine;
2020
import com.github.benmanes.caffeine.cache.LoadingCache;
21-
import com.google.common.base.Preconditions;
22-
import com.intellij.ide.plugins.IdeaPluginDescriptor;
23-
import com.intellij.ide.plugins.PluginManager;
24-
import com.intellij.openapi.extensions.PluginId;
21+
import com.intellij.formatting.service.FormattingService;
22+
import com.intellij.openapi.extensions.PluginDescriptor;
2523
import com.intellij.openapi.project.Project;
2624
import com.intellij.openapi.util.SystemInfo;
2725
import com.palantir.javaformat.bootstrap.BootstrappingFormatterService;
2826
import com.palantir.javaformat.bootstrap.NativeImageFormatterService;
2927
import com.palantir.javaformat.java.FormatterService;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
3031
import java.io.IOException;
3132
import java.io.UncheckedIOException;
3233
import java.net.URI;
3334
import java.nio.file.Files;
3435
import java.nio.file.Path;
3536
import java.util.List;
37+
import java.util.NoSuchElementException;
3638
import java.util.Objects;
3739
import java.util.Optional;
3840
import java.util.stream.Collectors;
3941
import java.util.stream.Stream;
40-
import org.slf4j.Logger;
41-
import org.slf4j.LoggerFactory;
42+
43+
import static java.util.Optional.ofNullable;
4244

4345
final class FormatterProvider {
4446
private static final Logger log = LoggerFactory.getLogger(FormatterProvider.class);
4547

46-
static final String PLUGIN_ID = "open-java-format";
47-
4848
// Cache to avoid resolving the formatter every time we want to format from IntelliJ
4949
private final LoadingCache<FormatterCacheKey, Optional<FormatterService>> implementationCache =
5050
Caffeine.newBuilder().maximumSize(1).build(FormatterProvider::createFormatter);
5151

52-
static IdeaPluginDescriptor getPluginDescriptor() {
53-
return Preconditions.checkNotNull(
54-
PluginManager.getInstance().findEnabledPlugin(PluginId.getId(PLUGIN_ID)),
55-
"Couldn't find our own plugin: %s",
56-
PLUGIN_ID);
57-
}
58-
5952
Optional<FormatterService> get(Project project, PalantirJavaFormatSettings settings) {
6053
return implementationCache.get(new FormatterCacheKey(
6154
project,
@@ -89,9 +82,14 @@ private static List<Path> getProvidedImplementationUrls(List<URI> implementation
8982
@SuppressWarnings("for-rollout:Slf4jLogsafeArgs")
9083
private static List<Path> getBundledImplementationUrls() {
9184
// Load from the jars bundled with the plugin.
92-
IdeaPluginDescriptor ourPlugin = getPluginDescriptor();
93-
Path implDir = ourPlugin.getPluginPath().resolve("impl");
85+
Path implDir = ofNullable(FormattingService.EP_NAME.findExtension(PalantirJavaFormatFormattingService.class))
86+
.flatMap(PalantirJavaFormatFormattingService::getPluginDescriptor)
87+
.map(PluginDescriptor::getPluginPath)
88+
.orElseThrow(() -> new NoSuchElementException("The platform has not set the plugin descriptor"))
89+
.resolve("impl");
90+
9491
log.debug("Using open-java-format implementation bundled with plugin: {}", implDir);
92+
9593
return listDirAsUrlsUnchecked(implDir);
9694
}
9795

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingService.java‎

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616

1717
package com.palantir.javaformat.intellij;
1818

19-
import static java.util.Comparator.comparing;
20-
2119
import com.google.common.collect.ImmutableList;
2220
import com.google.common.collect.Range;
2321
import com.intellij.formatting.service.AsyncDocumentFormattingService;
2422
import com.intellij.formatting.service.AsyncFormattingRequest;
2523
import com.intellij.ide.highlighter.JavaFileType;
2624
import com.intellij.ide.impl.TrustedProjects;
2725
import com.intellij.openapi.diagnostic.Logger;
26+
import com.intellij.openapi.extensions.PluginAware;
27+
import com.intellij.openapi.extensions.PluginDescriptor;
2828
import com.intellij.openapi.progress.ProcessCanceledException;
2929
import com.intellij.openapi.project.Project;
3030
import com.intellij.openapi.util.NlsSafe;
@@ -33,17 +33,37 @@
3333
import com.palantir.javaformat.java.FormatterException;
3434
import com.palantir.javaformat.java.FormatterService;
3535
import com.palantir.javaformat.java.Replacement;
36+
import org.jetbrains.annotations.NotNull;
37+
38+
import javax.annotation.Nullable;
3639
import java.util.ArrayList;
3740
import java.util.Collection;
3841
import java.util.List;
3942
import java.util.Optional;
4043
import java.util.Set;
41-
import org.jetbrains.annotations.NotNull;
4244

43-
class PalantirJavaFormatFormattingService extends AsyncDocumentFormattingService {
45+
import static java.util.Comparator.comparing;
46+
import static java.util.Optional.ofNullable;
47+
48+
class PalantirJavaFormatFormattingService extends AsyncDocumentFormattingService implements PluginAware {
4449
private static final Logger logger = Logger.getInstance(PalantirJavaFormatFormattingService.class);
4550
private final FormatterProvider formatterProvider = new FormatterProvider();
4651

52+
// The platform sets this right after creating the service from plugin.xml: the descriptor of the plugin that
53+
// declared it, which is how the plugin learns its own path and version (see FormatterProvider.getPluginDescriptor).
54+
// A service created with `new`, as the tests do, has to be given the descriptor itself.
55+
@Nullable
56+
private PluginDescriptor pluginDescriptor;
57+
58+
@Override
59+
public void setPluginDescriptor(@NotNull PluginDescriptor pluginDescriptor) {
60+
this.pluginDescriptor = pluginDescriptor;
61+
}
62+
63+
Optional<PluginDescriptor> getPluginDescriptor() {
64+
return ofNullable(pluginDescriptor);
65+
}
66+
4767
@Override
4868
protected FormattingTask createFormattingTask(@NotNull AsyncFormattingRequest request) {
4969
Project project = request.getContext().getProject();
@@ -108,7 +128,7 @@ public void run() {
108128
if (logger.isDebugEnabled()) {
109129
logger.debug(String.format(
110130
"Received request to format file=%s, length=%s with ranges=%s",
111-
Optional.ofNullable(request.getIOFile())
131+
ofNullable(request.getIOFile())
112132
.map(file -> file.toPath().toString())
113133
.orElse("null"),
114134
preFormatText.length(),

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatSettings.java‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616

1717
package com.palantir.javaformat.intellij;
1818

19+
import com.intellij.formatting.service.FormattingService;
1920
import com.intellij.openapi.components.PersistentStateComponent;
2021
import com.intellij.openapi.components.State;
2122
import com.intellij.openapi.components.Storage;
23+
import com.intellij.openapi.extensions.PluginDescriptor;
2224
import com.intellij.openapi.project.Project;
2325
import com.palantir.javaformat.java.FormatterService;
2426
import com.palantir.javaformat.java.JavaFormatterOptions;
27+
28+
import javax.annotation.Nullable;
2529
import java.io.IOException;
2630
import java.io.UncheckedIOException;
2731
import java.net.URI;
@@ -30,7 +34,8 @@
3034
import java.util.jar.JarFile;
3135
import java.util.stream.Collectors;
3236
import java.util.stream.Stream;
33-
import javax.annotation.Nullable;
37+
38+
import static java.util.Optional.ofNullable;
3439

3540
@SuppressWarnings("for-rollout:SameNameButDifferent")
3641
@State(
@@ -109,7 +114,9 @@ boolean injectedVersionIsOutdated() {
109114
}
110115

111116
Optional<String> getImplementationVersion() {
112-
return Optional.ofNullable(FormatterProvider.getPluginDescriptor().getVersion());
117+
return ofNullable(FormattingService.EP_NAME.findExtension(PalantirJavaFormatFormattingService.class))
118+
.flatMap(PalantirJavaFormatFormattingService::getPluginDescriptor)
119+
.map(PluginDescriptor::getVersion);
113120
}
114121

115122
Optional<String> computeFormatterVersion() {

‎open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurableTest.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ public void readsAndWritesTheEnabledSetting() throws Throwable {
9292
assertThat(settings.isEnabled()).isTrue();
9393
}
9494

95+
@Test
96+
public void showsTheVersionOfThePlugin() {
97+
// The "Plugin version" row: the version the platform read from the plugin's own descriptor, not "unknown".
98+
// Whatever the build stamped: CI checks out without tags, so there it is a commit hash rather than a
99+
// release-like version.
100+
assertThat(settings.getImplementationVersion())
101+
.hasValueSatisfying(version -> assertThat(version).isNotBlank());
102+
}
103+
95104
private static Optional<JCheckBox> findCheckBox(Component root) {
96105
if (root instanceof JCheckBox checkBox) {
97106
return Optional.of(checkBox);

‎open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingServiceTest.java‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
package com.palantir.javaformat.intellij;
1818

19-
import static org.assertj.core.api.Assertions.assertThat;
20-
21-
import com.google.common.collect.ImmutableList;
2219
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
2320
import com.intellij.formatting.service.AsyncFormattingRequest;
2421
import com.intellij.formatting.service.FormattingService;
@@ -39,16 +36,20 @@
3936
import com.intellij.testFramework.fixtures.JavaTestFixtureFactory;
4037
import com.intellij.testFramework.fixtures.TestFixtureBuilder;
4138
import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.State;
39+
import org.jetbrains.annotations.NotNull;
40+
import org.junit.jupiter.api.AfterEach;
41+
import org.junit.jupiter.api.BeforeEach;
42+
import org.junit.jupiter.api.Test;
43+
4244
import java.io.File;
4345
import java.io.IOException;
4446
import java.io.UncheckedIOException;
4547
import java.nio.file.Files;
4648
import java.nio.file.Path;
4749
import java.nio.file.Paths;
48-
import org.jetbrains.annotations.NotNull;
49-
import org.junit.jupiter.api.AfterEach;
50-
import org.junit.jupiter.api.BeforeEach;
51-
import org.junit.jupiter.api.Test;
50+
import java.util.List;
51+
52+
import static org.assertj.core.api.Assertions.assertThat;
5253

5354
public class PalantirJavaFormatFormattingServiceTest {
5455
private JavaCodeInsightTestFixture fixture;
@@ -63,10 +64,12 @@ public void setUp() throws Exception {
6364
fixture.setUp();
6465

6566
delegatingFormatter = new DelegatingFormatter();
67+
6668
ExtensionTestUtil.maskExtensions(
67-
FormattingService.EP_NAME, ImmutableList.of(delegatingFormatter), fixture.getProjectDisposable());
69+
FormattingService.EP_NAME, List.of(delegatingFormatter), fixture.getProjectDisposable());
6870

6971
settings = PalantirJavaFormatSettings.getInstance(fixture.getProject());
72+
7073
State resetState = new State();
7174
resetState.setEnabled("true");
7275
settings.loadState(resetState);
@@ -126,6 +129,13 @@ private PsiFile createPsiFile(String path, String... contents) throws IOExceptio
126129
}
127130

128131
private static final class DelegatingFormatter extends PalantirJavaFormatFormattingService {
132+
@SuppressWarnings("DataFlowIssue")
133+
public DelegatingFormatter() {
134+
this.setPluginDescriptor(FormattingService.EP_NAME
135+
.findExtension(PalantirJavaFormatFormattingService.class)
136+
.getPluginDescriptor()
137+
.orElseThrow());
138+
}
129139

130140
private boolean invoked = false;
131141

0 commit comments

Comments
 (0)