From 48086ea62ce7cfa2c5a85aa57e7eac06de6863c0 Mon Sep 17 00:00:00 2001 From: Magnus Eide-Fredriksen Date: Thu, 14 Nov 2024 12:18:49 +0100 Subject: [PATCH 1/5] feat: lemminx extension in Intellij Plugin (validation and hover) --- .../clients/intellij/build.gradle.kts | 21 ++++++++-- .../schemals/intellij/LemminxVespaServer.java | 40 +++++++++++++++++++ .../intellij/LemminxVespaServerFactory.java | 11 +++++ .../src/main/resources/META-INF/lsp.xml | 17 ++++++++ .../src/main/resources/META-INF/plugin.xml | 2 + 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java create mode 100644 integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java create mode 100644 integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml diff --git a/integration/schema-language-server/clients/intellij/build.gradle.kts b/integration/schema-language-server/clients/intellij/build.gradle.kts index c250f4b84a0b..bdb5ee98314c 100644 --- a/integration/schema-language-server/clients/intellij/build.gradle.kts +++ b/integration/schema-language-server/clients/intellij/build.gradle.kts @@ -11,6 +11,14 @@ val JAVA_VERSION = "17" repositories { mavenCentral() + maven { + url = uri("https://repo.eclipse.org/content/repositories/lemminx") + metadataSources { + mavenPom() + artifact() + } + } + mavenLocal() maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") @@ -35,8 +43,13 @@ dependencies { implementation("org.jsoup:jsoup:1.17.2") implementation("com.vladsch.flexmark:flexmark-html2md-converter:0.64.8") + implementation("org.eclipse.lemminx:org.eclipse.lemminx:0.28.0:uber") { + exclude(group = "org.eclipse.lsp4j") + exclude(group = "com.google.code.gson") + } + intellijPlatform { - intellijIdeaCommunity("2024.2") + intellijIdeaUltimate("2024.2") instrumentationTools() plugin("com.redhat.devtools.lsp4ij:0.7.0") } @@ -68,14 +81,16 @@ tasks { } prepareSandbox { - val fromPath = "../../language-server/target/schema-language-server-jar-with-dependencies.jar" + val fromPathSchema = "../../language-server/target/schema-language-server-jar-with-dependencies.jar" + val fromPathLemminx = "../../lemminx-vespa/target/lemminx-vespa-jar-with-dependencies.jar" val toPath = pluginDirectory.get() // see: https://docs.gradle.org/8.7/userguide/configuration_cache.html#config_cache:requirements:disallowed_types val injected = project.objects.newInstance() doLast { injected.fs.copy { - from(fromPath) + from(fromPathSchema) + from(fromPathLemminx) into(toPath) } } diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java new file mode 100644 index 000000000000..d2e057876a00 --- /dev/null +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java @@ -0,0 +1,40 @@ +package ai.vespa.schemals.intellij; + +import com.intellij.openapi.project.Project; +import com.redhat.devtools.lsp4ij.server.JavaProcessCommandBuilder; +import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import com.intellij.openapi.extensions.PluginId; +import com.intellij.ide.plugins.PluginManagerCore; + +public class LemminxVespaServer extends ProcessStreamConnectionProvider { + public LemminxVespaServer(Project project) { + PluginId id = PluginId.getId("ai.vespa"); + var plugin = PluginManagerCore.getPlugin(id); + if (plugin == null) { + throw new IllegalStateException("Plugin " + id + " not found. Cannot start the Vespa Schema Language Support plugin."); + } + var pluginPath = plugin.getPluginPath(); + + var vespaServerPath = pluginPath + .resolve("lemminx-vespa-jar-with-dependencies.jar") + .toAbsolutePath() + .toString(); + + var lemminxPath = pluginPath + .resolve("lib") + .resolve("org.eclipse.lemminx-0.28.0-uber.jar") + .toAbsolutePath() + .toString(); + + List commands = new JavaProcessCommandBuilder(project, "vespaSchemaLanguageServer") + .setCp(lemminxPath + File.pathSeparator + vespaServerPath) + .create(); + commands.add("org.eclipse.lemminx.XMLServerLauncher"); + + super.setCommands(commands); + } +} diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java new file mode 100644 index 000000000000..c51af61df718 --- /dev/null +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java @@ -0,0 +1,11 @@ +package ai.vespa.schemals.intellij; +import com.redhat.devtools.lsp4ij.LanguageServerFactory; +import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider; +import com.intellij.openapi.project.Project; + +public class LemminxVespaServerFactory implements LanguageServerFactory { + @Override + public StreamConnectionProvider createConnectionProvider(Project project) { + return new LemminxVespaServer(project); + } +} diff --git a/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml b/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml new file mode 100644 index 000000000000..4c211280ad5d --- /dev/null +++ b/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml @@ -0,0 +1,17 @@ + + + + +
  • The services.xml file of Vespa Applications
  • + + ]]> +
    +
    + +
    +
    \ No newline at end of file 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 92b5b8c7d9dd..545278d96b66 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 @@ -39,4 +39,6 @@ In addition, the plugin will be available for community editions as well. serverId="vespaSchemaLanguageServer" languageId="vespaSchema"/> + From acc644bffbbd9feb327ecbe7a9a8dbe9b52ebef6 Mon Sep 17 00:00:00 2001 From: Magnus Eide-Fredriksen Date: Thu, 14 Nov 2024 15:57:16 +0100 Subject: [PATCH 2/5] fix: remove lsp4j classloading to be compatible with lsp4ij in XML client --- .../clients/intellij/build.gradle.kts | 2 +- .../schemals/intellij/LemminxVespaClient.java | 27 +++++++++++++++++ .../schemals/intellij/LemminxVespaServer.java | 29 +++++++++++++------ .../intellij/LemminxVespaServerFactory.java | 7 +++++ .../src/main/resources/META-INF/lsp.xml | 17 ----------- .../src/main/resources/META-INF/plugin.xml | 16 ++++++++-- 6 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java delete mode 100644 integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml diff --git a/integration/schema-language-server/clients/intellij/build.gradle.kts b/integration/schema-language-server/clients/intellij/build.gradle.kts index bdb5ee98314c..e32880f91d57 100644 --- a/integration/schema-language-server/clients/intellij/build.gradle.kts +++ b/integration/schema-language-server/clients/intellij/build.gradle.kts @@ -43,7 +43,7 @@ dependencies { implementation("org.jsoup:jsoup:1.17.2") implementation("com.vladsch.flexmark:flexmark-html2md-converter:0.64.8") - implementation("org.eclipse.lemminx:org.eclipse.lemminx:0.28.0:uber") { + implementation("org.eclipse.lemminx:org.eclipse.lemminx:0.28.0") { exclude(group = "org.eclipse.lsp4j") exclude(group = "com.google.code.gson") } diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java new file mode 100644 index 000000000000..8c403476cb58 --- /dev/null +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java @@ -0,0 +1,27 @@ +package ai.vespa.schemals.intellij; +import com.intellij.openapi.project.Project; +import com.redhat.devtools.lsp4ij.client.LanguageClientImpl; +import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.jsonrpc.CompletableFutures; +import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; +import org.eclipse.lemminx.customservice.XMLLanguageClientAPI; + +import java.util.concurrent.CompletableFuture; + +/* +The XMLLanguageClientAPI from LemMinX declares the custom LSP extensions they made. +It is two things: +- JSON Notification: "actionableNotification" (throws UnsupportedOperationException unless implemented here) +- JSON Request: "executeClientCommand" (this is the reason we implement it). + */ +public class LemminxVespaClient extends LanguageClientImpl implements XMLLanguageClientAPI { + public LemminxVespaClient(Project project) { super(project); } + + @Override + public CompletableFuture executeClientCommand(ExecuteCommandParams params) { + super.logMessage(new MessageParams(MessageType.Info, "Execute: " + params.toString())); + return CompletableFutures.computeAsync(cancelChecker -> { + return null; + }); + } +} diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java index d2e057876a00..e98306221c56 100644 --- a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServer.java @@ -5,33 +5,44 @@ import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider; import java.io.File; -import java.util.Arrays; import java.util.List; + import com.intellij.openapi.extensions.PluginId; import com.intellij.ide.plugins.PluginManagerCore; public class LemminxVespaServer extends ProcessStreamConnectionProvider { public LemminxVespaServer(Project project) { PluginId id = PluginId.getId("ai.vespa"); - var plugin = PluginManagerCore.getPlugin(id); - if (plugin == null) { + var vespaPlugin = PluginManagerCore.getPlugin(id); + if (vespaPlugin == null) { throw new IllegalStateException("Plugin " + id + " not found. Cannot start the Vespa Schema Language Support plugin."); } - var pluginPath = plugin.getPluginPath(); + var vespaPluginPath = vespaPlugin.getPluginPath(); + + var lsp4ijPlugin = PluginManagerCore.getPlugin(PluginId.getId("com.redhat.devtools.lsp4ij")); + if (lsp4ijPlugin == null) { + throw new IllegalStateException("LSP4IJ could not be found. Cannot start the Vespa Schema Language Support plugin."); + } - var vespaServerPath = pluginPath + var vespaServerPath = vespaPluginPath .resolve("lemminx-vespa-jar-with-dependencies.jar") .toAbsolutePath() .toString(); - var lemminxPath = pluginPath + var lemminxPath = vespaPluginPath + .resolve("lib") + .resolve("*") + .toAbsolutePath() + .toString(); + + var lsp4ijPath = lsp4ijPlugin.getPluginPath() .resolve("lib") - .resolve("org.eclipse.lemminx-0.28.0-uber.jar") + .resolve("*") .toAbsolutePath() .toString(); - List commands = new JavaProcessCommandBuilder(project, "vespaSchemaLanguageServer") - .setCp(lemminxPath + File.pathSeparator + vespaServerPath) + List commands = new JavaProcessCommandBuilder(project, "vespaLemminxLanguageServer") + .setCp(lemminxPath + File.pathSeparator + vespaServerPath + File.pathSeparator + lsp4ijPath) .create(); commands.add("org.eclipse.lemminx.XMLServerLauncher"); diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java index c51af61df718..a245e7315c59 100644 --- a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaServerFactory.java @@ -2,10 +2,17 @@ import com.redhat.devtools.lsp4ij.LanguageServerFactory; import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider; import com.intellij.openapi.project.Project; +import com.redhat.devtools.lsp4ij.client.LanguageClientImpl; +import org.eclipse.lsp4j.services.LanguageServer; public class LemminxVespaServerFactory implements LanguageServerFactory { @Override public StreamConnectionProvider createConnectionProvider(Project project) { return new LemminxVespaServer(project); } + + @Override + public LanguageClientImpl createLanguageClient(Project project) { + return new LemminxVespaClient(project); + } } diff --git a/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml b/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml deleted file mode 100644 index 4c211280ad5d..000000000000 --- a/integration/schema-language-server/clients/intellij/src/main/resources/META-INF/lsp.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - -
  • The services.xml file of Vespa Applications
  • - - ]]> -
    -
    - -
    -
    \ No newline at end of file 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 545278d96b66..d958cabef3ae 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 @@ -38,7 +38,19 @@ In addition, the plugin will be available for community editions as well. + + + +
  • The services.xml file of Vespa Applications
  • + + ]]> +
    +
    + - From 09380fcd8b4e944d09b41433c6e2bdc4721eb5ca Mon Sep 17 00:00:00 2001 From: Magnus Eide-Fredriksen Date: Fri, 22 Nov 2024 10:53:23 +0100 Subject: [PATCH 3/5] feat: schema commands from XML server in intellij client --- .../clients/intellij/build.gradle.kts | 2 ++ .../schemals/intellij/LemminxVespaClient.java | 26 +++++++++++++++++-- .../lsp/common/command/ExecuteCommand.java | 5 ++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/integration/schema-language-server/clients/intellij/build.gradle.kts b/integration/schema-language-server/clients/intellij/build.gradle.kts index e32880f91d57..e7347dc0e1d0 100644 --- a/integration/schema-language-server/clients/intellij/build.gradle.kts +++ b/integration/schema-language-server/clients/intellij/build.gradle.kts @@ -43,6 +43,8 @@ dependencies { implementation("org.jsoup:jsoup:1.17.2") implementation("com.vladsch.flexmark:flexmark-html2md-converter:0.64.8") + // Note: its quite important we ignore lsp4j, as the classes would collide + // with the lsp4ij plugins classes. implementation("org.eclipse.lemminx:org.eclipse.lemminx:0.28.0") { exclude(group = "org.eclipse.lsp4j") exclude(group = "com.google.code.gson") diff --git a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java index 8c403476cb58..540992088d4c 100644 --- a/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java +++ b/integration/schema-language-server/clients/intellij/src/main/java/ai/vespa/schemals/intellij/LemminxVespaClient.java @@ -1,11 +1,15 @@ package ai.vespa.schemals.intellij; import com.intellij.openapi.project.Project; +import com.redhat.devtools.lsp4ij.LanguageServerManager; import com.redhat.devtools.lsp4ij.client.LanguageClientImpl; +import com.redhat.devtools.lsp4ij.commands.CommandExecutor; +import com.redhat.devtools.lsp4ij.commands.LSPCommandContext; import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.jsonrpc.CompletableFutures; import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; import org.eclipse.lemminx.customservice.XMLLanguageClientAPI; +import java.util.Map; import java.util.concurrent.CompletableFuture; /* @@ -15,13 +19,31 @@ - JSON Request: "executeClientCommand" (this is the reason we implement it). */ public class LemminxVespaClient extends LanguageClientImpl implements XMLLanguageClientAPI { + + private static final Map clientVespaCommands = Map.of( + "vespaSchemaLS.commands.schema.findSchemaDefinition", "FIND_SCHEMA_DEFINITION", + "vespaSchemaLS.commands.schema.setupWorkspace", "SETUP_WORKSPACE", + "vespaSchemaLS.commands.schema.hasSetupWorkspace", "HAS_SETUP_WORKSPACE", + "vespaSchemaLS.commands.schema.createSchemaFile", "CREATE_SCHEMA_FILE", + "vespaSchemaLS.commands.schema.getDefinedSchemas", "GET_DEFINED_SCHEMAS" + ); + public LemminxVespaClient(Project project) { super(project); } @Override public CompletableFuture executeClientCommand(ExecuteCommandParams params) { super.logMessage(new MessageParams(MessageType.Info, "Execute: " + params.toString())); - return CompletableFutures.computeAsync(cancelChecker -> { + String commandKey = params.getCommand(); + + if (!clientVespaCommands.containsKey(commandKey)) { return null; - }); + } + + // Forward command to vespa schema LS + Command command = new Command("SchemaCommand", clientVespaCommands.get(commandKey)); + command.setArguments(params.getArguments()); + LSPCommandContext context = new LSPCommandContext(command, getProject()); + context.setPreferredLanguageServerId("vespaSchemaLanguageServer"); + return CommandExecutor.executeCommand(context).response(); } } diff --git a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/lsp/common/command/ExecuteCommand.java b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/lsp/common/command/ExecuteCommand.java index 4c97221f590a..cf1a2e58c91c 100644 --- a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/lsp/common/command/ExecuteCommand.java +++ b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/lsp/common/command/ExecuteCommand.java @@ -17,6 +17,11 @@ public static Object executeCommand(EventExecuteCommandContext context) { if (command.isEmpty()) { context.logger.error("Unknown command " + context.params.getCommand()); context.logger.error("Arguments:"); + if (context.params.getArguments() == null) { + context.logger.error("null"); + return null; + } + for (Object obj : context.params.getArguments()) { context.logger.info(obj.getClass().toString() + ": " + obj.toString()); } From f2616d6f779f9581ef8f17fd82c40d494317b96f Mon Sep 17 00:00:00 2001 From: Magnus Eide-Fredriksen Date: Fri, 22 Nov 2024 12:51:26 +0100 Subject: [PATCH 4/5] fix: chop documentation markdown at tables due to ugly formatting --- .../documentation/FetchDocumentation.java | 20 ++++++----- .../SchemaDocumentationFetcher.java | 35 +++---------------- .../ServicesDocumentationFetcher.java | 5 +++ 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/FetchDocumentation.java b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/FetchDocumentation.java index e36dda7fb3e0..238c81186c8e 100644 --- a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/FetchDocumentation.java +++ b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/FetchDocumentation.java @@ -48,15 +48,13 @@ public static void fetchSchemaDocs(Path targetPath) throws IOException { Map schemaMarkdownContent = new SchemaDocumentationFetcher(SCHEMA_URL).getMarkdownContent(); for (var entry : schemaMarkdownContent.entrySet()) { - String fileName = convertToToken(entry.getKey()); + String tokenName = convertToToken(entry.getKey()); String content = entry.getValue(); - if (REPLACE_FILENAME_MAP.containsKey(fileName)) { - for (String replacedFileName : REPLACE_FILENAME_MAP.get(fileName)) { - Files.write(writePath.resolve(replacedFileName + ".md"), content.getBytes(), StandardOpenOption.CREATE); - } - } else { - Files.write(writePath.resolve(fileName + ".md"), content.getBytes(), StandardOpenOption.CREATE); + List fileNamesToWrite = REPLACE_FILENAME_MAP.getOrDefault(tokenName, List.of(tokenName)); + + for (String fileName : fileNamesToWrite) { + writeMarkdown(writePath.resolve(fileName + ".md"), content); } } @@ -64,7 +62,7 @@ public static void fetchSchemaDocs(Path targetPath) throws IOException { writePath = targetPath.resolve("rankExpression"); for (var entry : rankFeatureMarkdownContent.entrySet()) { - Files.write(writePath.resolve(entry.getKey() + ".md"), entry.getValue().getBytes(), StandardOpenOption.CREATE); + writeMarkdown(writePath.resolve(entry.getKey() + ".md"), entry.getValue()); } } @@ -81,11 +79,15 @@ public static void fetchServicesDocs(Path targetPath) throws IOException { for (var entry : markdownContent.entrySet()) { if (entry.getKey().contains("/")) continue; String fileName = entry.getKey().toLowerCase(); - Files.write(writePath.resolve(fileName + ".md"), entry.getValue().getBytes(), StandardOpenOption.CREATE); + writeMarkdown(writePath.resolve(fileName + ".md"), entry.getValue()); } } } + private static void writeMarkdown(Path writePath, String markdown) throws IOException { + Files.write(writePath, markdown.getBytes(), StandardOpenOption.CREATE); + } + private static String convertToToken(String h2Id) { return h2Id.toUpperCase().replaceAll("-", "_"); } diff --git a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/SchemaDocumentationFetcher.java b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/SchemaDocumentationFetcher.java index 5746e5a63834..45c94e88dd80 100644 --- a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/SchemaDocumentationFetcher.java +++ b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/SchemaDocumentationFetcher.java @@ -75,13 +75,10 @@ Map getMarkdownContent() throws IOException { } if (element.tag().equals(Tag.valueOf("table"))) { - Element tbody = element.selectFirst("tbody"); - // replace all in tbody with - tbody.select("th").tagName("td"); - - // some tables have very big texts in td. For our purposes, only keep the first sentence. - if (prevH2.id().equals("field")) - manuallyFixFieldTable(tbody); + // The tables in the docs are inherently problematic + // so we just replace the first table and everything after with "read more" + prevH2 = null; + continue; } currentBuilder.append(element.outerHtml()); @@ -107,28 +104,4 @@ Map getMarkdownContent() throws IOException { } return result; } - - private static void manuallyFixFieldTable(Element tbodyElement) { - for (Element td : tbodyElement.select("tr td:nth-child(2)")) { - String curr = td.html(); - int level = 0; - int i; - for (i = 0; i < curr.length(); ++i) { - if (( - (curr.charAt(i) == '.' && !curr.substring(i-1, Math.min(curr.length(), i+3)).equals("i.e.") && !curr.substring(i-3,i+1).equals("i.e.")) - || curr.substring(i).startsWith("") - || curr.substring(i).startsWith("
    ") 
    -                    || curr.charAt(i) == ':') && level == 0) {
    -                    break;
    -                }
    -                if (curr.charAt(i) == '(')++level;
    -                if (curr.charAt(i) == ')')--level;
    -                if (curr.charAt(i) == '<')++level;
    -                if (curr.charAt(i) == '>')--level;
    -            }
    -            String firstSentence = curr.substring(0, i) + ".";
    -            td.html(firstSentence);
    -        }
    -    }
    -    
     }
    diff --git a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/ServicesDocumentationFetcher.java b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/ServicesDocumentationFetcher.java
    index 705d832c4875..e0af4979fbb5 100644
    --- a/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/ServicesDocumentationFetcher.java
    +++ b/integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/documentation/ServicesDocumentationFetcher.java
    @@ -97,6 +97,11 @@ Map getMarkdownContent() throws IOException {
                         currentBuilder.append(nodeIterator.toString());
                     continue;
                 }
    +            if (element.tag().equals(Tag.valueOf("table"))) {
    +                // tables are inherently problematic so we just replace everything after the first table with "read more"
    +                prevH2 = null;
    +                continue;
    +            }
     
                 currentBuilder.append(getElementHTML(element));
             }
    
    From 36347ddb5adde7a6450217bc0e4d983a918982b6 Mon Sep 17 00:00:00 2001
    From: Magnus Eide-Fredriksen 
    Date: Fri, 22 Nov 2024 13:00:36 +0100
    Subject: [PATCH 5/5] fix: support IntelliJ Community
    
    ---
     .../schema-language-server/clients/intellij/build.gradle.kts  | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/integration/schema-language-server/clients/intellij/build.gradle.kts b/integration/schema-language-server/clients/intellij/build.gradle.kts
    index e7347dc0e1d0..4fe9f7c28ca9 100644
    --- a/integration/schema-language-server/clients/intellij/build.gradle.kts
    +++ b/integration/schema-language-server/clients/intellij/build.gradle.kts
    @@ -51,7 +51,7 @@ dependencies {
       }
     
       intellijPlatform {
    -    intellijIdeaUltimate("2024.2")
    +    intellijIdeaCommunity("2024.2")
         instrumentationTools()
         plugin("com.redhat.devtools.lsp4ij:0.7.0")
       }
    @@ -112,4 +112,4 @@ tasks {
       publishPlugin {
         token.set(System.getenv("PUBLISH_TOKEN"))
       }
    -}
    \ No newline at end of file
    +}