diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettings.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettings.java new file mode 100644 index 000000000000..81619a2236a3 --- /dev/null +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettings.java @@ -0,0 +1,41 @@ +package ai.vespa.schemals.intellij.settings; + + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +/** + * This is the 'Model' part of the Settings interface per MVC. + * It simply contains the current settings state. + */ +@State( + name = "ai.vespa.schemals.intellij.settings.SchemaLspSettings", + storages = @Storage("VespaSchemaSettings.xml") +) +public final class SchemaSettings implements PersistentStateComponent { + public static class State { + @NonNls + public String javaPath = ""; + } + + private State state = new State(); + + public static SchemaSettings getInstance() { + return ApplicationManager.getApplication() + .getService(SchemaSettings.class); + } + + @Override + public State getState() { + return state; + } + + @Override + public void loadState(@NotNull State state) { + this.state = state; + } +} diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettingsComponent.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettingsComponent.java new file mode 100644 index 000000000000..d51851fdf5be --- /dev/null +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettingsComponent.java @@ -0,0 +1,56 @@ +package ai.vespa.schemals.intellij.settings; + +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; +import com.intellij.openapi.fileChooser.FileChooserPanel; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBTextField; +import com.intellij.util.ui.FormBuilder; +import com.jetbrains.JBRFileDialog; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +/** + * This is the 'View' part of the Settings interface per MVC + * It defines the settings ui for the plugin. + */ +public class SchemaSettingsComponent { + private final JPanel mainPanel; + private final TextFieldWithBrowseButton javaPathTextField = new TextFieldWithBrowseButton(); + + public SchemaSettingsComponent() { + FileChooserDescriptor fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); + fileChooserDescriptor.setTitle("Select Path to Java Home"); + javaPathTextField.addBrowseFolderListener("Java Path", "Select path to java home", null, fileChooserDescriptor); + javaPathTextField.setToolTipText("Path to Java Home or directory containing a java executable. Will use the system installed version of java if not set."); + + mainPanel = FormBuilder.createFormBuilder() + .addLabeledComponent(new JBLabel("Path to java home:"), javaPathTextField, 1, false) + .addComponentFillVertically(new JPanel(), 0) + .getPanel(); + } + + public JPanel getPanel() { + return mainPanel; + } + + public JComponent getPreferredFocusedComponent() { + return javaPathTextField; + } + + @NotNull + public String getJavaPathText() { + return javaPathTextField.getText(); + } + + public void setJavaPathText(@NotNull String javaPath) { + javaPathTextField.setText(javaPath); + } +} diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettingsConfigurable.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettingsConfigurable.java new file mode 100644 index 000000000000..e460d169ee29 --- /dev/null +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/settings/SchemaSettingsConfigurable.java @@ -0,0 +1,61 @@ +package ai.vespa.schemals.intellij.settings; + +import com.intellij.openapi.options.Configurable; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Objects; + +/** + * This is the 'Controller' part of the Settings interface per MVC + * It glues the ui and the state together and interacts with the IntelliJ platform. + */ +public class SchemaSettingsConfigurable implements Configurable { + private SchemaSettingsComponent settingsComponent; + + @Nls(capitalization = Nls.Capitalization.Title) + @Override + public String getDisplayName() { + return "Vespa Schema Settings"; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return settingsComponent.getPreferredFocusedComponent(); + } + + @Nullable + @Override + public JComponent createComponent() { + settingsComponent = new SchemaSettingsComponent(); + return settingsComponent.getPanel(); + } + + @Override + public boolean isModified() { + SchemaSettings.State state = + Objects.requireNonNull(SchemaSettings.getInstance().getState()); + return !settingsComponent.getJavaPathText().equals(state.javaPath); + } + + @Override + public void apply() { + SchemaSettings.State state = + Objects.requireNonNull(SchemaSettings.getInstance().getState()); + state.javaPath = settingsComponent.getJavaPathText(); + } + + @Override + public void reset() { + SchemaSettings.State state = + Objects.requireNonNull(SchemaSettings.getInstance().getState()); + settingsComponent.setJavaPathText(state.javaPath); + } + + @Override + public void disposeUIResources() { + settingsComponent = null; + } +} diff --git a/integration/schema-language-server/clients/intellij/src/main/kotlin/ai/vespa/schemals/intellij/SchemaLspServerSupportProvider.kt b/integration/schema-language-server/clients/intellij/src/main/kotlin/ai/vespa/schemals/intellij/SchemaLspServerSupportProvider.kt index 91641af550df..e1a2259cc932 100644 --- a/integration/schema-language-server/clients/intellij/src/main/kotlin/ai/vespa/schemals/intellij/SchemaLspServerSupportProvider.kt +++ b/integration/schema-language-server/clients/intellij/src/main/kotlin/ai/vespa/schemals/intellij/SchemaLspServerSupportProvider.kt @@ -7,8 +7,9 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.platform.lsp.api.LspServerSupportProvider import com.intellij.platform.lsp.api.ProjectWideLspServerDescriptor -import com.intellij.openapi.application.PathManager -import java.nio.file.Path +import ai.vespa.schemals.intellij.settings.SchemaSettings +import java.nio.file.Paths +import kotlin.io.path.isExecutable /** * Entry point for giving LSP support by starting the server. @@ -39,6 +40,19 @@ class SchemaLspServerDescriptor(project: Project) : ProjectWideLspServerDescript .toAbsolutePath() .toString() - return GeneralCommandLine("java", "-jar", serverPath) + // Check if user has supplied a custom path to java + val settingsState = SchemaSettings.getInstance().state + val javaPath = settingsState?.javaPath ?: "" + + val customJavaExecutable = listOf( + Paths.get(javaPath).resolve("java"), + Paths.get(javaPath).resolve("bin").resolve("java") + ).firstOrNull { it.isExecutable() } + + return if (customJavaExecutable != null) { + GeneralCommandLine(customJavaExecutable.toString(), "-jar", serverPath) + } else { + GeneralCommandLine("java", "-jar", serverPath) + } } } diff --git a/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/plugin.xml b/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/plugin.xml index 22b75f9dd5e3..39f4a3e9148f 100644 --- a/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/plugin.xml +++ b/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/plugin.xml @@ -19,6 +19,10 @@
  • Syntax highlighting
  • +

    Settings:

    +

    If you encounter issues running the language server, you can supply a custom path to java by changing the setting under "Languages & Frameworks": "Vespa Schema Language Server"

    +

    The language server requires Java 17 or higher. The supplied path should contain a java binary or a subdirectory "bin" containing the java binary.

    + ]]> Rewritten from scratch to include LSP support @@ -37,4 +41,16 @@ + + + + + +