为了体验 LSP 的效果,最近试用了下 LanguageClient-neovim 这个插件(以下简称 LCN )。
总的来说 LSP 的基本功都已实现,但是细节体验上还跟 vscode 存在很大差距,尤其是在补全功能的实现上面。
我给作者提了几次 issue, 但是似乎作者不愿意讨论相关问题,所以记录在此,以供诸位 vim 用户参考、讨论。
不支持 complete
的 supportSnippet
却会在 initialize 中发送 {"supportSnippet": true}
。
LCN 简单的检测了用户是否安装了 snippet 相关插件,如果有安装就声明 supportSnippet 为 true,但是实际上 LCN 并没有任何代码支持对 LSP 服务端返回的 snippet 进行扩展,也没有为 completion 插件声明如何处理 snippet。相关 issue: https://github.com/autozimu/LanguageClient-neovim/issues/379 https://github.com/autozimu/LanguageClient-neovim/pull/410
可能错误的补全起始位置判定:
源码使用了 python 的 \w
寻找补全单词起始位: https://github.com/autozimu/LanguageClient-neovim/blob/next/rplugin/python3/deoplete/sources/LanguageClientSource.py#L20
但是不同语言类型关键词并不相同,这里使用 vim 中的 \k
来寻找补全的起始位置应该更合适些。正确的实现应该是在 LSP 服务端返回的 TextEdit
中的 range
里面获取补全的起始和终止位置。
发送错误的补全起始位置给 LSP server。
LSP 服务端 completion 接受的 position 中的 charactor 字段应该是当前光标所在列,但是 LSP 却会发送当前单词第一个字母所在列,相关代码: https://github.com/autozimu/LanguageClient-neovim/blob/next/rplugin/python3/deoplete/sources/LanguageClientSource.py#L23, 这会导致部分 LSP 服务端位置判定错,例如: https://github.com/chemzqm/wxml-languageserver 需要在补全时判定当前光标后面是否已经紧跟 =
来返回不同 textEdit
对象。
猜测如此实现是为了更好支持 deoplete 插件中提供的 fuzzy match 功能,因为 LSP 服务端可能对于补全前半部分做的是全匹配验证。
错误的处理返回的 TextEdit
代码: https://github.com/autozimu/LanguageClient-neovim/blob/d7cac79c1dd2b7b644c07ff55c8208821ff1192e/src/types.rs#L419 text_edit.new_text
应该就是服务端返回用于插入的文本,但是由于 LCN 无法支持 text_edit
中的 range
修改已有 buffer,所以只能去主观的截取第一个单词,然后移除末尾的非单词部分。该做法会极大影响部分 LSP 服务的使用,例如 https://github.com/vscode-langservers/vscode-css-languageserver-bin 补全 css 属性时 new_text
最后为空格,另外像 https://github.com/Microsoft/vscode-html-languageservice 会返回带有 "
的 snippet 补全项。
问题根源在与 neovim/vim 提供的 complete 功能无法支持 LSP 中的 TextEdit
以及 snippet
等定义,所以我提了一个需求 https://github.com/neovim/neovim/issues/8334
1
congeec 2018-05-01 02:17:11 +08:00 via iPhone
所以要作为 source 陪 deoplete 之类的用
不过 deoplete 体验不如 ycm 前端 |
2
autozimu 2018-05-01 05:53:58 +08:00 3
并不是我不想讨论这些问题. 而是在你了解具体问题的复杂性之前讨论并不能解决问题. 再者, talk is cheap. 我的时间很有限, 不想把它浪费在无谓的争论上.
1. 这么做是有原因的. 因为的确部分用户(包括我)通过一些个设置是能够利用 snippet 的功能的. https://github.com/autozimu/LanguageClient-neovim/pull/327 而且我也加入了最新的 configuration override 这个检测. 2. 推荐你去尝试了解下 deoplete 整个的 workflow, 重点 deoplete 什么情况下触发 completion. 在用到这个 regex 的时候, 根本还没有 LSP server 的 response, 何谈根据 LSP response 判断起点. `\ w` 只是目前的一个权宜之计. 3. 同 2 4. 这个是因为 deoplete 并不理解 LSP 的 TextEdit 概念. deoplete 期望收到的是 word, 而某些 LSP server 返回的是 TextEdit, 所以需要这一步的装换. comment 里面我也写到了, extremely hacky. 如果你发现了某些情况下这个 hack 会有问题, 当然欢迎你的 PR, 但不是这种会造成 regression 的 https://github.com/autozimu/LanguageClient-neovim/issues/409 我再重复一遍, 我的时间有限, 不想浪费在讨论和争论上. Show me your code. |
3
yuuko 2018-05-01 06:32:18 +08:00 via Android
目前的 vim/neovim 上 lsp 体验不好,还是等 neovim 官方支持,不过貌似还要很长时间
|
4
muziki 2018-05-01 06:50:06 +08:00 via iPhone
ale
试过 lcn 这个插件 用了 ale 之后就回不去了 |
5
hanxiV2EX 2018-05-01 09:14:30 +08:00 via Android
NCM 怎么样?
|
6
congeec 2018-05-01 09:14:43 +08:00 via iPhone 1
开源嘛,能动手就不逼逼
|
7
skywind3000 2018-05-01 12:56:11 +08:00
@autozimu 快支持一下引用结果添加到 quickfix 窗口,我正在帮你的 LanguageClient-neovim 写评测呢。
|
9
7jmS8834H50s975y 2018-05-01 13:12:42 +08:00
关于 lsp 的支持,我个人觉得还是等 neovim 的官方 PR 比较合适,我已经本地测试过这个 PR,基本能完成正常补全。
https://github.com/neovim/neovim/pull/6856 |
10
glues 2018-05-01 16:06:23 +08:00 via iPhone
这不正是自己造轮子的好机会吗
|
11
omph 2018-05-01 18:09:09 +08:00
作为一个旁观者,我想说,neovim 有时中文乱码
|
12
chemzqm OP |
13
chemzqm OP @wsdjeg 就是不知道啥时候能 merge,而且也是不支持 text edit 和 snippet 这些 LSP 2.0 的东西,LCN 除了补全有些问题,其它功能例如 hover,signature,diagnostic 还是比较好用的。
|
14
chemzqm OP @autozimu
> 1. 这么做是有原因的. 因为的确部分用户(包括我)通过一些个设置是能够利用 snippet 的功能的. https://github.com/autozimu/LanguageClient-neovim/pull/327 而且我也加入了最新的 configuration override 这个检测. 你说的能利用是让 complete item 里面的 word 对应到自己创建 snippet 然后再通过特定快捷键触发补全吧?这种无视后端返回数据然后嫁接到自己实现的东西都不出 bug ? |
15
pony279 2018-07-09 12:57:21 +08:00 1
|