Skip to content

Commit 88345e1

Browse files
feat: add JDK runtime dependency
1 parent 6a2cddb commit 88345e1

File tree

2 files changed

+117
-24
lines changed

2 files changed

+117
-24
lines changed

src/multilspy/language_servers/kotlin_language_server/kotlin_language_server.py

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
import asyncio
6+
import dataclasses
67
import json
78
import logging
89
import os
@@ -20,6 +21,16 @@
2021
from multilspy.multilspy_utils import PlatformUtils
2122

2223

24+
@dataclasses.dataclass
25+
class KotlinRuntimeDependencyPaths:
26+
"""
27+
Stores the paths to the runtime dependencies of Kotlin Language Server
28+
"""
29+
java_path: str
30+
java_home_path: str
31+
kotlin_executable_path: str
32+
33+
2334
class KotlinLanguageServer(LanguageServer):
2435
"""
2536
Provides Kotlin specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Kotlin.
@@ -29,16 +40,24 @@ def __init__(self, config: MultilspyConfig, logger: MultilspyLogger, repository_
2940
"""
3041
Creates a Kotlin Language Server instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead.
3142
"""
32-
kotlin_executable_path = self.setup_runtime_dependencies(logger, config)
43+
runtime_dependency_paths = self.setup_runtime_dependencies(logger, config)
44+
self.runtime_dependency_paths = runtime_dependency_paths
45+
46+
# Create command to execute the Kotlin Language Server script
47+
cmd = f'"{self.runtime_dependency_paths.kotlin_executable_path}"'
48+
49+
# Set environment variables including JAVA_HOME
50+
proc_env = {"JAVA_HOME": self.runtime_dependency_paths.java_home_path}
51+
3352
super().__init__(
3453
config,
3554
logger,
3655
repository_root_path,
37-
ProcessLaunchInfo(cmd=kotlin_executable_path, cwd=repository_root_path),
56+
ProcessLaunchInfo(cmd=cmd, env=proc_env, cwd=repository_root_path),
3857
"kotlin",
3958
)
4059

41-
def setup_runtime_dependencies(self, logger: MultilspyLogger, config: MultilspyConfig) -> str:
60+
def setup_runtime_dependencies(self, logger: MultilspyLogger, config: MultilspyConfig) -> KotlinRuntimeDependencyPaths:
4261
"""
4362
Setup runtime dependencies for Kotlin Language Server.
4463
"""
@@ -47,39 +66,69 @@ def setup_runtime_dependencies(self, logger: MultilspyLogger, config: MultilspyC
4766
# Verify platform support
4867
assert platform_id.value.startswith("win-") or platform_id.value.startswith("linux-") or platform_id.value.startswith("osx-"), "Only Windows, Linux and macOS platforms are supported for Kotlin in multilspy at the moment"
4968

50-
# Determine the binary name based on platform
51-
binary_name = "kotlin-language-server.bat" if platform_id.value.startswith("win-") else "kotlin-language-server"
52-
5369
# Load dependency information
5470
with open(os.path.join(os.path.dirname(__file__), "runtime_dependencies.json"), "r") as f:
5571
d = json.load(f)
5672
del d["_description"]
5773

58-
dependency = d["runtimeDependency"]
59-
60-
# Setup paths and download if necessary
61-
kotlin_ls_dir = os.path.join(os.path.dirname(__file__), "static")
62-
kotlin_bin_path = os.path.join(kotlin_ls_dir, "server", "bin")
63-
kotlin_executable_path = os.path.join(kotlin_bin_path, binary_name)
74+
kotlin_dependency = d["runtimeDependency"]
75+
jdk_dependency = d["jdk"][platform_id.value]
6476

65-
if not os.path.exists(kotlin_ls_dir):
66-
os.makedirs(kotlin_ls_dir)
77+
# Setup paths for dependencies
78+
static_dir = os.path.join(os.path.dirname(__file__), "static")
79+
os.makedirs(static_dir, exist_ok=True)
80+
81+
# Setup JDK paths
82+
jdk_dir = os.path.join(static_dir, "jdk")
83+
os.makedirs(jdk_dir, exist_ok=True)
84+
85+
java_home_path = os.path.join(jdk_dir, jdk_dependency["java_home_path"])
86+
java_path = os.path.join(jdk_dir, jdk_dependency["java_path"])
87+
88+
# Download and extract JDK if not exists
89+
if not os.path.exists(java_path):
90+
logger.log(f"Downloading JDK for {platform_id.value}...", logging.INFO)
6791
FileUtils.download_and_extract_archive(
68-
logger, dependency["url"], kotlin_ls_dir, dependency["archiveType"]
92+
logger, jdk_dependency["url"], jdk_dir, jdk_dependency["archiveType"]
6993
)
70-
71-
assert os.path.exists(kotlin_executable_path)
94+
# Make Java executable
95+
if not platform_id.value.startswith("win-"):
96+
os.chmod(java_path, 0o755)
97+
98+
assert os.path.exists(java_path), f"Java executable not found at {java_path}"
7299

73-
# Set proper executable permissions (read+execute for everyone)
74-
os.chmod(kotlin_executable_path, 0o755)
100+
# Setup Kotlin Language Server paths
101+
kotlin_ls_dir = os.path.join(static_dir, "server")
75102

76-
# Create command that will properly execute the script
103+
# Get platform-specific executable script path
77104
if platform_id.value.startswith("win-"):
78-
cmd = f'"{kotlin_executable_path}"'
105+
kotlin_script = os.path.join(kotlin_ls_dir, "bin", "kotlin-language-server.bat")
79106
else:
80-
cmd = f'/bin/sh "{kotlin_executable_path}"'
81-
82-
return cmd
107+
kotlin_script = os.path.join(kotlin_ls_dir, "bin", "kotlin-language-server")
108+
109+
# Download and extract Kotlin Language Server if script doesn't exist
110+
if not os.path.exists(kotlin_script):
111+
logger.log("Downloading Kotlin Language Server...", logging.INFO)
112+
FileUtils.download_and_extract_archive(
113+
logger, kotlin_dependency["url"], static_dir, kotlin_dependency["archiveType"]
114+
)
115+
116+
# Make script executable on Unix platforms
117+
if os.path.exists(kotlin_script) and not platform_id.value.startswith("win-"):
118+
os.chmod(kotlin_script, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
119+
120+
# Use script file
121+
if os.path.exists(kotlin_script):
122+
kotlin_executable_path = kotlin_script
123+
logger.log(f"Using Kotlin Language Server script at {kotlin_script}", logging.INFO)
124+
else:
125+
raise FileNotFoundError(f"Kotlin Language Server script not found at {kotlin_script}")
126+
127+
return KotlinRuntimeDependencyPaths(
128+
java_path=java_path,
129+
java_home_path=java_home_path,
130+
kotlin_executable_path=kotlin_executable_path
131+
)
83132

84133
def _get_initialize_params(self, repository_absolute_path: str) -> InitializeParams:
85134
"""

