返回介绍

drei 是如何工作的

发布于 2021-03-25 13:13:13 字数 3669 浏览 972 评论 0 收藏 0

language server 为编辑器client提供语言智能提示功能,包括

  • format
  • validate
  • autoComplete
  • goToDefinition
  • type Intelligence

等等功能。

vscode 官方及社区已有各种语言的 language server,为开发者提供了很多便利。

drei 是为 san 设计的 language server,(名字是 三 来的)。

一个标准的 language server 分为三层

  • language server 对外提供标准化的接口
  • language service 语言服务层面,在解析代码的基础上提供各种智能分析结果
  • language service host 语言文件系统层,负责文件管理

对于一种复合语言,比如 html,其中除了 html tag,tag 中包含的内容也可能是一种独立的语言(js/ts/css)等, 这时 language server 分为四层

  • language server
  • language modes 在这一层,会根据请求的不同,调用不同语言的 language service,以提供正确的结果
  • language services 不同块对应的语言的的 language service.
  • language service host

对于 html 这种语言,其各部分语言之间的内容是不相关的:

而对于 .vue, .san 这种单文件组件,template中tag与script中声明的component相关,差值表达式与中script声明的data/methods相关,因此不再是一个简单的树状组织结构。

这个造型

vetur初期的版本基本上是在html的版本上,对script部分作了扩展以支持vue的api自动提示,对html部分增加的tag的自动提示,但对差值表达式没有进行处理。

drei在这个基础上更进一步,让template中的差值表达式和指令都能够获得language service的支持。

为了使用ts language service提供的能力,我们需要准备正确的ts文件,再把请求映射到这些生成的文件上。

由于 interpolation 中的变量是存在作用域的,因此从template的 interpolation 抽出一个 interpolation tree (类似于一个ast),再从这个树ts的 ast, 也就是一个 typescript 的 source file,。

ts的ast中所有的节点都包含位置信息,如果生成的ast位置信息不对,在进行后续操作时会抛出各种神秘的异常,这也是开发中的主要障碍。

另外,由于 san 设计的接口并没有考虑到 typescript 的局限性,ts language service 直接对 san文件的script部分进行推断基本就只能拿到一个any的结果,(这里也可能是因为我写的ts定义文件不对),因此在script部分的类型提示是从 js文件生成了一个ts文件,再从ts文件提供类型提示。

生成这两个新文件还有一个前提,需要知道原本script中用户声明的对象的类型:

对 ts language serivice 的扩展方式如这个图,如果获得类型和输出修改后的 sourcefile 的 language service 是同一个,你需要在访问一个文件之前知道他的内容,这里就会产生一个死循环。

因此这里使用了两个 language service

先从其中一个language service中获得基本的类型信息,再生成文件,给到第二个 language service 提供接口。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文