Skip to content

Commit

Permalink
第二章初稿
Browse files Browse the repository at this point in the history
  • Loading branch information
imbant committed Jan 14, 2025
1 parent d62fe09 commit e696a68
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 28 deletions.
43 changes: 43 additions & 0 deletions source/_drafts/lsp3草稿.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
如果想入门 LSP,查官方文档是必不可少的:microsoft.github.io

但是语言服务非常重交互,只靠文字描述是很单薄的,初学者只看干巴巴的接口定义肯定会头晕,不知道这些接口都能干什么。不过也不怪 LSP 官方,毕竟只负责设计协议,具体的实现还得靠客户端(各大代码编辑器)。

这时候就推荐 VS Code 的这篇文档了,列出了插件 API 和 LSP 的对应关系,毕竟和 LSP 一样都是微软家的,很多概念和术语都相通:code.visualstudio.com

文档里详细列出了 VS Code 支持的语言特性,并且都配上了动图和聊胜于无的文字说明。要说为什么是聊胜于无,还是因为交互太重了,各个功能需要多写 demo 去体验,意会。

从学习和方便调试的角度,可以尝试先用 VS Code API 实现一些功能,翻翻 API 的文档,然后再换成 LSP 实现,两者的文档交叉比对,能更好的体会“设计”和“实现”的差异,更好的理解 LSP。

---

在 VS Code 中的语言服务插件,指的是能给一种语言提供高亮、补全、诊断,悬浮提示,查看定义等等功能的插件。

实现这些功能有两种方式。
一种是在插件进程内,调用 vscode 这个 npm 包的 API。插件是一个 node 进程,也是 Electron 进程(具体是主进程,还是渲染进程,还不确定)的子进程。
另一种是再新开一个进程,作为语言服务器,和插件(客户端)通过 LSP(Language Server Protocol) 通信。

是的,这些功能都是插件作者一行一行的代码写出来的。在开发插件之前,我完全没有料到在编辑器里 console 后输一个点,要经历这么复杂的代码后,才会弹出 log,warn 和 error。

两种方案有什么区别?
vscode API。文档全面,教程详细。可以快速实现小功能。适合快速实现轻量化语言服务,例如 json,markdown 甚至 css 这种非编程语言。或者快速验证想法。
缺点是只能使用 js(ts) 实现,而且业务功能和插件底层在一个进程会导致性能问题,不适合计算密集型的功能。提供语言服务和编译器的区别之一就是需要处理用户输入,要求写完代码后能快速更新语法树,然后基于语法树提供语言服务。例如给一个 1000 行的 js 代码生成 AST,然后提供语义高亮。这时候插件更新慢了,插件和 vs code 的通信就会慢,提供语言服务的速度也会慢。

语言服务器。实现语言没有限制。与 vs code 解耦,只要是实现了 LSP 的客户端都可以通信,服务更多的编辑器。并且可以起多个进程(多个实例),一起给客户端服务,解放客户端进程的算力,客户端只需要转发其他进程算出来的数据给 vs code 即可。
缺点是 LSP 有一定上手门槛,需要额外处理进程通信,架构复杂后,调试和开发都没那么轻便了。如果你还是用 node,微软官方提供了 vscode-languageserver 这个 npm 包,但是我都用它写完语义高亮、悬浮提示这些功能了,还是不知道这个包应该怎么用。比起 vs code API,它的文档太少了,示例代码也很少,相关讨论也很少,最要命的是 ChatGPT 也不太懂这个包怎么用,看来是能训练的资料确实太少了…

文档缺失倒逼我去翻 GitHub,推荐一下 Volar.js 的源码,用 node 实现,实现的功能都很丰富,我就是抄它的配置,才做出语义高亮的…

---

插件进程主要的功能应该是和 VS Code 主体通信。就像 Electron 主进程一样,应该避免执行很重的任务。VS Code 通知插件,现在需要一个自动补全的列表,虽然插件可以返回一个 promise 异步处理,但如果等太久,VS Code 就不要这个结果了(不提供补全)。这也是 VS Code 的用户交互指南之一,插件不能影响 UI 响应速度

---

插件本体、语言服务器、代码编辑器这三者分别是什么关系?
插件本体就是个转发层,代码编辑器是真正发请求的,语言服务器是真正处理请求的。
他们在三个进程,分别是 VS Code 的 extension host 进程、VS Code 的渲染进程、语言服务器进程。后两者通过 LSP 通信,前两者通过 Electron IPC 通信(TODO: 存疑)。

---

拿自动补全举例,在 console 后输入一个点,这时候语法结构是不完整的,有错的,怎么根据不完整的语法结构和当前光标的位置,推断出当前上下文适用哪些补全,是很难的。
现在理解尤雨溪为什么资助 Volar 作者全职开发这个插件了,它就是 DX 的基础之一,没有这种插件,开发者写 .vue 文件就和白纸写代码一样,是完全写不了的
8 changes: 4 additions & 4 deletions source/_posts/LSP1.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: LSP 与 VS Code 插件开发 第一章
title: LSP 与 VS Code 插件开发(一)语言服务器架构
date: 2024-8-24
tags: [LSP, VS Code, 语言服务器]
---
Expand Down Expand Up @@ -84,9 +84,9 @@ Vue 插件做了哪些事情,才让你的编程体验变得如此美好呢?
- 查看启动性能:VS Code 指令 `Show Running Extensions` 可以列出插件的启动时间,也有 Profile 能力,用来查看运行缓慢的插件。
- 二分法检查问题:当 VS Code 用起来总是有问题,还有个[二分查找法](https://code.visualstudio.com/blogs/2021/02/16/extension-bisect)功能,用来关闭一半的插件,看看问题是否解决。持续二分,直到找到问题插件。

#### 相关文档
<!-- #### 相关文档
这里就不堆砌官方的文档教程了。我只是想告诉你 Why and How。如果想尝试写一个使用 VS Code API 的插件,可以从[这个教程](https://code.visualstudio.com/api/get-started/your-first-extension)看起。相信等你看完全部教程,已经能成为插件高手,可以尝试动手解决一些日常开发中碰到的痛点了。
这里就不堆砌官方的文档教程了。我只是想告诉你 Why and How。如果想尝试写一个使用 VS Code API 的插件,可以从[这个教程](https://code.visualstudio.com/api/get-started/your-first-extension)看起。相信等你看完全部教程,已经能成为插件高手,可以尝试动手解决一些日常开发中碰到的痛点了。 -->

## 语言服务器 —— 服务任何代码编辑器

Expand Down Expand Up @@ -133,4 +133,4 @@ Vue 插件做了哪些事情,才让你的编程体验变得如此美好呢?

我在播客 [`Web Worker`](https://www.xiaoyuzhoufm.com/episode/66a1197533ddcbb53cd7a063) 上和几位 Vue 生态的大佬、团队成员们聊过 Vue 插件,欢迎收听。

我也会在[即刻](https://okjk.co/OUqto1)分享语言服务器相关的开发心得,计划将它们整理成系列文章,欢迎关注。
我也会在[即刻](https://okjk.co/OUqto1)分享语言服务器相关的开发心得,计划将它们整理成系列文章,欢迎关注。
Loading

0 comments on commit e696a68

Please sign in to comment.