diff --git a/ktfmt_idea_plugin/build.gradle.kts b/ktfmt_idea_plugin/build.gradle.kts index f41c343b..c1de90eb 100644 --- a/ktfmt_idea_plugin/build.gradle.kts +++ b/ktfmt_idea_plugin/build.gradle.kts @@ -17,10 +17,10 @@ import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType.* */ plugins { - java - alias(libs.plugins.kotlin) - alias(libs.plugins.intelliJPlatform) - alias(libs.plugins.spotless) + java + alias(libs.plugins.kotlin) + alias(libs.plugins.intelliJPlatform) + alias(libs.plugins.spotless) } val ktfmtVersion = rootProject.file("../version.txt").readText().trim() @@ -33,45 +33,38 @@ version = "$pluginVersion.$ktfmtVersion" kotlin { jvmToolchain(17) } repositories { - mavenCentral() - intellijPlatform { - defaultRepositories() - } - mavenLocal() + mavenCentral() + intellijPlatform { defaultRepositories() } + mavenLocal() } dependencies { - intellijPlatform { - create(IntellijIdeaCommunity, "2022.3") - instrumentationTools() - pluginVerifier() - zipSigner() - } - - implementation("com.facebook", "ktfmt", ktfmtVersion) - implementation(libs.googleJavaFormat) + intellijPlatform { + create(IntellijIdeaCommunity, "2022.3") + instrumentationTools() + pluginVerifier() + zipSigner() + } + + implementation("com.facebook", "ktfmt", ktfmtVersion) + implementation(libs.googleJavaFormat) } intellijPlatform { - pluginConfiguration.ideaVersion { - sinceBuild = "223.7571.182" // 2022.3 - untilBuild = provider { null } - } + pluginConfiguration.ideaVersion { + sinceBuild = "223.7571.182" // 2022.3 + untilBuild = provider { null } + } - publishing { - token = System.getenv("JETBRAINS_MARKETPLACE_TOKEN") - } + publishing { token = System.getenv("JETBRAINS_MARKETPLACE_TOKEN") } - pluginVerification { - ides { - recommended() - } - } + pluginVerification { ides { recommended() } } } spotless { java { googleJavaFormat(libs.versions.googleJavaFormat.get()) } } -val runIntellij242 by intellijPlatformTesting.runIde.registering { - type = IntellijIdeaCommunity - version = "2024.2" -} +val runIntellij242 by + intellijPlatformTesting.runIde.registering { + type = IntellijIdeaCommunity + version = "2024.2" + } diff --git a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/InitialConfigurationStartupActivity.java b/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/InitialConfigurationStartupActivity.java deleted file mode 100644 index 00fe09ae..00000000 --- a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/InitialConfigurationStartupActivity.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2016 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.facebook.ktfmt.intellij; - -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationGroupManager; -import com.intellij.notification.NotificationType; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.startup.StartupActivity; -import org.jetbrains.annotations.NotNull; - -final class InitialConfigurationStartupActivity implements StartupActivity.Background { - - private static final String NOTIFICATION_TITLE = "Enable ktfmt"; - - @Override - public void runActivity(@NotNull Project project) { - KtfmtSettings settings = KtfmtSettings.getInstance(project); - - if (settings.isUninitialized()) { - settings.setEnabled(false); - displayNewUserNotification(project, settings); - } - } - - private void displayNewUserNotification(Project project, KtfmtSettings settings) { - Notification notification = - new Notification( - NotificationGroupManager.getInstance() - .getNotificationGroup(NOTIFICATION_TITLE) - .getDisplayId(), - NOTIFICATION_TITLE, - "The ktfmt plugin is disabled by default.", - NotificationType.INFORMATION); - - notification - .addAction( - new AnAction("Enable for This Project") { - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - settings.setEnabled(true); - notification.expire(); - } - }) - .notify(project); - } -} diff --git a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtConfigurable.form b/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtConfigurable.form deleted file mode 100644 index e515398f..00000000 --- a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtConfigurable.form +++ /dev/null @@ -1,40 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtConfigurable.java b/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtConfigurable.java deleted file mode 100644 index 9fd0e9ae..00000000 --- a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtConfigurable.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2016 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.facebook.ktfmt.intellij; - -import com.facebook.ktfmt.intellij.KtfmtSettings.EnabledState; -import com.intellij.openapi.options.BaseConfigurable; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.ComboBox; -import com.intellij.uiDesigner.core.GridConstraints; -import com.intellij.uiDesigner.core.GridLayoutManager; -import com.intellij.uiDesigner.core.Spacer; -import java.awt.Insets; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class KtfmtConfigurable extends BaseConfigurable implements SearchableConfigurable { - - private final Project project; - private JPanel panel; - private JCheckBox enable; - private JComboBox styleComboBox; - - public KtfmtConfigurable(Project project) { - this.project = project; - } - - @NotNull - @Override - public String getId() { - return "ktfmt.settings"; - } - - @Nullable - @Override - public Runnable enableSearch(String option) { - return null; - } - - @Nls - @Override - public String getDisplayName() { - return "ktfmt Settings"; - } - - @Nullable - @Override - public String getHelpTopic() { - return null; - } - - @Nullable - @Override - public JComponent createComponent() { - return panel; - } - - @Override - public void apply() throws ConfigurationException { - KtfmtSettings settings = KtfmtSettings.getInstance(project); - settings.setEnabled(enable.isSelected() ? EnabledState.ENABLED : getDisabledState()); - settings.setUiFormatterStyle(((UiFormatterStyle) styleComboBox.getSelectedItem())); - } - - private EnabledState getDisabledState() { - // The default settings (inherited by new projects) are either 'enabled' or - // 'show notification'. There's no way to default new projects to disabled. If - // someone wants - // that, we can add another checkbox, I suppose. - return project.isDefault() ? EnabledState.UNKNOWN : EnabledState.DISABLED; - } - - @Override - public void reset() { - KtfmtSettings settings = KtfmtSettings.getInstance(project); - enable.setSelected(settings.isEnabled()); - styleComboBox.setSelectedItem(settings.getUiFormatterStyle()); - } - - @Override - public boolean isModified() { - KtfmtSettings settings = KtfmtSettings.getInstance(project); - return enable.isSelected() != settings.isEnabled() - || !styleComboBox.getSelectedItem().equals(settings.getUiFormatterStyle()); - } - - @Override - public void disposeUIResources() {} - - private void createUIComponents() { - styleComboBox = new ComboBox<>(UiFormatterStyle.values()); - } - - { - // GUI initializer generated by IntelliJ IDEA GUI Designer - // >>> IMPORTANT!! <<< - // DO NOT EDIT OR ADD ANY CODE HERE! - $$$setupUI$$$(); - } - - /** - * Method generated by IntelliJ IDEA GUI Designer >>> IMPORTANT!! <<< DO NOT edit this method OR - * call it in your code! - * - * @noinspection ALL - */ - private void $$$setupUI$$$() { - createUIComponents(); - panel = new JPanel(); - panel.setLayout(new GridLayoutManager(3, 2, new Insets(0, 0, 0, 0), -1, -1)); - enable = new JCheckBox(); - enable.setText("Enable ktfmt"); - panel.add( - enable, - new GridConstraints( - 0, - 0, - 1, - 2, - GridConstraints.ANCHOR_WEST, - GridConstraints.FILL_NONE, - GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, - GridConstraints.SIZEPOLICY_FIXED, - null, - null, - null, - 0, - false)); - final Spacer spacer1 = new Spacer(); - panel.add( - spacer1, - new GridConstraints( - 2, - 0, - 1, - 2, - GridConstraints.ANCHOR_CENTER, - GridConstraints.FILL_VERTICAL, - 1, - GridConstraints.SIZEPOLICY_WANT_GROW, - null, - null, - null, - 0, - false)); - final JLabel label1 = new JLabel(); - label1.setText("Code style"); - panel.add( - label1, - new GridConstraints( - 1, - 0, - 1, - 1, - GridConstraints.ANCHOR_WEST, - GridConstraints.FILL_NONE, - GridConstraints.SIZEPOLICY_FIXED, - GridConstraints.SIZEPOLICY_FIXED, - null, - null, - null, - 0, - false)); - panel.add( - styleComboBox, - new GridConstraints( - 1, - 1, - 1, - 1, - GridConstraints.ANCHOR_WEST, - GridConstraints.FILL_HORIZONTAL, - GridConstraints.SIZEPOLICY_CAN_GROW, - GridConstraints.SIZEPOLICY_FIXED, - null, - null, - null, - 1, - false)); - } - - /** - * @noinspection ALL - */ - public JComponent $$$getRootComponent$$$() { - return panel; - } -} diff --git a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtFormattingService.java b/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtFormattingService.java deleted file mode 100644 index 58aaac7d..00000000 --- a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtFormattingService.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.facebook.ktfmt.intellij; - -import static com.facebook.ktfmt.format.Formatter.format; - -import com.google.googlejavaformat.java.FormatterException; -import com.intellij.formatting.service.AsyncDocumentFormattingService; -import com.intellij.formatting.service.AsyncFormattingRequest; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; -import java.util.EnumSet; -import java.util.Set; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.idea.KotlinFileType; - -/** Uses {@code ktfmt} to reformat code. */ -public class KtfmtFormattingService extends AsyncDocumentFormattingService { - - @Override - protected FormattingTask createFormattingTask(AsyncFormattingRequest request) { - Project project = request.getContext().getProject(); - - UiFormatterStyle style = KtfmtSettings.getInstance(project).getUiFormatterStyle(); - return new KtfmtFormattingTask(request, style); - } - - @Override - protected @NotNull String getNotificationGroupId() { - return Notifications.PARSING_ERROR_NOTIFICATION_GROUP; - } - - @Override - protected @NotNull String getName() { - return "ktfmt"; - } - - @Override - public @NotNull Set getFeatures() { - return EnumSet.noneOf(Feature.class); - } - - @Override - public boolean canFormat(@NotNull PsiFile file) { - return KotlinFileType.INSTANCE.getName().equals(file.getFileType().getName()) - && KtfmtSettings.getInstance(file.getProject()).isEnabled(); - } - - private static final class KtfmtFormattingTask implements FormattingTask { - private final AsyncFormattingRequest request; - private final UiFormatterStyle style; - - private KtfmtFormattingTask(AsyncFormattingRequest request, UiFormatterStyle style) { - this.request = request; - this.style = style; - } - - @Override - public void run() { - try { - String formattedText = format(style.getFormattingOptions(), request.getDocumentText()); - request.onTextReady(formattedText); - } catch (FormatterException e) { - request.onError( - Notifications.PARSING_ERROR_TITLE, - Notifications.parsingErrorMessage(request.getContext().getContainingFile().getName())); - } - } - - @Override - public boolean isRunUnderProgress() { - return true; - } - - @Override - public boolean cancel() { - return false; - } - } -} diff --git a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtSettings.java b/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtSettings.java deleted file mode 100644 index 90909e61..00000000 --- a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/KtfmtSettings.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2016 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.facebook.ktfmt.intellij; - -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -@State( - name = "KtfmtSettings", - storages = {@Storage("ktfmt.xml")}) -class KtfmtSettings implements PersistentStateComponent { - - private State state = new State(); - - static KtfmtSettings getInstance(Project project) { - return project.getService(KtfmtSettings.class); - } - - @Nullable - @Override - public State getState() { - return state; - } - - @Override - public void loadState(@NotNull State state) { - this.state = state; - } - - boolean isEnabled() { - return state.enabled.equals(EnabledState.ENABLED); - } - - void setEnabled(boolean enabled) { - setEnabled(enabled ? EnabledState.ENABLED : EnabledState.DISABLED); - } - - void setEnabled(EnabledState enabled) { - state.enabled = enabled; - } - - boolean isUninitialized() { - return state.enabled.equals(EnabledState.UNKNOWN); - } - - UiFormatterStyle getUiFormatterStyle() { - return state.uiFormatterStyle; - } - - void setUiFormatterStyle(UiFormatterStyle uiFormatterStyle) { - state.uiFormatterStyle = uiFormatterStyle; - } - - enum EnabledState { - UNKNOWN, - ENABLED, - DISABLED; - } - - static class State { - - private EnabledState enabled = EnabledState.UNKNOWN; - public UiFormatterStyle uiFormatterStyle = UiFormatterStyle.META; - - // enabled used to be a boolean so we use bean property methods for backwards - // compatibility - public void setEnabled(@Nullable String enabledStr) { - if (enabledStr == null) { - enabled = EnabledState.UNKNOWN; - } else if (Boolean.parseBoolean(enabledStr)) { - enabled = EnabledState.ENABLED; - } else { - enabled = EnabledState.DISABLED; - } - } - - public String getEnabled() { - switch (enabled) { - case ENABLED: - return "true"; - case DISABLED: - return "false"; - default: - return null; - } - } - } -} diff --git a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/Notifications.java b/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/Notifications.java deleted file mode 100644 index b64db568..00000000 --- a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/Notifications.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * 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.facebook.ktfmt.intellij; - -class Notifications { - - static final String PARSING_ERROR_NOTIFICATION_GROUP = "ktfmt parsing error"; - static final String PARSING_ERROR_TITLE = PARSING_ERROR_NOTIFICATION_GROUP; - - static String parsingErrorMessage(String filename) { - return "ktfmt failed. Does " + filename + " have syntax errors?"; - } -} diff --git a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/UiFormatterStyle.java b/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/UiFormatterStyle.java deleted file mode 100644 index ac7ae57a..00000000 --- a/ktfmt_idea_plugin/src/main/java/com/facebook/ktfmt/intellij/UiFormatterStyle.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2016 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.facebook.ktfmt.intellij; - -import static com.facebook.ktfmt.format.Formatter.GOOGLE_FORMAT; -import static com.facebook.ktfmt.format.Formatter.KOTLINLANG_FORMAT; -import static com.facebook.ktfmt.format.Formatter.META_FORMAT; - -import com.facebook.ktfmt.format.FormattingOptions; - -/** Configuration options for the formatting style. */ -enum UiFormatterStyle { - META("Meta (default)", META_FORMAT), - GOOGLE("Google (internal)", GOOGLE_FORMAT), - KOTLINLANG("Kotlinlang", KOTLINLANG_FORMAT); - - private final String description; - private final FormattingOptions formattingOptions; - - UiFormatterStyle(String description, FormattingOptions formattingOptions) { - this.description = description; - this.formattingOptions = formattingOptions; - } - - FormattingOptions getFormattingOptions() { - return formattingOptions; - } - - @Override - public String toString() { - return description; - } -} diff --git a/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/InitialConfigurationStartupActivity.kt b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/InitialConfigurationStartupActivity.kt new file mode 100644 index 00000000..83212339 --- /dev/null +++ b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/InitialConfigurationStartupActivity.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2016 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.facebook.ktfmt.intellij + +import com.intellij.notification.Notification +import com.intellij.notification.NotificationGroupManager +import com.intellij.notification.NotificationType.INFORMATION +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.project.Project +import com.intellij.openapi.startup.StartupActivity.Background + +class InitialConfigurationStartupActivity : Background { + override fun runActivity(project: Project) { + val settings = KtfmtSettings.getInstance(project) + + if (settings.isUninitialized) { + settings.isEnabled = false + displayNewUserNotification(project, settings) + } + } + + private fun displayNewUserNotification(project: Project, settings: KtfmtSettings) { + val notification = + Notification( + NotificationGroupManager.getInstance() + .getNotificationGroup(NOTIFICATION_TITLE) + .displayId, + NOTIFICATION_TITLE, + "The ktfmt plugin is disabled by default.", + INFORMATION, + ) + + notification + .addAction( + object : AnAction("Enable for This Project") { + override fun actionPerformed(e: AnActionEvent) { + settings.isEnabled = true + notification.expire() + } + } + ) + .notify(project) + } + + companion object { + private const val NOTIFICATION_TITLE = "Enable ktfmt" + } +} diff --git a/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtConfigurable.kt b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtConfigurable.kt new file mode 100644 index 00000000..95497e47 --- /dev/null +++ b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtConfigurable.kt @@ -0,0 +1,45 @@ +package com.facebook.ktfmt.intellij + +import com.facebook.ktfmt.intellij.KtfmtSettings.EnabledState.Disabled +import com.facebook.ktfmt.intellij.KtfmtSettings.EnabledState.Enabled +import com.intellij.openapi.options.BoundSearchableConfigurable +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.DialogPanel +import com.intellij.ui.dsl.builder.bindItem +import com.intellij.ui.dsl.builder.bindSelected +import com.intellij.ui.dsl.builder.panel +import com.intellij.ui.layout.selected +import javax.swing.JCheckBox + +@Suppress("DialogTitleCapitalization") +class KtfmtConfigurable(project: Project) : + BoundSearchableConfigurable( + displayName = "ktfmt Settings", + _id = "com.facebook.ktfmt_idea_plugin.settings", + helpTopic = "ktfmt", + ) { + private val settings = KtfmtSettings.getInstance(project) + + override fun createPanel(): DialogPanel = panel { + lateinit var enabledCheckbox: JCheckBox + row { + enabledCheckbox = + checkBox("Enable ktfmt") + .bindSelected( + getter = { settings.isEnabled }, + setter = { settings.setEnabled(if (it) Enabled else Disabled) }, + ) + .component + } + + row { + comboBox(UiFormatterStyle.entries.toList()) + .label("Code style:") + .bindItem( + getter = { settings.uiFormatterStyle }, + setter = { settings.uiFormatterStyle = it ?: UiFormatterStyle.Meta }, + ) + .enabledIf(enabledCheckbox.selected) + } + } +} diff --git a/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtFormattingService.kt b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtFormattingService.kt new file mode 100644 index 00000000..4e4cf643 --- /dev/null +++ b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtFormattingService.kt @@ -0,0 +1,67 @@ +/* + * 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.facebook.ktfmt.intellij + +import com.facebook.ktfmt.format.Formatter.format +import com.google.googlejavaformat.java.FormatterException +import com.intellij.formatting.service.AsyncDocumentFormattingService +import com.intellij.formatting.service.AsyncFormattingRequest +import com.intellij.formatting.service.FormattingService.Feature +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.idea.KotlinFileType + +private const val PARSING_ERROR_NOTIFICATION_GROUP: String = "ktfmt parsing error" +private const val PARSING_ERROR_TITLE: String = PARSING_ERROR_NOTIFICATION_GROUP + +/** Uses `ktfmt` to reformat code. */ +class KtfmtFormattingService : AsyncDocumentFormattingService() { + override fun createFormattingTask(request: AsyncFormattingRequest): FormattingTask { + val project = request.context.project + val style = KtfmtSettings.getInstance(project).uiFormatterStyle + return KtfmtFormattingTask(request, style) + } + + override fun getNotificationGroupId(): String = PARSING_ERROR_NOTIFICATION_GROUP + + override fun getName(): String = "ktfmt" + + override fun getFeatures(): Set = emptySet() + + override fun canFormat(file: PsiFile): Boolean = + KotlinFileType.INSTANCE.name == file.fileType.name && + KtfmtSettings.getInstance(file.project).isEnabled + + private class KtfmtFormattingTask( + private val request: AsyncFormattingRequest, + private val style: UiFormatterStyle, + ) : FormattingTask { + override fun run() { + try { + val formattedText = format(style.formattingOptions, request.documentText) + request.onTextReady(formattedText) + } catch (e: FormatterException) { + request.onError( + PARSING_ERROR_TITLE, + "ktfmt failed. Does ${request.context.containingFile.name} have syntax errors?", + ) + } + } + + override fun isRunUnderProgress(): Boolean = true + + override fun cancel(): Boolean = false + } +} diff --git a/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtSettings.kt b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtSettings.kt new file mode 100644 index 00000000..f66bc63b --- /dev/null +++ b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/KtfmtSettings.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2016 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.facebook.ktfmt.intellij + +import com.facebook.ktfmt.intellij.KtfmtSettings.EnabledState.Disabled +import com.facebook.ktfmt.intellij.KtfmtSettings.EnabledState.Enabled +import com.facebook.ktfmt.intellij.KtfmtSettings.EnabledState.Unknown +import com.facebook.ktfmt.intellij.UiFormatterStyle.Meta +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.Service.Level.PROJECT +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.openapi.project.Project + +@Service(PROJECT) +@State(name = "KtfmtSettings", storages = [Storage("ktfmt.xml")]) +internal class KtfmtSettings : PersistentStateComponent { + private var state = State() + + override fun getState(): State = state + + override fun loadState(state: State) { + this.state = state + } + + var isEnabled: Boolean + get() = state.enabled == Enabled + set(enabled) { + setEnabled(if (enabled) Enabled else Disabled) + } + + fun setEnabled(enabled: EnabledState) { + state.enabled = enabled + } + + val isUninitialized: Boolean + get() = state.enabled == Unknown + + var uiFormatterStyle: UiFormatterStyle + get() = state.uiFormatterStyle + set(uiFormatterStyle) { + state.uiFormatterStyle = uiFormatterStyle + } + + internal enum class EnabledState { + Unknown, + Enabled, + Disabled, + } + + internal class State { + @JvmField var enabled: EnabledState = Unknown + var uiFormatterStyle: UiFormatterStyle = Meta + + // enabled used to be a boolean so we use bean property methods for backwards + // compatibility + fun setEnabled(enabledStr: String?) { + enabled = + when { + enabledStr == null -> Unknown + enabledStr.toBoolean() -> Enabled + else -> Disabled + } + } + + fun getEnabled(): String? = + when (enabled) { + Enabled -> "true" + Disabled -> "false" + else -> null + } + } + + companion object { + @JvmStatic + fun getInstance(project: Project): KtfmtSettings = + project.getService(KtfmtSettings::class.java) + } +} diff --git a/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/UiFormatterStyle.kt b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/UiFormatterStyle.kt new file mode 100644 index 00000000..13b47eca --- /dev/null +++ b/ktfmt_idea_plugin/src/main/kotlin/com/facebook/ktfmt/intellij/UiFormatterStyle.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2016 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.facebook.ktfmt.intellij + +import com.facebook.ktfmt.format.Formatter.GOOGLE_FORMAT +import com.facebook.ktfmt.format.Formatter.KOTLINLANG_FORMAT +import com.facebook.ktfmt.format.Formatter.META_FORMAT +import com.facebook.ktfmt.format.FormattingOptions + +/** Configuration options for the formatting style. */ +internal enum class UiFormatterStyle( + private val description: String, + val formattingOptions: FormattingOptions, +) { + Meta("Meta (default)", META_FORMAT), + Google("Google (internal)", GOOGLE_FORMAT), + KotlinLang("Kotlinlang", KOTLINLANG_FORMAT); + + override fun toString(): String = description +} diff --git a/ktfmt_idea_plugin/src/main/resources/META-INF/plugin.xml b/ktfmt_idea_plugin/src/main/resources/META-INF/plugin.xml index 7f5ed4b4..f47f163e 100644 --- a/ktfmt_idea_plugin/src/main/resources/META-INF/plugin.xml +++ b/ktfmt_idea_plugin/src/main/resources/META-INF/plugin.xml @@ -19,7 +19,6 @@ id="com.facebook.ktfmt_idea_plugin.settings" displayName="ktfmt Settings" parentId="editor"/> -