likes
comments
collection
share

Language Server 基础:从记事本到 IDE提到语言服务器(Language Server),大部分人其实都

作者站长头像
站长
· 阅读数 169

不知道身为程序员的你,平日用什么代码编辑器或 IDE?

不知道你是否关注到一个细节,一位使用 VSCode 的 Python 开发者,初次配置 VSCode 时会很自然地安装一个插件(Extension),即 Pylance;

一位使用 Neovim 的 Web 开发者,初次使用 nvim 命令的下一个动作,多半是通过插件(Plugin)安装 TypeScript 语言对应的 tsserver(typescript-language-server)……

这些动作的背后,本质均是为自己所熟悉的语言配置合适的语言服务器

什么是语言服务器?

提到语言服务器(Language Server),大部分人其实都没有明晰的概念。然而对于习惯使用现代代码编辑器(比如 VSCode,Sublime Text 等)的人来说,其可以说是无处不在。我们平日在 IDE 中所习以为常的一些功能,比如:

  • 定义跳转(Go To Definition)
  • 句法诊断(Syntax Diagnostics)
  • 代码高亮(Highlighting)

诸如上述这些功能,底层都是语言服务器在发挥作用。此处,我们不去纠结代码编辑器与 IDE 的本质区别,只把目光放在代码编辑体验上。是的,语言服务器发展起来的初衷,就是为了不断改善程序员的代码编辑体验。

相信早年学习编程的前辈,多半都曾有记事本中写代码的经历。就我个人而言,仍然记得初次学习 PHP 时,盯着满屏绿色的字母,配置 Apache 的样子。乃至于多年后,修改 ZSH 配置文件时,面对清晰的高亮,一脸惊喜与不可置信,不可避免地在心底对过去的自己说一声:时代变了。

语言服务器能做什么?

即便早已习惯这一切,好学的我们,仍然会在某个不知名的下午,心底泛起一个问题,Language Server 是如何实现的呢?我们会在接下来的章节,一步步揭开这个问题的答案。在此之前,我们或许可以暂时抛开模糊的体感,站在更高的层面来看看,Language Server 究竟能做什么?

对于这个问题,Microsoft 或者说 VSCode 开发团队做了一个很好的总结与定义,其将语言服务器所提供的功能大体分为两类:

  • 声明式语言功能 / Declarative Language Features
  • 命令式语言功能 / Programmatic Language Features

其中,声明式语言功能包括句法高亮、代码补全、括号匹配、注释识别、自动缩进、折叠识别等;命令式语言功能包括代码信息展示、自动补全、定义跳转、引用跳转、错误检查、格式调整等。

前者之所以叫「声明式」语言功能,是因为可以通过在插件中编写相应的配置文件,VSCode 即可根据配置实现对应的功能;至于后者,顾名思义,不得不借助 Language Server 方能实现。

在此,我们将广义的语言服务器,定义为一个系统,其系统内的各个组件,共同支持一门特定编程语言在代码编辑器中所需的编程体验的方方面面,包括声明式语言功能和命令式语言功能的一切。狭义的语言服务器,则是一个实现命令式语言功能的服务。在后续的章节中,我们将着眼于广义的语言服务器,深入理解其中的每一个组件。

LSP(Language Server Protocol)

了解到这里,你可能又产生了一个新的疑问,市面上的代码编辑器或者 IDE 层出不穷,难道一门编程语言需要就不同的代码编辑器开发不同的语言服务器么?这思路显然太野了,程序员手上追求的是精细活,干不出这么糙的事。

同样由 Microsoft 提出的一个概念,LSP(Language Server Protocol)便是解决这个问题的答案。其本身只是一种协议和规范,用于对语言服务器的标准化实现。随着 LSP 的流行,市面上主流的代码编辑器,逐渐以之作为对广义的语言服务器的代称。因此,探秘 LSP,本质上是探秘整个 Language Server,逐一探索其内部各个组件的实现细节。

开发 Language Server

Language Server 基础:从记事本到 IDE提到语言服务器(Language Server),大部分人其实都

说了这么多,假如我们开发了一门新的编程语言,随之而来的便是,开发对应的 Language Server 以帮助开发者获得更好的开发体验。此处,我们以当前市面上主流的代码编辑器 VSCode 为载体,可以从架构、配置、解析和协议四个视角展开,由浅及深,步步深入,逐步实现一个语言服务器。当然,篇幅所限,我们不会马上从实现层面入手,而是先从宏观层面初步把握 Language Server 各个视角下的要点。

其中,就架构视角,我们需要了解 LSP 和 JSON-RPC 两个要点,二者构成了 Langauge Server 的基石。所有的实现工作,都是基于上述架构。

接下来,我们将会以 VSCode 为载体,介绍如何基于 TextMate 语法,通过编写配置文件实现声明式语言功能。此处,我们尚未真正涉及语言服务器,却是广义的语言服务器系统内不可或缺的部分。到了这一步,一门编程语言在代码编辑器中的编辑体验已然有模有样。

更进一步,我们需要深入了解和学习抽象句法树(Abstract Syntax Tree, AST)的概念及其解析方式。我们将会介绍业界主流的两个框架,即 ANTLR 和 Tree Sitter。二者将 AST 解析的复杂度,从十万大山变成如履平地,真正做到「有手就行」。

最后,在 AST 解析的基础上,我们将真正学习如何一步一步实现命令式语言功能,将代码编辑体验提升到极致。从这里开始,我们将不再是记事本里写代码,而是在 IDE 中编程。

好了,有关 Language Server 的基本介绍到此为止。接下来,保持耐心和好奇心,我们一起,一点一点揭开 LSP 的神秘面纱,从记事本开始,逐渐步入到 IDE 的瑰丽世界,当然,仅限代码编辑体验哦!

转载自:https://juejin.cn/post/7425527459685154827
评论
请登录