import os import sys import tarfile from urllib import request from .lsp import LspServer, command, get_data_home FILE_URI = "file://" VERSION = "0.64.0" DOWNLOADS_URI = "http://download.eclipse.org/jdtls/milestones/{version}/{file}" LATEST = "latest.txt" def locate_product_directory (jdt_ls_path): if os.path.isdir(os.path.join(jdt_ls_path, "plugins")): return jdt_ls_path return os.path.join(jdt_ls_path, "org.eclipse.jdt.ls.product/target/repository") def locate_launcher_jar (jdt_ls_path): plugins_directory = os.path.join(jdt_ls_path, "plugins") return os.path.join(plugins_directory, [jar for jar in os.listdir(plugins_directory) if jar.startswith("org.eclipse.equinox.launcher_")][0]) def locate_launcher_configuration (jdt_ls_path): return os.path.join(jdt_ls_path, "config_linux") def log (message, *args, **kwargs): print(message.format(*args, **kwargs), file=sys.stderr) def download_jdt_ls (destination): if not os.path.isdir(destination): os.makedirs(destination) current_version = None current_version_file = os.path.join(destination, LATEST) if os.path.isfile(current_version_file): with open(current_version_file) as f: current_version = f.read().strip() log("Currently downloaded version is {version}:", version=current_version) latest_version = None with request.urlopen(DOWNLOADS_URI.format(version=VERSION, file=LATEST)) as f: latest_version = f.read().decode().strip() log("Latest available version is {version}:", version=latest_version) if not latest_version == current_version: latest_uri = DOWNLOADS_URI.format(version=VERSION, file=latest_version) log("Downloading latest version from: {uri}:", uri=latest_uri) with request.urlopen(latest_uri) as f: with tarfile.open(fileobj=f, mode="r|gz") as tar: tar.extractall(destination) print(tar) with open(current_version_file, "w") as cvf: cvf.write(latest_version) return destination # TODO def locate_lombok (): return os.path.join(os.environ['HOME'], ".m2/repository/org/projectlombok/lombok/1.18.16/lombok-1.18.16.jar") class Java(LspServer): def __init__ (self, arguments): self.path = arguments[0] if arguments else None if self.path is None or not os.path.exists(self.path): self.path = download_jdt_ls(os.path.join(get_data_home(), "java", "jdt.ls")) else: self.path = locate_product_directory(self.path) command = ["java"] if "--enable-lombok" in arguments: arguments.remove("--enable-lombok") command.append(f"-javaagent:{locate_lombok()}") data_directory = None if "--data" in arguments: data_directory = arguments.pop(arguments.index("--data") + 1) arguments.remove("--data") else: data_directory = os.path.join(get_data_home(), "java", "data") command = command + [ "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044", "-Declipse.application=org.eclipse.jdt.ls.core.id1", "-Dosgi.bundles.defaultStartLevel=4", "-Declipse.product=org.eclipse.jdt.ls.core.product", "-noverify", "-Xmx1G", "-jar", locate_launcher_jar(self.path), "-configuration", locate_launcher_configuration(self.path), "-data", data_directory, "--add-modules=ALL-SYSTEM", "--add-opens", "java.base/java.util=ALL-UNNAMED", "--add-opens", "java.base/java.lang=ALL-UNNAMED" ] + arguments[1:] super().__init__(command) @command("java.apply.workspaceEdit") def workspaceEdit (self, arguments): for argument in arguments: self.send_to_client({ "id": -1, "method": "workspace/applyEdit", "params": { "edit": { "changes": argument['changes'] } } })