今天翻新了一下ccls的codeLens和codeAction。下面簡單介紹下這兩個LSP requests
-
textDocument/codeAction
: clang FixIt,如void main(){}
自動更正爲int main(){}
textDocument/codeAction
可返回(Command | CodeAction)[] | null
,目前lsp-mode僅處理Command[]
,這個PR添加edit?: WorkspaceEdit;
的支持。- 插入
void main() {}
-
textDocument/publishDiagnostics
在void
處warning -
M-x lsp-execute-code-action
and select the action - ccls返回
CodeAction[]
- lsp-mode自動更正爲
int main() {}
- 插入
-
textDocument/codeLens
: 原來cquery的做法,codeLens返回值包含所有refs/derived/bases/vars的Location[]
,因爲三種原因會造成緩慢:- 消息很大。如果有1000 refs那麼就返回1000
Location[]
。服務端要計算一會兒 - Emacs JSON deserialize慢
- 把LSP的
Location
(line/character)翻譯成(point)
慢。大量(goto-char 1) (forward-line l) (forward-char c)
操作。根據我的理解,移動操作的時間和移動距離正相關。
- 消息很大。如果有1000 refs那麼就返回1000
現在改成ccls僅返回
"command":{
"title":"1 var",
"command":"ccls.xref",
"arguments":["{\"usr\":16926293689053220079,\"kind\":2,\"field\":\"instances\"}"]}}
取代原來的1000 Location[]
。點擊1000 refs
overlay時,發送workspace/executeCommand
,帶上"arguments"
,ccls返回1000 Location[]
。參照下圖理解。
我另外加了ccls-code-lens-position
,預設爲'end
,用overlay after-string放置到行末。但無法防止point移動到overlay右邊,如何避免呢?
(-let (([l0 c0 l1 c1 command] lens))
(forward-line (- l1 line))
(let ((ov (pcase ccls-code-lens-position
('end
(let ((p (line-end-position)))
(make-overlay p p)))
('inplace
(forward-char c1)
(make-overlay (point) (point))))))
(overlay-put ov 'ccls-code-lens t)
(overlay-put ov 'after-string (ccls--make-code-lens-string (if (= l1 line) "|" " ") command)))
(setq line l1)
)
point移動到overlay右邊可以打字,不過好在這個是暫時的,textDocument/didChange
觸發diagnostics更新後,emacs-ccls會重新請求codeLens,overlay又會被重新放置到行末。
放到右邊不inplace干擾後我打算預設開啓了 (add-hook 'lsp-after-open-hook #'ccls-code-lens-mode)
。如果這個能改好體驗會更棒一些。
另外改進lsp-ui-sideline.el
顯示code lens也是個好主意。等人來實現~