M LSP.props => LSP.props +1 -1
@@ 71,7 71,7 @@ lsp.server.jdtls.command=${PLUGIN_HOME}/jdtls/bin/jdtls
lsp.server.jdtls.install=dir = lsp.Utils.getPluginSubdir("jdtls"); \
eclipseDownload(view, "jdtls", "1.23.0", dir); \
new File(dir, "bin/jdtls").setExecutable(true);
-lsp.server.jdtls.get-root=lsp.Utils.findRoot(buffer, new String[]{ "build.xml", "pom.xml", "settings.gradle", "settings.gradle.kts" })
+lsp.server.jdtls.get-root-uri=lsp.Utils.findRootURI(buffer, new String[]{ "build.xml", "pom.xml", "settings.gradle", "settings.gradle.kts" })
# Map a mode to the language server to use
mode.go.languageServer=gopls
M Makefile => Makefile +8 -1
@@ 21,7 21,14 @@ else
@make -f Makefile.macos userdocs
endif
+clean: get-build-support
+ifeq ($(UNAME), Linux)
+ @make -f Makefile.linux clean
+else
+ @make -f Makefile.macos clean
+endif
+
get-build-support:
@if [ ! -d build-support ]; then svn checkout svn://svn.code.sf.net/p/jedit/svn/build-support/trunk/ build-support; fi
-.PHONY: dist build userdocs get-build-support
+.PHONY: dist build userdocs clean get-build-support
M Makefile.linux => Makefile.linux +4 -1
@@ 16,4 16,7 @@ build:
userdocs:
$(ANT) userdocs
-.PHONY: dist build userdocs
+clean:
+ $(ANT) clean
+
+.PHONY: dist build userdocs clean
M lsp/ClientCommands.java => lsp/ClientCommands.java +1 -0
@@ 12,6 12,7 @@ import org.eclipse.lsp4j.WorkspaceEdit;
public class ClientCommands {
public static Map<String, ClientCommandHandler> commands;
+ // TODO: allow client command implementations to be written in Beanshell and registered via properties.
static {
commands = new HashMap<>();
commands.put("java.apply.workspaceEdit", ClientCommands::javaApplyWorkspaceEdit);
M lsp/Server.java => lsp/Server.java +38 -2
@@ 13,6 13,7 @@ import java.util.Arrays;
import java.util.ArrayList;
import java.io.IOException;
import java.net.URI;
+import java.net.URL;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ 74,6 75,7 @@ import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.launch.LSPLauncher;
import org.eclipse.lsp4j.services.LanguageServer;
+import org.gjt.sp.jedit.BeanShell;
import org.gjt.sp.jedit.Buffer;
import org.gjt.sp.jedit.EditPane;
import org.gjt.sp.jedit.Macros;
@@ 81,6 83,7 @@ import org.gjt.sp.jedit.Mode;
import org.gjt.sp.jedit.View;
import org.gjt.sp.jedit.jEdit;
import org.gjt.sp.jedit.bsh.UtilEvalError;
+import org.gjt.sp.jedit.bsh.NameSpace;
import org.gjt.sp.jedit.textarea.TextArea;
import org.gjt.sp.util.Log;
import org.gjt.sp.util.ThreadUtilities;
@@ 229,19 232,52 @@ public class Server {
}
}
+ private List<String> findWorkspaceFolders(Buffer buffer) {
+ List<String> roots = Utils.getProjectRootURIs(buffer);
+ if (!roots.isEmpty()) {
+ return roots;
+ }
+ if (this.serverDefinition.hasGetRootURI()) {
+ String script = this.serverDefinition.getGetRootURI();
+ log(Log.WARNING, "Executing get-root-uri script: " + script);
+ try {
+ NameSpace ns = new NameSpace(BeanShell.getNameSpace(), "LSP " + this.getName() + " findWorkspaceFolders()");
+ ns.setVariable("buffer", buffer);
+ Object result = BeanShell.eval(null, ns, script);
+ if (result instanceof String) {
+ return Collections.singletonList((String) result);
+ } else if ((result instanceof Path) || (result instanceof URI) || (result instanceof URL)) {
+ return Collections.singletonList(result.toString());
+ } else if (result instanceof List) {
+ List<String> convertedResult = new ArrayList<>();
+ for (Object item : ((List) result)) {
+ convertedResult.add(item.toString());
+ }
+ return convertedResult;
+ } else {
+ log(Log.WARNING, "get-root-uri script returned an invalid result: " + result.toString());
+ }
+ } catch (UtilEvalError e) {
+ log(Log.ERROR, "get-root-uri script threw an error", e);
+ }
+ } else {
+ log(Log.WARNING, "no get-root-uri script");
+ }
+ return Collections.emptyList();
+ }
+
/*
* Initializes the language server once it is running.
* See: https://github.com/eclipse/lsp4j/blob/0a3e64aa029ad7f760427a0dfd74f2a2d3e4ae97/org.eclipse.lsp4j/src/main/java/org/eclipse/lsp4j/Protocol.xtend#L4913
*/
private void initialize(Buffer buffer) throws UtilEvalError {
- // TODO: execute the get-root script, and pass that in to init
InitializeParams params = new InitializeParams();
params.setProcessId((int) ProcessHandle.current().pid());
//params.setInitializationOptions(initOptions);
params.setCapabilities(new ClientCapabilities(Capabilities.getWorkspace(), Capabilities.getDocument(), null));
params.setClientInfo(new ClientInfo("jEdit", jEdit.getVersion()));
- List<String> roots = Utils.getRootURIsWith(buffer);
+ List<String> roots = this.findWorkspaceFolders(buffer);
if (!roots.isEmpty()) {
this.workspaceFolders = roots.stream().map(root -> new WorkspaceFolder(root, "project root")).collect(Collectors.toList());
params.setWorkspaceFolders(this.workspaceFolders);
M lsp/ServerDefinition.java => lsp/ServerDefinition.java +12 -14
@@ 7,7 7,7 @@ public class ServerDefinition implements Comparable<ServerDefinition> {
private String name;
private String rawCommand;
private String installScript;
- //private String getRoot;
+ private String getRootURI;
public ServerDefinition(String name) {
this.name = name;
@@ 19,17 19,17 @@ public class ServerDefinition implements Comparable<ServerDefinition> {
if (this.installScript == null) {
this.installScript = "";
}
- //this.getRoot = jEdit.getProperty(getProp("get-root"));
- //if (this.getRoot == null) {
- // this.getRoot = "";
- //}
+ this.getRootURI = jEdit.getProperty(getProp("get-root-uri"));
+ if (this.getRootURI == null) {
+ this.getRootURI = "";
+ }
}
public void save() {
Log.log(Log.DEBUG, this, "Saving command as: " + this.rawCommand);
jEdit.setProperty(getProp("command"), this.rawCommand);
jEdit.setProperty(getProp("install"), this.installScript);
- //jEdit.setProperty(getProp("get-root"), this.getRoot);
+ jEdit.setProperty(getProp("get-root-uri"), this.getRootURI);
}
public String getName() {
@@ 62,19 62,17 @@ public class ServerDefinition implements Comparable<ServerDefinition> {
this.installScript = installScript;
}
- /*
- public String getGetRoot() {
- return this.getRoot;
+ public String getGetRootURI() {
+ return this.getRootURI;
}
- public void setGetRoot(String getRoot) {
- this.getRoot = getRoot;
+ public void setGetRootURI(String getRootURI) {
+ this.getRootURI = getRootURI;
}
- public boolean hasGetRoot() {
- return this.getRoot != null;
+ public boolean hasGetRootURI() {
+ return this.getRootURI != null && !this.getRootURI.isEmpty();
}
- */
@Override
public int compareTo(ServerDefinition other) {
M lsp/Utils.java => lsp/Utils.java +57 -33
@@ 20,6 20,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.function.Predicate;
import org.gjt.sp.jedit.Buffer;
@@ 27,6 29,8 @@ import org.gjt.sp.jedit.MiscUtilities;
import org.gjt.sp.jedit.Mode;
import org.gjt.sp.jedit.View;
import org.gjt.sp.jedit.jEdit;
+import org.gjt.sp.jedit.io.VFS;
+import org.gjt.sp.jedit.io.VFSFile;
//import org.gjt.sp.jedit.manager.BufferManagerImpl;
import org.gjt.sp.jedit.textarea.Selection;
import org.gjt.sp.jedit.textarea.TextArea;
@@ 42,10 46,6 @@ import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveEntry;
-import projectviewer.ProjectManager;
-import projectviewer.vpt.VPTNode;
-import projectviewer.vpt.VPTProject;
-
public class Utils {
private Utils() {}
@@ 316,23 316,14 @@ public class Utils {
return MiscUtilities.constructPath(LanguageServerPlugin.get().getPluginHome().getAbsolutePath(), name);
}
- public static List<VPTProject> getProjectsWith(Buffer buffer) {
- List<VPTProject> result = new ArrayList<>();
- for (VPTProject project : ProjectManager.getInstance().getProjects()) {
- project = ProjectManager.getInstance().getProject(project.getName()); // ensure it's loaded
- VPTNode node = project.getChildNode(buffer.getPath());
- if (node != null) {
- result.add(project);
- }
+ public static List<String> getProjectRootURIs(Buffer buffer) {
+ if (jEdit.getPlugin("projectviewer.ProjectPlugin") == null) {
+ return Collections.emptyList();
}
- return result;
- }
-
- public static List<String> getRootURIsWith(Buffer buffer) {
List<String> result = new ArrayList<>();
Path bufferPath = Paths.get(buffer.getPath());
- for (VPTProject project : ProjectManager.getInstance().getProjects()) {
- project = ProjectManager.getInstance().getProject(project.getName()); // ensure it's loaded
+ for (projectviewer.vpt.VPTProject project : projectviewer.ProjectManager.getInstance().getProjects()) {
+ project = projectviewer.ProjectManager.getInstance().getProject(project.getName()); // ensure it's loaded
// XXX: we don't care about projects containing buffer but with buffer outside of the root path, do we?
if (bufferPath.startsWith(project.getRootPath())) {
// TODO: support VFS?
@@ 342,32 333,65 @@ public class Utils {
return result;
}
- // Methods for finding the project root, currently unused in favor of ProjectViewer integration.
+ // Methods for finding the project root, when one is not found via ProjectViewer.
+
+ @FunctionalInterface
+ public interface VfsPredicate {
+ boolean test(VFS vfs, Object session, View view, String dir);
+ }
- public static Path findRoot(Path dir, Predicate<Path> pred) {
- if (dir == null) {
+ private static String findRootURI(VFS vfs, Object vfsSession, View view, String dir, VfsPredicate pred) {
+ if (dir == null || dir.isEmpty()) {
+ return null;
+ }
+ if (pred.test(vfs, vfsSession, view, dir)) {
+ return vfs.getName() + "://" + dir;
+ }
+ String parent = vfs.getParentOfPath(dir);
+ if (parent != null && parent.equals(dir)) {
+ // we've hit the root and can't go further
return null;
}
- if (pred.test(dir)) {
- return dir;
+ return findRootURI(vfs, vfsSession, view, vfs.getParentOfPath(dir), pred);
+ }
+
+ public static String findRootURI(VFS vfs, String dir, VfsPredicate pred) {
+ View view = jEdit.getActiveView();
+ Object vfsSession = vfs.createVFSSessionSafe(dir, view);
+ try {
+ try {
+ return findRootURI(vfs, vfsSession, view, dir, pred);
+ } finally {
+ vfs._endVFSSession(vfsSession, view);
+ }
+ } catch (IOException e) {
+ Log.log(Log.ERROR, Utils.class, "Error closing VFS session", e);
+ return null;
}
- return findRoot(dir.getParent(), pred);
}
- public static Path findRoot(Buffer buffer, Predicate<Path> pred) {
- return findRoot(Paths.get(buffer.getDirectory()), pred);
+ public static String findRootURI(Buffer buffer, VfsPredicate pred) {
+ return findRootURI(buffer.getVFS(), buffer.getDirectory(), pred);
}
- public static Path findRoot(Buffer buffer, String file) {
- return findRoot(buffer, new String[]{file});
+ public static String findRootURI(Buffer buffer, String file) {
+ return findRootURI(buffer, new String[]{file});
}
- public static Path findRoot(Buffer buffer, String[] files) {
- return findRoot(Paths.get(buffer.getDirectory()), (dir) -> {
- for (String file : files) {
- if (Files.exists(dir.resolve(file))) {
- return true;
+ public static String findRootURI(Buffer buffer, String[] files) {
+ return findRootURI(buffer.getVFS(), buffer.getDirectory(), (vfs, session, view, dir) -> {
+ try {
+ Set<String> listedFileNames = new TreeSet<>();
+ for (VFSFile file : vfs._listFiles(session, dir, view)) {
+ listedFileNames.add(file.getName());
+ }
+ for (String file : files) {
+ if (listedFileNames.contains(file)) {
+ return true;
+ }
}
+ } catch (IOException e) {
+ Log.log(Log.ERROR, Utils.class, "Error listing files while getting root URI", e);
}
return false;
});
M lsp/jEditLanguageClient.java => lsp/jEditLanguageClient.java +15 -11
@@ 69,11 69,6 @@ import com.google.gson.JsonObject;
import errorlist.DefaultErrorSource.DefaultError;
-import projectviewer.ProjectManager;
-import projectviewer.vpt.VPTProject;
-import projectviewer.vpt.VPTDirectory;
-import projectviewer.vpt.VPTFile;
-
// See https://github.com/eclipse/lsp4j/blob/main/org.eclipse.lsp4j/src/main/java/org/eclipse/lsp4j/services/LanguageClient.java
public class jEditLanguageClient implements LanguageClient {
@@ 748,17 743,23 @@ public class jEditLanguageClient implements LanguageClient {
// NOTE: This doesn't seem to refresh the ProjectViewer interface.
// Running AutoReimporter.runNow() does, but that seems heavy-handed.
private void addToProjects(boolean isDir, String uri) {
+ if (jEdit.getPlugin("projectviewer.ProjectPlugin") == null) {
+ return;
+ }
Log.log(Log.DEBUG, this, "Adding to projects: " + uri);
try {
- for (VPTProject project : ProjectManager.getInstance().getProjects()) {
- project = ProjectManager.getInstance().getProject(project.getName()); // ensure it's loaded
+ for (projectviewer.vpt.VPTProject project : projectviewer.ProjectManager.getInstance().getProjects()) {
+ project = projectviewer.ProjectManager.getInstance().getProject(project.getName()); // ensure it's loaded
if (Paths.get(new URI(uri).getPath()).startsWith(Paths.get(project.getRootPath()))) {
if (isDir) {
Log.log(Log.DEBUG, this, "Registering new directory in " + project + ": " + uri);
- project.registerNodePath(new VPTDirectory(uri));
+ // NOTE: For some reason, the call to project.registerNodePath() causes the plugin to
+ // fail loading due to a NoClassDefFound error if we try to make ProjectViewer an
+ // optional dependency.
+ project.registerNodePath(new projectviewer.vpt.VPTDirectory(uri));
} else {
Log.log(Log.DEBUG, this, "Registering new file in " + project + ": " + uri);
- project.registerNodePath(new VPTFile(uri));
+ project.registerNodePath(new projectviewer.vpt.VPTFile(uri));
}
} else {
Log.log(Log.WARNING, this, "URI " + uri + " does not start with " + project.getRootPath());
@@ 774,9 775,12 @@ public class jEditLanguageClient implements LanguageClient {
}
private void removeFromProjects(String uri) {
+ if (jEdit.getPlugin("projectviewer.ProjectPlugin") == null) {
+ return;
+ }
Log.log(Log.DEBUG, this, "Removing from projects: " + uri);
- for (VPTProject project : ProjectManager.getInstance().getProjects()) {
- project = ProjectManager.getInstance().getProject(project.getName()); // ensure it's loaded
+ for (projectviewer.vpt.VPTProject project : projectviewer.ProjectManager.getInstance().getProjects()) {
+ project = projectviewer.ProjectManager.getInstance().getProject(project.getName()); // ensure it's loaded
Log.log(Log.DEBUG, this, "Removing path from " + project + ": " + uri);
project.unregisterNodePath(uri);
}