【活动回顾】Lexical ——下一代语言服务器

Tubi 赞助与组织的第八期 Elixir Meetup 于五月底顺利结束,三位 Elixir 资深使用者 Horvo、Scott 和杨淼,与 660 多名线上线下的函数式编程爱好者分享了 Elixir 的相关应用与实践经验。本文回顾了 Scott 带来的分享“ Lexical ——下一代的语言服务器”,回顾笔记来自观众 Rylynn。

欢迎关注比图科技公众号,查看 Horvo 带来的分享《用 Elixir 开发 HLS 直播后端服务》

什么是 Language Server Protocol (LSP) ?

为编程语言添加自动补全、转到定义或悬停文档等功能需要大量的工作。传统上,每个编辑器为实现相同的特性提供了不同的 API,因此这些工作在每个编辑器中都必须重复。

语言服务器旨在提供特定于语言的智能,并通过支持进程间通信的协议与开发工具进行通信。语言服务器协议 (LSP) 背后的思想是标准化这些服务器和开发工具如何通信的协议。通过这种方式,单个语言服务器可以在多个开发工具中重用,这反过来又可以最小的工作量支持多种语言。

LSP 是语言提供者和工具供应商的双赢!

编辑器与 LS 的通信简化过程

设想一下,如果你需要跳转一个函数的定义到源文件,使用 LSP 协议会有多简单呢?

在你打开文件之后,你的光标选中引用函数之后,客户端 (VScode/nvim/Emacs) 会向语言服务器 (LS) 发送一个 method 为 textDocument/definition 的请求,参数为当前光标位置,即行与列,LS 接收到请求之后,则返回目标文件的 URI、Location 信息,之后客户端便可依据这些信息进行跳转了。

Lexical 的发展背景

虽然 Scott 没有直接比较 Lexical 与 旧有 Elixir-ls 的差异,但是通过“一个理想的语言服务器具有哪些特点”的分享,我们也可以对 Lexical 的优势有清晰的了解。

扫描二维码关注公众号,回复: 16076520 查看本文章

一个理想的语言服务器,其终极的目标是为开发者写代码和读代码提供愉悦的使用体验。要达成这个⽬标,Scott 认为 LS 需在以下几个方面有出色表现:

· 可靠,不轻易崩溃,若是崩溃,也能明确缘由

· 基础功能精确,⼀致且完整

· 体验极佳的反馈循环

· 易于贡献

当我们可以在一个语言服务器中实现前三点时,便能极大地保障开发者的心流体验不被打断。关于第四点,一个理想的语言服务器,应让使⽤该语⾔的开发者能轻易贡献或增强 LS 本身,这也是 Lexical 设计之初的⽬标。

Lexical 从四个方面考虑并突出其“易于贡献”这一特点。

⾸先,架构和设计都应该尽可能简单,这样才易于理解,降低参与的门槛;其⼆,需要易于测试,因为好的测试能给开发者充分的信⼼,继续做出贡献;其三,它应该让开发者尽可能关注业务逻辑,⽽非协议数据间的转换;其四,它需要具备强⼤的扩展能⼒,每个团队、每个⼈都可基于自身对编辑器的需求而进行扩展。

关于架构简单、易于测试、关注业务逻辑这三点如何实施,Scott 在后面的分享中做了详细介绍,请继续阅读本文。如果你对第四点“扩展能力”有感兴趣,请观看视频回放

Lexical 的解决方案

双节点解决请求与业务逻辑穿插问题

为了解决与项目之间的版本依赖问题,Lexical 引入了 Project Node VM。将请求与业务逻辑剥离,Server Node 与 Project Node 各司其职,不再相互耦合。这是 Lexical 的核心,可以有效地解决上一代 Elixir-ls 将所有项目库的依赖都在一个 Node 中运行而出现污染的情况。

其中:

Server Node 主要做与编译器的交互,同时它会启动⼀个 Project Node,启动的时候会注⼊少量 App 到你的项⽬中,以便让两个 Node 通信更加⽅便。Peoject Node 是编译工具,可对原数据进行提取,与客户端实现交互。

清晰的模块划分使得整体 Lexical 更易维护

在双节点系统设计的基础上,Scott 深入分享了 Lexical 在容器层级和组件层级的架构与实现。

整体的 Server Node 分别由五个 App 组成,分别用于解决数据一致性、通信和业务模块集成等问题。其中,特别需要关注的是 Server App 和 Remote Control App,这里往往包含真正的业务逻辑。

通过这样的设计,我们可以清楚地看到 Lexical 极大地降低了 LS 的复杂度,继而可以确保一致性与准确性,甚至让以前在 Code Review 的很多工作,比如没使用某个公共函数、代码复杂度过高、alias 没展开等,都有可能集成到 LS 中,极大地缩短了反馈时间。

如何实现 LS 功能?

Scott 以 Server App 的⼀些组件为例,从同步和异步的⻆度帮助大家理解 LS 的功能。

⽐如 Navigation 的相关功能是同步的,我们会在 Server Genserver 接收请求后直接转发给 Provider,⽽通知类的功能则是异步的,我们会在 Server App 的 Project ⽂件夹下有一系列 Genserver,用于接收 Project Node 发出的消息,并把它们转化成编辑器需要的 Response。

Lexical 的后续发展

在认识了 Lexical 的发展背景和架构设计之后,Scott 又带大家详细地了解了 Lexical 的后续计划:

· Pluggability:这是⽬前的⼯作重⼼,但还处于架构阶段

· Navigation:这是排在 Plugin 之后的第一重点,但它的复杂度很⾼

· Diagnostics, Completions 等现有功能的提升

目前,Lexical 整体上仅有 Steve Cohen 等几位核心开发者在维护着,为提供更丰富的功能,还有一段路要走。

Scott 在现场手把手地演示了 Elixir 用户可以如何创造属于自己的 LS 功能,鼓励更多人参与贡献 Lexical,共同为社区创造一些价值。如果你感兴趣,也欢迎参与到Lexical 项目中!

Elixir 在 Tubi 的其他应用案例

使用 Elixir/OTP 构建多媒体 E2E 处理平台

Ruby 思想在 Elixir 项目中的应用

一个潜藏在 Elixir 代码库里 7 年的性能问题

加入 Tubi 一起成长变强!

热招岗位:https://tubi.tech/careers/

微信公众号:【活动回顾】Lexical ——下一代语言服务器

猜你喜欢

转载自blog.csdn.net/weixin_49193714/article/details/131576143