src/multilspy/language_servers/kotlin_language_server/runtime_dependencies.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,49 @@
55
"description": "Kotlin Language Server",
66
"url": "https://github.com/fwcd/kotlin-language-server/releases/download/1.3.13/server.zip",
77
"archiveType": "zip"
8+
},
9+
"jdk": {
10+
"win-x64": {
11+
"url": "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_x64_windows_hotspot_21.0.6_7.zip",
12+
"archiveType": "zip",
13+
"jdk_path": "jdk-21.0.6+7",
14+
"java_home_path": "jdk-21.0.6+7",
15+
"java_path": "jdk-21.0.6+7/bin/java.exe"
16+
},
17+
"win-arm64": {
18+
"url": "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_aarch64_windows_hotspot_21.0.6_7.zip",
19+
"archiveType": "zip",
20+
"jdk_path": "jdk-21.0.6+7",
21+
"java_home_path": "jdk-21.0.6+7",
22+
"java_path": "jdk-21.0.6+7/bin/java.exe"
23+
},
24+
"linux-x64": {
25+
"url": "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_x64_linux_hotspot_21.0.6_7.tar.gz",
26+
"archiveType": "gztar",
27+
"jdk_path": "jdk-21.0.6+7",
28+
"java_home_path": "jdk-21.0.6+7",
29+
"java_path": "jdk-21.0.6+7/bin/java"
30+
},
31+
"linux-arm64": {
32+
"url": "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.6_7.tar.gz",
33+
"archiveType": "gztar",
34+
"jdk_path": "jdk-21.0.6+7",
35+
"java_home_path": "jdk-21.0.6+7",
36+
"java_path": "jdk-21.0.6+7/bin/java"
37+
},
38+
"osx-x64": {
39+
"url": "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_x64_mac_hotspot_21.0.6_7.tar.gz",
40+
"archiveType": "gztar",
41+
"jdk_path": "jdk-21.0.6+7/Contents/Home",
42+
"java_home_path": "jdk-21.0.6+7/Contents/Home",
43+
"java_path": "jdk-21.0.6+7/Contents/Home/bin/java"
44+
},
45+
"osx-arm64": {
46+
"url": "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_aarch64_mac_hotspot_21.0.6_7.tar.gz",
47+
"archiveType": "gztar",
48+
"jdk_path": "jdk-21.0.6+7/Contents/Home",
49+
"java_home_path": "jdk-21.0.6+7/Contents/Home",
50+
"java_path": "jdk-21.0.6+7/Contents/Home/bin/java"
51+
}
852
}
953
}

0 commit comments

Comments
 (0)