Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,37 @@

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.base.Preconditions;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.formatting.service.FormattingService;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.palantir.javaformat.bootstrap.BootstrappingFormatterService;
import com.palantir.javaformat.bootstrap.NativeImageFormatterService;
import com.palantir.javaformat.java.FormatterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.Optional.ofNullable;

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

static final String PLUGIN_ID = "open-java-format";

// Cache to avoid resolving the formatter every time we want to format from IntelliJ
private final LoadingCache<FormatterCacheKey, Optional<FormatterService>> implementationCache =
Caffeine.newBuilder().maximumSize(1).build(FormatterProvider::createFormatter);

static IdeaPluginDescriptor getPluginDescriptor() {
return Preconditions.checkNotNull(
PluginManager.getInstance().findEnabledPlugin(PluginId.getId(PLUGIN_ID)),
"Couldn't find our own plugin: %s",
PLUGIN_ID);
}

Optional<FormatterService> get(Project project, PalantirJavaFormatSettings settings) {
return implementationCache.get(new FormatterCacheKey(
project,
Expand Down Expand Up @@ -89,9 +82,14 @@ private static List<Path> getProvidedImplementationUrls(List<URI> implementation
@SuppressWarnings("for-rollout:Slf4jLogsafeArgs")
private static List<Path> getBundledImplementationUrls() {
// Load from the jars bundled with the plugin.
IdeaPluginDescriptor ourPlugin = getPluginDescriptor();
Path implDir = ourPlugin.getPluginPath().resolve("impl");
Path implDir = ofNullable(FormattingService.EP_NAME.findExtension(PalantirJavaFormatFormattingService.class))
.flatMap(PalantirJavaFormatFormattingService::getPluginDescriptor)
.map(PluginDescriptor::getPluginPath)
.orElseThrow(() -> new NoSuchElementException("The platform has not set the plugin descriptor"))
.resolve("impl");

log.debug("Using open-java-format implementation bundled with plugin: {}", implDir);

return listDirAsUrlsUnchecked(implDir);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

package com.palantir.javaformat.intellij;

import static java.util.Comparator.comparing;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Range;
import com.intellij.formatting.service.AsyncDocumentFormattingService;
import com.intellij.formatting.service.AsyncFormattingRequest;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.ide.impl.TrustedProjects;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginAware;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsSafe;
Expand All @@ -33,17 +33,37 @@
import com.palantir.javaformat.java.FormatterException;
import com.palantir.javaformat.java.FormatterService;
import com.palantir.javaformat.java.Replacement;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.jetbrains.annotations.NotNull;

class PalantirJavaFormatFormattingService extends AsyncDocumentFormattingService {
import static java.util.Comparator.comparing;
import static java.util.Optional.ofNullable;

class PalantirJavaFormatFormattingService extends AsyncDocumentFormattingService implements PluginAware {
private static final Logger logger = Logger.getInstance(PalantirJavaFormatFormattingService.class);
private final FormatterProvider formatterProvider = new FormatterProvider();

// The platform sets this right after creating the service from plugin.xml: the descriptor of the plugin that
// declared it, which is how the plugin learns its own path and version (see FormatterProvider.getPluginDescriptor).
// A service created with `new`, as the tests do, has to be given the descriptor itself.
@Nullable
private PluginDescriptor pluginDescriptor;

@Override
public void setPluginDescriptor(@NotNull PluginDescriptor pluginDescriptor) {
this.pluginDescriptor = pluginDescriptor;
}

Optional<PluginDescriptor> getPluginDescriptor() {
return ofNullable(pluginDescriptor);
}

@Override
protected FormattingTask createFormattingTask(@NotNull AsyncFormattingRequest request) {
Project project = request.getContext().getProject();
Expand Down Expand Up @@ -108,7 +128,7 @@ public void run() {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"Received request to format file=%s, length=%s with ranges=%s",
Optional.ofNullable(request.getIOFile())
ofNullable(request.getIOFile())
.map(file -> file.toPath().toString())
.orElse("null"),
preFormatText.length(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package com.palantir.javaformat.intellij;

import com.intellij.formatting.service.FormattingService;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.project.Project;
import com.palantir.javaformat.java.FormatterService;
import com.palantir.javaformat.java.JavaFormatterOptions;

import javax.annotation.Nullable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
Expand All @@ -30,7 +34,8 @@
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;

import static java.util.Optional.ofNullable;

@SuppressWarnings("for-rollout:SameNameButDifferent")
@State(
Expand Down Expand Up @@ -109,7 +114,9 @@ boolean injectedVersionIsOutdated() {
}

Optional<String> getImplementationVersion() {
return Optional.ofNullable(FormatterProvider.getPluginDescriptor().getVersion());
return ofNullable(FormattingService.EP_NAME.findExtension(PalantirJavaFormatFormattingService.class))
.flatMap(PalantirJavaFormatFormattingService::getPluginDescriptor)
.map(PluginDescriptor::getVersion);
}

Optional<String> computeFormatterVersion() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ public void readsAndWritesTheEnabledSetting() throws Throwable {
assertThat(settings.isEnabled()).isTrue();
}

@Test
public void showsTheVersionOfThePlugin() {
// The "Plugin version" row: the version the platform read from the plugin's own descriptor, not "unknown".
// Whatever the build stamped: CI checks out without tags, so there it is a commit hash rather than a
// release-like version.
assertThat(settings.getImplementationVersion())
.hasValueSatisfying(version -> assertThat(version).isNotBlank());
}

private static Optional<JCheckBox> findCheckBox(Component root) {
if (root instanceof JCheckBox checkBox) {
return Optional.of(checkBox);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@

package com.palantir.javaformat.intellij;

import static org.assertj.core.api.Assertions.assertThat;

import com.google.common.collect.ImmutableList;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.formatting.service.AsyncFormattingRequest;
import com.intellij.formatting.service.FormattingService;
Expand All @@ -39,16 +36,20 @@
import com.intellij.testFramework.fixtures.JavaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TestFixtureBuilder;
import com.palantir.javaformat.intellij.PalantirJavaFormatSettings.State;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

public class PalantirJavaFormatFormattingServiceTest {
private JavaCodeInsightTestFixture fixture;
Expand All @@ -63,10 +64,12 @@ public void setUp() throws Exception {
fixture.setUp();

delegatingFormatter = new DelegatingFormatter();

ExtensionTestUtil.maskExtensions(
FormattingService.EP_NAME, ImmutableList.of(delegatingFormatter), fixture.getProjectDisposable());
FormattingService.EP_NAME, List.of(delegatingFormatter), fixture.getProjectDisposable());

settings = PalantirJavaFormatSettings.getInstance(fixture.getProject());

State resetState = new State();
resetState.setEnabled("true");
settings.loadState(resetState);
Expand Down Expand Up @@ -126,6 +129,13 @@ private PsiFile createPsiFile(String path, String... contents) throws IOExceptio
}

private static final class DelegatingFormatter extends PalantirJavaFormatFormattingService {
@SuppressWarnings("DataFlowIssue")
public DelegatingFormatter() {
this.setPluginDescriptor(FormattingService.EP_NAME
.findExtension(PalantirJavaFormatFormattingService.class)
.getPluginDescriptor()
.orElseThrow());
}

private boolean invoked = false;

Expand Down
Loading