惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
Y
Y Combinator Blog
T
Tailwind CSS Blog
D
Docker
博客园 - Franky
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
腾讯CDC
Vercel News
Vercel News
Engineering at Meta
Engineering at Meta
U
Unit 42
The Cloudflare Blog
S
SegmentFault 最新的问题
WordPress大学
WordPress大学
爱范儿
爱范儿
Recent Announcements
Recent Announcements
博客园 - 聂微东
博客园 - 叶小钗
H
Help Net Security
MyScale Blog
MyScale Blog

See you soon

哟,好久不见,无线打印 | See you soon 试试将文章版本化管理吧 | See you soon 使用 Quadlet 将 Podman 中的 Postgres 当作 systemd 服务运行 | See you soon 大他者,那个无时无刻都在盯着你的东西 | See you soon Laws of Software Engineering,软件工程定律 | See you soon 浅记多因素身份认证 | See you soon Linux 内核中的度量单位 | See you soon 重置 GPG 智能密钥 | See you soon 向 NAS 引入 samba | See you soon 无法重复键入的 Fcitx5 | See you soon ZFS 降级事故 | See you soon 记被 XanMod Kernel 和 AppArmor 联合坑的一次踩坑 | See you soon agent 的 skill 与 toolcall | See you soon 记一次服务器被挂恶意挖矿二进制 | See you soon 活着的 Arc | See you soon 令 acme.sh 使用 Cloudflare 的 DNS API 签发与续签证书 | See you soon 于 Tokio 中卸载 CPU Bound 任务 | See you soon 如我所见,梦破碎的时候 | See you soon 74LS 家族手册 | See you soon JDK Projects 备忘录 | See you soon 关于历史 | See you soon 用 curl 下载 OnePlus 的 ROM | See you soon 实用命令切片 | See you soon 再见,Oh My Zsh。 | See you soon 你不应该复用 strings.Builder | See you soon 博客的明日 | See you soon 被 AppArmor 击杀的 Dockge | See you soon AI 时代的自我 | See you soon 支持删除的布隆过滤器 | See you soon 基于栈的虚拟机与基于寄存器的虚拟机 | See you soon
让 JDTLS 能正确识别 Scala3 源码 | See you soon
Krysztal Huang · 2026-09-19 · via See you soon

CasualtiesBelow 是我突发奇想用 Scala 3 写的 Fabric mod(其实是我太想在 Minecraft 里玩 Casualties: Unknown 了),考虑到面向 Java 的生态兼容性于是在 src/test/java/ 里放了一个 Java 写的 API 互操作测试,引用了 Scala 侧的类型。

这个时候困扰了我有两三年的问题在不经意间把我直接创死了:默认的 Gradle 配置下 JDTLS 找不到 Scala 的符号,但实际上又能编译出正常的东西。

为什么编译没事?

./gradlew build 的时候 Scala 插件和 Java 做联合编译,这个时候源码互相可见,那肯定是没有问题的。我使用的是 JDTLS,那么我觉得肯定是 JDTLS 的什么配置出了问题。

注意到 JDTLS 会默认生成多个文件,根据 JDTLS 的文档我们可以得到这两个文件的作用:

  • .project 是 workspace 层的(由 Eclipse Platform 的 Resources 插件定义),声明”这里有一个叫什么名字的工程、装了哪些 nature、跑哪些 builder”
  • .classpath 是 JDT 层的(由 org.eclipse.jdt.core 定义),声明”这个 Java工程的构建路径是什么”

NOTE

既然是继承自 Eclipse 的遗产,那就不奇怪了

修法

好了,现在有了几个基本的信息:

  • 我们用的是 JDTLS,这是源自 Eclipse Foundation 的作品
  • Gradle 能执行源码合并等
    • 参照 Kotlin 编写的 Java mod,这是个很常见的需求

那么问题大致就在于如何让 JDTLS 认得出来需要去找 Scala 的编译结果。

Eclipse 插件

在 AI 大人的帮助下我找到了这篇 Gradle Eclipse 插件的文档:The Eclipse Plugins

不过仔细探索之下发现这篇文章里的 Scala 一节意思是激活 Eclipse IDE 里的 Scala 插件,和我们一点关系都没有…好吧,那很遗憾了。

在仔细阅读后发现了大概是我想要的东西:如果 JDTLS 需要依赖 .classpath 文件的信息,那么或许找对应的配置就能把我们的 Scala 生成的 .class 塞进去

果不其然还真有这种东西:eclipse.classpath, Allows configuring classpath information.

合并 classpath

在互联网上搜索的时候发现了两条很有用的论坛帖子,并且均来自 Gradle 自己的论坛,我觉得可行性非常高于是打算试试。

这个时候我得到了两条非常重要的 Gradle 切片

eclipse {

classpath {

defaultOutputDir = file('war/WEB-INF/classes')

file {

whenMerged {

def gwtClasspath = entries.find { it.path == 'com.gwtplugins.gwt.eclipse.core.GWT_CONTAINER' }

entries.remove gwtClasspath

entries += gwtClasspath

}

}

}

}

eclipse {

classpath {

file {

whenMerged {

entries += new Library(fileReference(file('/conductor- grpc/build/classes/java/main')))

}

}

}

}

他们都有个非常重要的行为:使用了 whenMerge而这个配置块的意思恰好是当合并的时候添加什么内容

最后的修改

不过这两条写法是 Groovy 写法,显而易见的我能看懂但我 写 不 懂

那么我们现在的逻辑有了:把 Scala 的编译结果塞到 classpath 里就行了。有请 Kimi 大人来帮我写剩下的吧

eclipse {

classpath {

val factory = fileReferenceFactory

// whenMerged 签名是无类型的 Action<?>:预声明成 Action<Classpath> 才能拿到类型化的接收者

val addScalaClasses = Action<Classpath> {

entries.add(

Library(factory.fromPath("build/classes/scala/main")).apply {

sourcePath = factory.fromPath("src/main/scala")

},

)

}

file {

whenMerged(addScalaClasses)

}

}

}

完毕,我和 Kimi 大人简直是太厉害了。

最后的小坑

小坑还是有的,每次修改完毕 Scala 后都需要手动触发一次编译他才会把编译结果放到 build/classes/scala/main 里,这样才能被 JDTLS 识别到。