一个基于 websocket 的 LSP 客户端

如题,主要受勇哥的 deno-bridge 启发,不过我选择了用 nodejs + typescript 实现,主要是 node 环境相对 deno 更普遍一些。

感受一下效果(功能尚不完整):

python: lsp-py

rust: lsp-rs

项目地址:lsp-rocks

补充一下运行方法:

  1. 克隆下来之后,执行 npm i && npm run build
  2. 设置 lsp-rocks-server-bin 的值为 lsp-rocks根目录 + /lib/cli.js。(请教各位大佬,有木有办法自动获取到这个路径) 已改为自动获取
  3. 打开文件,M-x lsp-rocks-mode
13 个赞

欢迎欢迎,这是正确的方向,我去点颗星星⭐

我稍微瞄了一下代码,不要在elisp端做json数据解析,你遇到volar这种服务器,elisp解析数据压力极大,会造成卡顿,还会遭遇GC影响。

第二,不要用 put-text-property 的方法,像Java服务器会返回很多函数名一样(label),但是参数完全不一样(editText)的情况,对于capf这种接口来说,它认为label一样候选词就应该一样,虽然你加了 put-text-property 绕,但会增加很多查询性能负担。

建议像lsp-bridge那样,你应该在nodejs那端做缓存,这样除了解决上述问题,还可以把补全API文档和实时诊断信息(这两块实时数据量超大)拦截在外部进程,极大减少LSP数据洪流对emacs的冲击。

感谢勇哥的建议 :pray:

补充一点信息:目前我的前端用的是 company,它提供了一个 :async 回调,在数据准备好的时候,才会处理补全。在 发出请求 → 解析响应 这段时间不会让 emacs 卡顿。

  1. 经测试,即使后端返回上千条补全信息,emacs 也能很好的完成 json parse, 且不会卡手
  2. 同名 label 的问题我后面测试 java 试一下
  3. 一开始,我确实在 node 端做了缓存,但发现好像没必要,因为我只处理相同 command 最后一次的请求,其他的全部丢弃
1 个赞

跑了下 jdtls,居然能区分,可能是 company 已经处理了?

后续需要处理下展示,把方法签名补上,现在只能在 minibuffer 看到签名。

可以用变量load-file-name,看下帮助就明白了。

多谢大佬,已解决

你要测试一下volar,这种服务器会返回上千条补全和数万行每个API对应的文档,遇到这种实时返回文档的服务器。

elisp解析json就扛不住,而且后面还有实时诊断信息,这个量不仅仅是一个几千个列表的字符串。

缓存主要是为了 completion-item 和 诊断 准备的。

不缓存,这些实时数据都是浪费elisp解析性能,大部分都用不着,还容易触发GC

简陋的实现了异步 xref: async-xref

4 个赞

异步 xref & 跳转定义、查找引用、查找声明 已实现:

implement async xref & refactor DeclarationFeature, DefinitionFeature and ReferencesFeature

3 个赞

新实现两个功能:

hover/describe-thing-at-point: hover


signature-help: signature

暂不支持动态更新 signature & signature 翻页

动态更新 signature 信息: dynamic-signature