~damien/jedit-lsp

8cbb6307cf48afd9bb41393a0c977cbc8c5dbdc4 — Damien Radtke 4 months ago 9615a34
Improve settings support
3 files changed, 79 insertions(+), 26 deletions(-)

M lsp/Server.java
M lsp/Settings.java
M lsp/jEditLanguageClient.java
M lsp/Server.java => lsp/Server.java +12 -0
@@ 48,6 48,7 @@ import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.CompletionParams;
import org.eclipse.lsp4j.DefinitionParams;
import org.eclipse.lsp4j.DidChangeConfigurationParams;
import org.eclipse.lsp4j.DocumentDiagnosticParams;
import org.eclipse.lsp4j.DocumentDiagnosticReport;
import org.eclipse.lsp4j.DocumentFormattingParams;


@@ 295,6 296,7 @@ public class Server {
				log(Log.DEBUG, "Initialization response: " + result.toString());
				this.handle.getRemoteProxy().initialized(new InitializedParams());
				this.initResult = result;
				sendConfiguration();
				Synchronization.didOpenAll(this);
				Utils.showTemporaryMessage("Server ready");
			} catch (Exception e) {


@@ 304,6 306,16 @@ public class Server {
		}));
	}

	private void sendConfiguration() {
		try {
			Settings settings = Settings.get(this.workspaceFolders);
			DidChangeConfigurationParams params = new DidChangeConfigurationParams(settings.getAll());
			this.handle.getRemoteProxy().getWorkspaceService().didChangeConfiguration(params);
		} catch (Exception e) {
			log(Log.WARNING, "Failed to send initial configuration", e);
		}
	}

	/*
	 * Executes the lsp.pull-diagnostics action.
	 */

M lsp/Settings.java => lsp/Settings.java +61 -8
@@ 3,11 3,19 @@ package lsp;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

import org.gjt.sp.jedit.Buffer;
import org.gjt.sp.jedit.jEdit;
import org.gjt.sp.jedit.OperatingSystem;
import org.gjt.sp.util.Log;

import org.eclipse.lsp4j.WorkspaceFolder;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;


@@ 16,10 24,24 @@ import com.google.gson.JsonPrimitive;
public class Settings {
	private Map<String, Object> settings;

	public Settings(File file) throws IOException {
	private Settings() {
		this(Collections.emptyMap());
	}

	private Settings(Map<String, Object> settings) {
		this.settings = settings;
	}

	private Settings(String parent, String path) {
		Buffer buffer = jEdit.openTemporary(null, parent, path, false);
		String text = buffer.getText();
		jEdit._closeBuffer(null, buffer);

		this.settings = new HashMap<>();
		JsonObject root = JsonParser.parseReader(new FileReader(file)).getAsJsonObject();
		load(root, null);
		if (!text.isEmpty()) {
			JsonObject root = JsonParser.parseString(text).getAsJsonObject();
			load(root, null);
		}
	}

	private void load(JsonObject object, String prefix) {


@@ 47,19 69,50 @@ public class Settings {
		}
	}

	public Map<String, Object> getSettings() {
		return this.settings;
	private Settings merge(Settings other) {
		if (other == null || other.settings.isEmpty()) {
			return this;
		}
		Map<String, Object> mergedSettings = new HashMap<>(this.settings);
		mergedSettings.putAll(other.settings);
		return new Settings(mergedSettings);
	}

	public Map<String, Object> getSettingsForScope(String section) {
	public Map<String, Object> getSection(String section) {
		String prefix = section + ".";
		Map<String, Object> sectionSettings = new HashMap<>();
		for (Map.Entry<String, Object> entry : this.settings.entrySet()) {
			String key = entry.getKey();
			if (key.startsWith(prefix)) {
				sectionSettings.put(key.substring(prefix.length()), entry.getValue());
			if (key.equals(section) || key.startsWith(prefix)) {
				sectionSettings.put(key, entry.getValue());
			}
		}
		return sectionSettings;
	}

	public Map<String, Object> getAll() {
		return this.settings;
	}

	public static Settings get(List<WorkspaceFolder> workspaceFolders) {
		Settings settings = new Settings();

		// See https://code.visualstudio.com/docs/getstarted/settings#_settings-file-locations
		if (OperatingSystem.isWindows()) {
			String appData = System.getenv("APPDATA");
			if (appData != null) {
				settings = settings.merge(new Settings(appData, "Code/User/settings.json"));
			}
		} else if (OperatingSystem.isMacOS()) {
			settings = settings.merge(new Settings(System.getProperty("user.home"), "Library/Application Support/Code/User/settings.json"));
		} else if (OperatingSystem.isUnix()) {
			settings = settings.merge(new Settings(System.getProperty("user.home"), ".config/Code/User/settings.json"));
		}

		for (WorkspaceFolder folder : workspaceFolders) {
			settings = settings.merge(new Settings(folder.getUri(), ".vscode/settings.json"));
			settings = settings.merge(new Settings(folder.getUri(), ".jedit/settings.json"));
		}
		return settings;
	}
}

M lsp/jEditLanguageClient.java => lsp/jEditLanguageClient.java +6 -18
@@ 307,27 307,15 @@ public class jEditLanguageClient implements LanguageClient {
		Log.log(Log.DEBUG, this, "configuration: " + params.toString());
		CompletableFuture<List<Object>> future = new CompletableFuture<>();
		ThreadUtilities.runInBackground(() -> {
			// TODO: iterate over all workspace folders, and merge the results
			List<Object> config = new ArrayList<>(params.getItems().size());
			List<WorkspaceFolder> folders = this.server.getWorkspaceFolders();
			if (!folders.isEmpty()) {
				// TODO: use VFS?
				String rootPath = folders.get(0).getUri();
				if (rootPath.startsWith("file://")) {
					rootPath = rootPath.substring(7);
				}
				try {
					Settings settings = new Settings(new File(rootPath, ".vscode/settings.json"));
					for (ConfigurationItem item : params.getItems()) {
						config.add(settings.getSettingsForScope(item.getSection()));
					}
				} catch (IOException e) {
					Log.log(Log.ERROR, this, "Error loading configuration settings:", e);
				}
			} else {
			try {
				Settings settings = Settings.get(this.server.getWorkspaceFolders());
				for (ConfigurationItem item : params.getItems()) {
					config.add(null);
					// TODO: support the scope parameter?
					config.add(settings.getSection(item.getSection()));
				}
			} catch (Exception e) {
				Log.log(Log.WARNING, this, "Failed to load requested configuration", e);
			}
			future.complete(config);
		});