VSCode原理 - 鼠标hover显示定义和Ctrl点击跳转原理


前言

大家好这里是阳九.

回归掘金, 写一点平时大家都的VSCode相关知识,

毕竟是每天大家都在用但是没有研究过的小原理, 篇幅较短, 删去全部废话,只贴原理和代码

模拟VSCode架构个人代码编辑器实现

lzy-code-editor: 模仿VSCode原理与架构实现的简易版桌面端代码编辑器 (github.com)

一句话解决

  • 简单的讲就是, 鼠标hover到某变量时,调用了VSCode内置插件API, 插件调用TS语言服务器,进行AST解析查找获取结果并显示.

VSCode文本模型

  • VSCode中使用monacoEditor实现编辑器主界面,
  • 其中每个文本文件进入编辑器后,都会创建为一个文本模型, VSC会解析这个文本模型, 类似AST的解析,
  • 其中每个变量,函数名,关键字等都会成为一个token进行保存,每个token都有自己的id

TypeScript语言服务插件

VSCode源码中的extensions文件夹下存放了内置的插件, 其中的typescript-language-features既是其语言服务器,提供了丰富的语法感知、编译与调试等功能。

  • VSCode会给每个单独的插件创建一个独立子进程
  • 其主类typescriptServiceClient是其根入口
  • 其中通过languageProvider 注册了大量的语言服务事件, 如 hover, definitions, references等(定义于languageFeatures文件夹中)
  • 每个事件都定义了一个Provider类,从源码中可以看到
ts 复制代码
// TypeScriptHoverProvider 鼠标悬停服务类做的事情
class TypeScriptHoverProvider implements vscode.HoverProvider {

    // hover时逻辑
    public async provideHover() {
        // 1. 向 TypeScript 服务器发起 quickinfo 请求
        this.client.execute('quickinfo', args, token);
        // 2. 创建Hover悬浮窗
        return new vscode.Hover(
            this.getContents()
        );
    }
    // 获取对应需要显示的内容数据
    private getContents() { }
}
  • execute命令调用栈为
  • execute-executeImpl - beforeCommand - serverState.server.executeImpl

BeforeCommand

  • 在执行command前, 需要进行一次beforeCommand, 内部调用了BufferSynchronizer 类进行flush刷新
  • BufferSynchronizer 管理与TS服务器之间的缓冲区同步。
  • 检查文件是否支持批处理,如果支持则将其保存到一个映射表中。这样可以使 TS 服务器更有效地处理更改
  1. 对于打开(open)、关闭(close)等文件操作,如果该类支持批处理,则将它们缓存到名为 _pending 的映射表中;
  2. 在flush的时候统一对所有pending的文件进行updateOnce命令
  3. 如果不支持批处理,则直接以无需回应的方式执行对应某一状态转移命令

TypeScriptServer

  • 接下来走到了excuteImpl方法,这个方法定义于ITypeScriptServer 接口

  • 该是用于 VSCode 编辑器连接 TypeScript 服务器(ts-server)的标准接口

  • VSCode中有多个类都实现了该接口,需要看一下这个command最终调用的是哪个实例上的方法

  • 有三个类实现了该接口

  • ProcessBasedTsServer // 启动一个独立的ts-server子进程,与之通信并处理来自编辑器界面的请求

  • GetErrRoutingTsServer // 用于捕获tsserver中/geterr请求返回的错误信息列表

  • SyntaxRoutingTsServer// 主要用于编辑器中对TS/JS进行语法检查和 AST 解析

SyntaxRoutingTsServer

  • 实际上,hover时和按住ctrl时触发的 quickInfo请求和Definition请求都是通过SyntaxRoutingTsServer触发的, 从源码中可以看到
  • 之后我们会想typescript语言服务器发送一个quickInfo请求,

TS语言服务器

    • github.com/microsoft/T... - 该链接提供了 Typescript 编译器项目仓库,在其 lib 目录下可以找到 tsServer 子项目。
  • github.com/microsoft/v... - 这个链接直接给出了利用typescript npm模块中已经内含挂载tsserver进程方案之示例
  • 这两个仓库是单独维护的仓库,没有直接放在vscode源码中,
  • 由官方文档可得知, 这个库主要是对生成的文档模型进行ast查找来实现quickInfo请求的

小结

  • 鼠标hover, 调用插件API
  • 插件API提供中层解析
  • 插件请求TS语言服务器
  • TS语言服务器进行AST解析计算结果并返回
  • 新建弹窗显示到UI界面
相关推荐
能来帮帮蒟蒻吗10 小时前
VUE3 -综合实践(Mock+Axios+ElementPlus)
前端·javascript·vue.js·笔记·学习·ajax·typescript
菜鸟una18 小时前
【taro3 + vue3 + webpack4】在微信小程序中的请求封装及使用
前端·vue.js·微信小程序·小程序·typescript·taro
struggle20251 天前
continue通过我们的开源 IDE 扩展和模型、规则、提示、文档和其他构建块中心,创建、共享和使用自定义 AI 代码助手
javascript·ide·python·typescript·开源
Bl_a_ck2 天前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架
Bl_a_ck2 天前
开发环境(Development Environment)
开发语言·前端·javascript·typescript·ecmascript
菜鸟una3 天前
【layout组件 与 路由镶嵌】vue3 后台管理系统
前端·vue.js·elementui·typescript
浪裡遊4 天前
Typescript中的对象类型
开发语言·前端·javascript·vue.js·typescript·ecmascript
从味书4 天前
安装typescript时,npm install -g typescript报错
javascript·typescript·npm
風吹过5 天前
A* (AStar) 寻路
typescript·cocos2d
geovindu6 天前
vue3: pdf.js 2.16.105 using typescript
javascript·vue.js·typescript·pdf