解决Zed编辑器Java/Kotlin混编Android项目无法跳转定义的问题
问题现象
在 Zed 编辑器中打开 Java + Kotlin 混编的 Android 项目,打开 .kt 或 .java 文件后,cmd-click 或 cmd-] 无法跳转到方法定义的位置,底部状态栏也看不到对应的 LSP 服务。
原因排查
1. 确认 LSP 进程
# 查看正在运行的 LSP 进程
ps aux | grep -iE "jdt|lsp|kotlin" | grep -v grep正常情况应看到两个进程:
jdtls— Eclipse JDT LS(Java LSP)kotlin-language-server— Kotlin LSP
2. 检查 Zed 日志
# 查看最近的 LSP 日志
grep -iE "kotlin|lsp" ~/Library/Logs/Zed/Zed.log | tail -20常见的错误信息:
ERROR [project::lsp_store] Failed to start language server "kotlin-lsp":
from extension "Kotlin" version 0.3.0:
error sending request for url (...RELEASES.md)
Caused by: Operation timed out (os error 60)3. 根因分析
Zed 的 Kotlin 扩展(v0.3.0)内置了两种语言服务器:
| LSP 名称 | 类型 | 说明 |
|---|---|---|
kotlin-lsp |
JetBrains IntelliJ Server | 需 JDK 25+,认证已过期,无法使用 |
kotlin-language-server |
fwcd/kotlin-language-server | 轻量,JDK 11 即可,独立运行 |
扩展的 WASM 代码启动时会先尝试 kotlin-lsp(IntelliJ 版),通过网络请求 GitHub 的 RELEASES.md 检查最新版本。即使网络正常,JetBrains IntelliJ Server 的认证也已过期,导致其无法正常启动和使用。这是不使用 JetBrains IntelliJ Server 的主因——它已不再是一个可行的选项。
此外,如果网络不通(比如国内无法访问 GitHub raw),扩展会直接崩溃,连本地已下载好的服务器文件也不看,导致 Kotlin 文件完全没有 LSP。
Java LSP(Eclipse JDT LS)是独立扩展,通常不受影响。
解决方案
方案一(推荐):手动安装 fwcd/kotlin-language-server
绕过内置扩展的 IntelliJ 服务器,使用独立的 fwcd/kotlin-language-server。
下载
从 GitHub Releases 下载最新版 server.zip:
# 如果无法直接访问 GitHub,使用 ghproxy 镜像
curl -sL -o server.zip \
"https://ghproxy.net/https://github.com/fwcd/kotlin-language-server/releases/download/1.3.13/server.zip"
# 你也可以直接使用浏览器访问这个地址进行下载解压
mkdir -p ~/.local/share/kotlin-language-server
unzip server.zip -d ~/.local/share/kotlin-language-server/
chmod +x ~/.local/share/kotlin-language-server/bin/kotlin-language-server验证
# 发送 LSP initialize 请求测试
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":null,"capabilities":{},"rootUri":null}}' \
| timeout 3 ~/.local/share/kotlin-language-server/bin/kotlin-language-server 2>&1 | head -5配置 Zed
在项目根目录创建 .zed/settings.json:
{
"lsp": {
"java": {
"settings": {
"java.configuration.runtimes": [
{
"name": "JavaSE-1.8",
"path": "/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home",
"default": true
}
],
"java.import.gradle.enabled": true,
"java.import.gradle.wrapper.enabled": true,
"java.import.gradle.version": "6.5",
"java.import.gradle.home": "",
"java.import.gradle.user.home": "${workspaceFolder}/.gradle-home",
"java.import.gradle.offline.enabled": false
}
},
"kotlin-language-server": {
"binary": {
"path": "~/.local/share/kotlin-language-server/bin/kotlin-language-server"
},
"settings": {
"kotlin.compiler.jvmTarget": "1.8",
"kotlin.trace.server": "off",
"kotlin.excludes": "**/build/**, **/.gradle/**"
}
}
},
"languages": {
"Kotlin": {
"language_servers": ["kotlin-language-server"]
}
},
"file_scan_exclusions": [
".gradle/**",
"build/**",
"*/build/**",
"**/build/**",
".git/**",
".idea/**",
"**/*.jar",
"**/*.aar",
"**/*.class"
]
}关键点:
binary.path— 指向手动安装的kotlin-language-server可执行文件languages.Kotlin.language_servers— 强制 Kotlin 文件使用这个自定义 LSP,不再尝试内置的 IntelliJ 服务器- JDK 路径要根据本地环境调整
重启 Zed
cmd-q 完全退出后重新打开,底部状态栏应能看到 Java 和 Kotlin 两个 LSP 图标。
方案二:临时使用代理让内置扩展初始化(不推荐)
⚠️ 注意:JetBrains IntelliJ Server 认证已过期,此方案已失效。 仅当该问题未来被修复时才可能有用。
如果只是首次需要网络,临时设置代理后重启 Zed:
HTTPS_PROXY=https://ghproxy.net/ open -a Zed扩展拿到 RELEASES.md 发现本地版本已是最新后,后续启动不再需要网络。
方案三:给混合模块的 build.gradle 加 sourceSets(辅助 JDT LS)
对于同时包含 Java 和 Kotlin 源码的模块,在 android {} 块内添加:
android {
sourceSets {
main {
java.srcDirs += 'src/main/kotlin'
}
}
}帮助 Eclipse JDT LS 的 Gradle 导入器识别 Kotlin 源目录。
注意事项
检查 Kotlin LSP 进程
ps aux | grep kotlin-language-server | grep -v grep | grep -v CompileDaemon首次启动时,Kotlin LSP 会消耗大量 CPU(100%+)进行项目索引,属于正常现象,等待 1-2 分钟即可。
需要加 sourceSets 的混合模块
如果模块同时有 .java 和 .kt 文件,建议加上 sourceSets 配置:
| 模块 | Java | Kotlin | 需要 |
|---|---|---|---|
v4-core |
✅ | ✅ | ✅ |
core(旧版) |
✅ | ✅ | ✅ |
app |
✅ | ✅ | ✅ |
v4-tx-player |
✅ | ✅ | ✅ |
v4-youku-player |
✅ | ✅ | ✅ |
纯 Java 或纯 Kotlin 的模块不需要。
关于跨语言跳转
fwcd/kotlin-language-server 能解析 Java 类路径,因此从 Kotlin 文件跳转到 Java 类的定义是可以工作的。JDT LS 也能通过 Gradle 模型解析跨模块依赖。两者结合可实现完整的跨语言导航。