返回

文章详情

Rust Glancer

Hacker News2026年8月21日 19:16

2026年8月21日,Rust Glancer 是一个功能性的 Rust LSP 服务器,它使用的内存比其他服务器少两个数量级,真的非常酷。快去看看吧!这篇文章起初是我在 lobste.rs 的评论,但我觉得以更显著的方式发布更好。不过不要指望写得多么精炼!一些想法:rust-analyzer 使用 rowan 来表示语法树。没错,rowan 非常糟糕 :P 我确实在考虑增量解析,增量的 DOM 变更风格重构,而 rowan 对此相当不错。但这只是1%的用例。99%的用例是你6666个依赖中的所有代码,这些代码你永远不会查看,但仍需要至少进行浅层分析。即使是以重构为主要目标的增量工具,其主要 AST 结构也应该只是一个数组列表。关于这一点可能会有一篇真正的文章,作为预告请见 https://youtu.be/G93oYL1ry70。Rust 工作区确实有很多信息需要索引:成千上万个函数、结构、特性、它们之间的关系、函数体及其语句等。每一个都需要被分析并记住,如果你想找到“这个结构的所有引用”,就不能撒谎。如果我理解正确,Rust Glancer 想要处理每个函数的函数体。我认为这一部分可以在开销很小的情况下变得懒惰(但不是增量的)?索引所有项目,但对于函数,只对当前打开的文件进行处理?这可能结合了两个领域的一些更好部分。与 Rust Rover 的内存使用量比较将会很有趣。尽管不包括 IDE GUI 本身,我预计 RR 会更紧凑。不过,有些功能可能不太可能得到支持,例如构建脚本 / 过程宏支持通过过程宏调用。我可能在合理化/错误记忆事情,但我记得正是在添加过程宏的时候,事情开始感觉异常庞大。展开过程宏的速度很慢,因为我们在运行真实代码,无法做正常 IDE 的技巧。而且过程宏会生成大量代码。有一次我测过,大约 30% 的 rust-analyzer 二进制大小与 JSON 解析代码有关。如果没有人看到代码,它就不会伤害任何人,对吧?这里有一种潜在的方法是采用 Sorbet 的技巧,即根本不运行元编程,而是提供一个插件接口来“解释”这将产生什么效果。我们不运行 serde,而是添加一个填充,注入 imp Serialize for T {},其主体为空。我不知道为什么,但在 rust-analyzer 中,我观察到当代理编辑代码时,内嵌提示会错位。Rust analyzer 的核心数据模型在始终观察代码的一致快照方面非常严格,并尽力确保语言客户端和服务器拥有共享的、严格可序列化的世界观。很遗憾的是,LSP 不允许对此进行正确的处理,只能是启发式的正确,这与旧的 Dart Analyzer 协议不同,后者具有可靠的数据同步。然而,我们的文件监视实现相当粗糙!首先,有两个后端:我们可以请求编辑器为我们进行监视,或者使用服务器端监视。尝试更改这个选项,看看是否有帮助?但我的回忆是我们的本地监视器 API 从根本上是竞争的,我并没有做 messy 的平台特定工作来使其正确。但我想要写的主要内容,以及我为什么从舒适的 lobste.rs 文本区域转到奢华的 Emacs 缓冲区,是现在的 rust-analyzer 有点像那半画的马的 meme,除了它只有马的头部。IntelliJ 的一个核心理念是它的 PSI API(本质上是带有已解析类型的 AST)确实是一个接口,并有多个提供者。在典型的使用中,至少有三个后端在运行:对于编辑器中已打开、用户主动修改的文件,PSI 是由具体的语法树支持的。对于项目中的其他文件,PSI 由所谓的 Stub Tree 支持,这是只存储文件“外部可见”部分的紧凑磁盘表示(不包括函数主体)。如果用户导航到新文件,其 PSI 会透明地从存根切换到语法树。对于依赖项,PSI 通常由 javac 生成的已编译 .class 文件支持。如果你导航到那里,IDE 会为你解压内容!太酷了!我认为这样的事情应该是这样工作的。rust-analyzer 不应针对所有你仍未查看的6666个依赖使用 salsa。它应该仅使用 rustc 的 .rmeta 文件,只有在用户开始更改他们的 ~/.cargo/registry/src 文件夹时,才透明地切换到 salsa。实现这一点的先决条件是定义访问 Rust 代码的抽象 API。这一直是计划,我们确实在某个时候开始了这个: https://hackmd.io/ytd82QNiT_Ku2XFr1EAtiQ rmeta-transparent – 源代码可能不可用。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