diff --git a/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestJSONResultLimitPreference.java b/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestJSONResultLimitPreference.java
new file mode 100644
index 0000000000..21e1b18887
--- /dev/null
+++ b/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestJSONResultLimitPreference.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2026 Vogella GmbH and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Lars Vogel (Vogella GmbH) - initial implementation
+ *******************************************************************************/
+package org.eclipse.wildwebdeveloper.tests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.lsp4e.LSPEclipseUtils;
+import org.eclipse.lsp4e.LanguageServers;
+import org.eclipse.lsp4e.LanguageServersRegistry;
+import org.eclipse.lsp4j.DocumentSymbolParams;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.eclipse.lsp4j.TextDocumentIdentifier;
+import org.eclipse.lsp4j.services.LanguageServer;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.tests.harness.util.DisplayHelper;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+import org.eclipse.wildwebdeveloper.Activator;
+import org.eclipse.wildwebdeveloper.json.JSonLanguageServer;
+import org.eclipse.wildwebdeveloper.json.ui.preferences.JSonPreferenceServerConstants;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(AllCleanRule.class)
+class TestJSONResultLimitPreference {
+
+ private static final int KEYS = 60;
+ private static final int REDUCED_LIMIT = 5;
+
+ private IProject project;
+
+ @BeforeEach
+ void setUpProject() throws Exception {
+ this.project = ResourcesPlugin.getWorkspace().getRoot().getProject(getClass().getName() + System.nanoTime());
+ project.create(null);
+ project.open(null);
+ }
+
+ @AfterEach
+ void resetPreference() {
+ Activator.getDefault().getPreferenceStore().setValue(
+ JSonPreferenceServerConstants.JSON_PREFERENCES_MAXITEMSCOMPUTED,
+ JSonPreferenceServerConstants.MAXITEMSCOMPUTED_DEFAULT);
+ }
+
+ @Test
+ void testResultLimitPreferenceAppliesWithoutRestart() throws Exception {
+ StringBuilder content = new StringBuilder("{\n");
+ for (int i = 0; i < KEYS; i++) {
+ content.append(" \"key_").append(i).append("\": ").append(i).append(i == KEYS - 1 ? "\n" : ",\n");
+ }
+ content.append("}\n");
+
+ IFile file = project.getFile("limit.json");
+ file.create(content.toString().getBytes(StandardCharsets.UTF_8), true, false, null);
+
+ AbstractTextEditor editor = (AbstractTextEditor) IDE.openEditor(
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file,
+ "org.eclipse.ui.genericeditor.GenericEditor");
+ IDocument document = LSPEclipseUtils.getDocument(editor);
+ DisplayHelper.sleep(2000);
+
+ assertEquals(KEYS, countSymbols(document), "Default limit should not truncate this document");
+
+ Activator.getDefault().getPreferenceStore()
+ .setValue(JSonPreferenceServerConstants.JSON_PREFERENCES_MAXITEMSCOMPUTED, REDUCED_LIMIT);
+ DisplayHelper.sleep(1500); // allow the asynchronous preference broadcast
+
+ // exact, so that an empty result does not silently satisfy the assertion
+ assertEquals(REDUCED_LIMIT, countSymbols(document),
+ "Lowering the limit should truncate the outline to exactly that many symbols");
+ }
+
+ private static int countSymbols(IDocument document) throws Exception {
+ DocumentSymbolParams params = new DocumentSymbolParams(
+ new TextDocumentIdentifier(LSPEclipseUtils.toUri(document).toString()));
+ return jsonLanguageServer(document).getTextDocumentService().documentSymbol(params).get(10, TimeUnit.SECONDS)
+ .size();
+ }
+
+ private static LanguageServer jsonLanguageServer(IDocument document) throws Exception {
+ return LanguageServers.forDocument(document) //
+ .withCapability(ServerCapabilities::getDocumentSymbolProvider) //
+ .collectAll((wrapper, ls) -> CompletableFuture.completedFuture( //
+ LanguageServersRegistry.getInstance()
+ .getDefinition(JSonLanguageServer.JSON_LANGUAGE_SERVER_ID)
+ .equals(wrapper.serverDefinition) ? ls : null)) //
+ .get(10, TimeUnit.SECONDS).stream() //
+ .filter(Objects::nonNull) //
+ .findFirst() //
+ .orElseThrow(() -> new AssertionError("Expected a running JSON language server for the document"));
+ }
+}
diff --git a/org.eclipse.wildwebdeveloper/META-INF/MANIFEST.MF b/org.eclipse.wildwebdeveloper/META-INF/MANIFEST.MF
index 244554cef4..dbaf9f80c9 100644
--- a/org.eclipse.wildwebdeveloper/META-INF/MANIFEST.MF
+++ b/org.eclipse.wildwebdeveloper/META-INF/MANIFEST.MF
@@ -41,4 +41,6 @@ Export-Package: org.eclipse.wildwebdeveloper;x-friends:="org.eclipse.wildwebdeve
org.eclipse.wildwebdeveloper.debug.npm;x-internal:=true,
org.eclipse.wildwebdeveloper.markdown;x-friends:="org.eclipse.wildwebdeveloper.tests",
org.eclipse.wildwebdeveloper.jsts;x-friends:="org.eclipse.wildwebdeveloper.tests",
- org.eclipse.wildwebdeveloper.jsts.ui.preferences;x-friends:="org.eclipse.wildwebdeveloper.tests"
+ org.eclipse.wildwebdeveloper.jsts.ui.preferences;x-friends:="org.eclipse.wildwebdeveloper.tests",
+ org.eclipse.wildwebdeveloper.json;x-friends:="org.eclipse.wildwebdeveloper.tests",
+ org.eclipse.wildwebdeveloper.json.ui.preferences;x-friends:="org.eclipse.wildwebdeveloper.tests"
diff --git a/org.eclipse.wildwebdeveloper/plugin.properties b/org.eclipse.wildwebdeveloper/plugin.properties
index 2cfd9b95dd..178822972e 100644
--- a/org.eclipse.wildwebdeveloper/plugin.properties
+++ b/org.eclipse.wildwebdeveloper/plugin.properties
@@ -48,6 +48,7 @@ JSTSFormatterPreferencePage.name=Formatter
# Markdown
MarkdownPreferencePage.name=Markdown (Wild Web Developer)
+JSonPreferencePage.name=JSON (Wild Web Developer)
MarkdownProblem=Markdown Problem
# YAML
@@ -69,3 +70,4 @@ preferenceKeywords.scss=scss
preferenceKeywords.sass=sass
preferenceKeywords.html=html
preferenceKeywords.markdown=markdown
+preferenceKeywords.json=json
diff --git a/org.eclipse.wildwebdeveloper/plugin.xml b/org.eclipse.wildwebdeveloper/plugin.xml
index 9ad200e3bf..99ee8c9c08 100644
--- a/org.eclipse.wildwebdeveloper/plugin.xml
+++ b/org.eclipse.wildwebdeveloper/plugin.xml
@@ -131,6 +131,19 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/JSonLanguageServer.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/JSonLanguageServer.java
index f27457de92..36279a0ce2 100644
--- a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/JSonLanguageServer.java
+++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/JSonLanguageServer.java
@@ -37,7 +37,7 @@
import org.eclipse.lsp4e.LanguageServers;
import org.eclipse.lsp4e.LanguageServersRegistry;
import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition;
-import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
+import org.eclipse.lsp4j.DidChangeConfigurationParams;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage;
@@ -46,20 +46,26 @@
import org.eclipse.wildwebdeveloper.SchemaAssociationRegistry;
import org.eclipse.wildwebdeveloper.SchemaAssociationsPreferenceInitializer;
import org.eclipse.wildwebdeveloper.embedder.node.NodeJSManager;
+import org.eclipse.wildwebdeveloper.json.ui.preferences.JSonPreferenceServerConstants;
+import org.eclipse.wildwebdeveloper.ui.preferences.ProcessStreamConnectionProviderWithPreference;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
@SuppressWarnings("restriction")
-public class JSonLanguageServer extends ProcessStreamConnectionProvider {
+public class JSonLanguageServer extends ProcessStreamConnectionProviderWithPreference {
public final static String SCHEMA_EXT = "org.eclipse.wildwebdeveloper.json.schema"; //$NON-NLS-1$
public final static String PATTERN_ATTR = "pattern"; //$NON-NLS-1$
public final static String URL_ATTR = "url"; //$NON-NLS-1$
+ public static final String JSON_LANGUAGE_SERVER_ID = "org.eclipse.wildwebdeveloper.json"; //$NON-NLS-1$
+
+ private static final String[] SUPPORTED_SECTIONS = { "json" }; //$NON-NLS-1$
+
private static final IPreferenceStore PREFERENCE_STORE = Activator.getDefault().getPreferenceStore();
private static final LanguageServerDefinition JSON_LS_DEFINITION = LanguageServersRegistry.getInstance()
- .getDefinition("org.eclipse.wildwebdeveloper.json");
+ .getDefinition(JSON_LANGUAGE_SERVER_ID);
private static final IPropertyChangeListener PROPERTY_CHANGE_LISTENER = new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
@@ -74,6 +80,7 @@ public void propertyChange(PropertyChangeEvent event) {
};
public JSonLanguageServer() {
+ super(JSON_LANGUAGE_SERVER_ID, PREFERENCE_STORE, SUPPORTED_SECTIONS);
List commands = new ArrayList<>();
commands.add(NodeJSManager.getNodeJsLocation().getAbsolutePath());
try {
@@ -96,10 +103,16 @@ public void handleMessage(Message message, LanguageServer languageServer, URI ro
// Language server side.
JSonLanguageServerInterface server = (JSonLanguageServerInterface) languageServer;
server.sendJSonchemaAssociations(getSchemaAssociations());
+ server.getWorkspaceService().didChangeConfiguration(new DidChangeConfigurationParams(createSettings()));
}
}
}
+ @Override
+ protected Object createSettings() {
+ return JSonPreferenceServerConstants.getGlobalSettings();
+ }
+
private static Map> getSchemaAssociations() {
Map> associations = new HashMap<>();
fillSchemaAssociationsFromPreferenceStore(associations);
diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/Messages.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/Messages.java
new file mode 100644
index 0000000000..ad31f11c5f
--- /dev/null
+++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/Messages.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2026 Vogella GmbH and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Lars Vogel (Vogella GmbH) - initial implementation
+ *******************************************************************************/
+package org.eclipse.wildwebdeveloper.json.ui;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * JSON messages keys.
+ *
+ */
+public class Messages extends NLS {
+
+ // --------- JSON Main preference page
+ public static String JSonPreferencePage_maxItemsComputed;
+
+ static {
+ NLS.initializeMessages("org.eclipse.wildwebdeveloper.json.ui.messages", Messages.class); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/messages.properties b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/messages.properties
new file mode 100644
index 0000000000..0a1aabfc46
--- /dev/null
+++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/messages.properties
@@ -0,0 +1,14 @@
+#/*******************************************************************************
+# * Copyright (c) 2026 Vogella GmbH and others.
+# * This program and the accompanying materials are made
+# * available under the terms of the Eclipse Public License 2.0
+# * which is available at https://www.eclipse.org/legal/epl-2.0/
+# *
+# * SPDX-License-Identifier: EPL-2.0
+# *
+# * Contributors:
+# * Lars Vogel (Vogella GmbH) - initial implementation
+# *******************************************************************************/
+
+# Preference main page
+JSonPreferencePage_maxItemsComputed=The maximum number of outline symbols and folding\nregions computed (limited for performance reasons, 0 means no limit).
diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferenceInitializer.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferenceInitializer.java
new file mode 100644
index 0000000000..ddbeb66e95
--- /dev/null
+++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferenceInitializer.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2026 Vogella GmbH and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Lars Vogel (Vogella GmbH) - initial implementation
+ *******************************************************************************/
+package org.eclipse.wildwebdeveloper.json.ui.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+
+/**
+ * JSON preference initializer.
+ *
+ */
+public class JSonPreferenceInitializer extends AbstractPreferenceInitializer {
+
+ @Override
+ public void initializeDefaultPreferences() {
+ JSonPreferenceServerConstants.initializeDefaultPreferences();
+ }
+
+}
diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferencePage.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferencePage.java
new file mode 100644
index 0000000000..01fb424d08
--- /dev/null
+++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferencePage.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2026 Vogella GmbH and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Lars Vogel (Vogella GmbH) - initial implementation
+ *******************************************************************************/
+package org.eclipse.wildwebdeveloper.json.ui.preferences;
+
+import static org.eclipse.wildwebdeveloper.json.ui.preferences.JSonPreferenceServerConstants.JSON_PREFERENCES_MAXITEMSCOMPUTED;
+
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.IntegerFieldEditor;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.wildwebdeveloper.Activator;
+import org.eclipse.wildwebdeveloper.json.ui.Messages;
+
+/**
+ * JSON main preference page.
+ *
+ */
+public class JSonPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
+
+ public JSonPreferencePage() {
+ super(GRID);
+ }
+
+ @Override
+ public void init(IWorkbench workbench) {
+ setPreferenceStore(Activator.getDefault().getPreferenceStore());
+ }
+
+ @Override
+ protected void createFieldEditors() {
+ IntegerFieldEditor maxItemsComputed = new IntegerFieldEditor(JSON_PREFERENCES_MAXITEMSCOMPUTED,
+ Messages.JSonPreferencePage_maxItemsComputed, getFieldEditorParent());
+ maxItemsComputed.setValidRange(0, Integer.MAX_VALUE);
+ addField(maxItemsComputed);
+ }
+
+}
diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferenceServerConstants.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferenceServerConstants.java
new file mode 100644
index 0000000000..b4d3c3782b
--- /dev/null
+++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/json/ui/preferences/JSonPreferenceServerConstants.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2026 Vogella GmbH and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Lars Vogel (Vogella GmbH) - initial implementation
+ *******************************************************************************/
+package org.eclipse.wildwebdeveloper.json.ui.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.wildwebdeveloper.Activator;
+import org.eclipse.wildwebdeveloper.ui.preferences.Settings;
+
+/**
+ * JSON preference server constants.
+ *
+ */
+public class JSonPreferenceServerConstants {
+
+ private static final String JSON_SECTION = "json"; //$NON-NLS-1$
+
+ /**
+ * Equivalent of VSCode's json.maxItemsComputed. Also drives the folding limits
+ * below, as VSCode does. 0 means no limit.
+ */
+ public static final String JSON_PREFERENCES_MAXITEMSCOMPUTED = "json.resultLimit"; //$NON-NLS-1$
+
+ private static final String JSON_PREFERENCES_JSON_FOLDINGLIMIT = "json.jsonFoldingLimit"; //$NON-NLS-1$
+ private static final String JSON_PREFERENCES_JSONC_FOLDINGLIMIT = "json.jsoncFoldingLimit"; //$NON-NLS-1$
+ private static final String JSON_PREFERENCES_VALIDATE_ENABLE = "json.validate.enable"; //$NON-NLS-1$
+ private static final String JSON_PREFERENCES_FORMAT_ENABLE = "json.format.enable"; //$NON-NLS-1$
+ private static final String HTTP_PREFERENCES_PROXYSTRICTSSL = "http.proxyStrictSSL"; //$NON-NLS-1$
+
+ public static final int MAXITEMSCOMPUTED_DEFAULT = 5000;
+
+ /**
+ * The server re-reads all of its settings from every notification, so entries
+ * that only restate a default still have to be sent: without "validate.enable"
+ * it turns validation off, and without "http.proxyStrictSSL" it stops verifying
+ * certificates when downloading schemas.
+ */
+ public static Settings getGlobalSettings() {
+ IPreferenceStore store = Activator.getDefault().getPreferenceStore();
+ Settings settings = new Settings(store);
+
+ int maxItemsComputed = store.getInt(JSON_PREFERENCES_MAXITEMSCOMPUTED);
+ settings.fillSetting(JSON_PREFERENCES_MAXITEMSCOMPUTED, maxItemsComputed);
+ settings.fillSetting(JSON_PREFERENCES_JSON_FOLDINGLIMIT, maxItemsComputed);
+ settings.fillSetting(JSON_PREFERENCES_JSONC_FOLDINGLIMIT, maxItemsComputed);
+
+ settings.fillSetting(JSON_PREFERENCES_VALIDATE_ENABLE, Boolean.TRUE);
+ settings.fillSetting(JSON_PREFERENCES_FORMAT_ENABLE, Boolean.TRUE);
+ settings.fillSetting(HTTP_PREFERENCES_PROXYSTRICTSSL, Boolean.TRUE);
+
+ return settings;
+ }
+
+ public static void initializeDefaultPreferences() {
+ IPreferenceStore store = Activator.getDefault().getPreferenceStore();
+ store.setDefault(JSON_PREFERENCES_MAXITEMSCOMPUTED, MAXITEMSCOMPUTED_DEFAULT);
+ }
+
+ public static boolean isMatchJSonSection(String section) {
+ return Settings.isMatchSection(section, JSON_SECTION);
+ }
+
+}