盐焗乳鸽还要香锅

V1

2022/11/14阅读:20主题:默认主题

实现一个具有差量解析算法的vscode插件

实现一个具有差量解析算法的vscode插件


前言

前情提要:本文适合于有vscode插件开发经验的同学~

我们平时在写scss的时候,是否因为经常忘记了自己定义的类名而频繁地在scss和tsx文件之间切换窗口呢?为了解决这个痛点,我决定自己实现一个工具,实现在scss文件中自动提示以及补全自己定义过的类名。

链接:https://github.com/1360151219/react-class-completion

https://marketplace.visualstudio.com/items?itemName=psfe.psfe-react-extension

欢迎大家前来star哦~🌟

Features

总体架构使用vscode lsp模型,具体样例可以去找vscode extension example。

相同目录下的scss文件和tsx文件进行解析,并且将类名进行存储等逻辑处理。

  • [x] 🌟 support incremental text sync and store & incremental parse algorithm
  • [x] 🌟 support class name completions for scss/css from .tsx files below the same dir path.
    • [x] ordinary className in JSXAttribute.
    • [x] variable className in JSXAttribute. example:
    // src/index,tsx
    const prefix = 'foo';
    export const foo = () => (
      <div>
        <div className="foo">foo</div>
        <div className="foo2">foo</
    div>
        <div className={`${prefix}3`}>foo</div>
        <div className={`${prefix}-${prefix}-4`}>foo</
    div>
      </div>
    );
    • [x] listening for classname changing in .tsx file.(only in changed file)
  • [x] 🌟 support go to defination from classname in scss/css to the relative tsx file

实现过程

  1. 使用babel api对tsx文件做解析
  2. 使用vscode-css-languageservice api 对scss文件做解析
  3. 🌟【重点讲解】实现lsp的差量文本同步以及差量解析算法

如果每次文本变化client都将全部文本发送到server上的话,将会浪费非常大的内存。于是vscode自身提供了差量同步的设置:

 textDocumentSync: {
    change: TextDocumentSyncKind.Incremental,
    openClose: true,// 开启open、close的事件监听
  },
  ...
  ...
  connection.onDidChangeTextDocument((param) => {
  // todo
});

注意:经过测试,这里的监听事件必须放在connection.listen(); 之后

设置好了之后,我们将param打印出来看一看(这里我们只输入一个字符1):

我们可以发现,这里server只会接受到修改内容range以及text修改文件路径。我们该如何去处理好这些信息呢?这就需要去自己实现一个差量解析的算法了。

第一步:要想根据以上信息去获取新的内容,我们首先想到的就是对原有文件内容做一个储存。

因此这里我实现了一个DocMap类,本质上是一个Map<uri,content>结构的一个哈希表。我们将在监听onDidOpenTextDocument的时候对相同目录下的tsx文件以及scss文件做解析,在解析过程中把文件内容存储在我们的DocMap中。

第二步:根据接受到的差量信息更新文件内容。

实际上,这里的关键就是做一个rangeToUpdate的一个函数。接受参数range以及text,对之前我们存储的文件内容做更新。

要实现这个功能,我们必须利用TextDocument类上的方法。首先是将range转换成对应文本的偏移值offset,其次,根据原有文件的总偏移值length做判断。如果startOffset刚好等于length,则可以判断为是直接在文本末尾新增内容,直接添加即可;如果是小于,则是对原有文本内容做了修改,直接拼接字符串即可:startOffset之前的文本+text+endOffset之后的文本。

至此文件内容就实现了更新。之后再对新的文本内容做编译解析即可。

总结

回过头来我们可以发现这样子的一个差量编译算法的优势有哪些?

  1. lsp通讯的数据量大大减少
  2. 无需每次通过fs去读取文件内容,减少io操作
  3. 实现以单文件为粒度的逻辑解析

我是盐焗乳鸽还要香锅,喜欢我的文章欢迎关注噢,github链接https://github.com/1360151219,博客链接是strk2.cn,掘金账号https://juejin.cn/user/1812428713376845

分类:

前端

标签:

前端

作者介绍

盐焗乳鸽还要香锅
V1