company-lsp 终于来了

cquery 支持 hierarchical .cquery,子目录 .cquery 文件影响所在子树的编译选项

compile_commands.json可以在 project/build/compile_commands.json 并且旁边有生成文件 project/build/generated.cc

等几个月等这个被作者捡起来吧 T_T

@tigersoldier

还有一个问题,好像company-lsp在匹配失败的时候也会强制换成候选的第一个,怎么让它不强制替换成第一个?

另外一个想请教的事情是,我好像设置过不补全参数表的,但我现在想补全参数表,但没找到在哪里了。。。隐约记得原来用company-clang的时候这么设置过。。。现在的表现是有参数的话,补全选中只有函数名字,没有参数的话,选中后会有括号。

这应该是之前的一个bug,更新之后还有这个问题吗? 如果有欢迎提issue。

company-lsp-enable-snippet?

第一个更新后没有了,第二个的话,company-lsp-enable-snippet我没有改动它,就是默认的on

你的配置是怎样的?建议强在调用lsp-xxx-enable之前先(require 'company-lsp),要不然会出现不能开启snippet的情况

这一楼.emacs中改动了两处:

第一处,my//enable-cquery-if-compile-commands-json改成了:

(defun my//enable-cquery-if-compile-commands-json ()
  (when
      (or (locate-dominating-file default-directory "compile_commands.json")
          (locate-dominating-file default-directory ".cquery"))
    (require 'company-lsp)
    (lsp-cquery-enable)))

第二处,company-backends改成了:

    (company-c-headers company-lsp company-bbdb company-nxml company-css company-cmake company-capf company-files
                       (company-dabbrev-code company-keywords)
                       company-oddmuse company-dabbrev)

https://github.com/emacs-lsp/lsp-mode/issues/293#issuecomment-370311956修好就不需要這個my//enable-cquery-if-compile-commands-json wrapper了

1 个赞

无法补全参数不像是由于配置错误造成的。开启lsp-print-io后尝试补全,*Messages*里的内容是什么?

开启方法:M-x set-variable <RET> lsp-print-io <RET> t

顺便给一下company-diag的输出呗。

struct foo_foo {
    int bar_bar;
    int bar(int);
};

void foo()
{
    foo_foo foo000;
    foo000.bar_bar;
    foo000.bar//choose bar here
}

lsp-print-io:

Output from language server: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/mark/test/etest/test.cc","diagnostics":[{"range":{"start":{"line":9,"character":14},"end":{"line":9,"character":14}},"severity":1,"source":"cquery","message":"expected ';' after expression"},{"range":{"start":{"line":9,"character":4},"end":{"line":9,"character":14}},"severity":1,"source":"cquery","message":"reference to non-static member function must be called"},{"range":{"start":{"line":8,"character":4},"end":{"line":8,"character":18}},"severity":2,"source":"cquery","message":"expression result unused [-Wunused-value]"}]}}

company-diag:

company-call-backend-raw: Company: backend company-lsp error "Wrong type argument: listp, t" with args (candidates (bar . t))

有没有带 textDocument/complete 的请求信息呢?尝试补全一个函数应该会产生若干条这样的请求

另外把所有的buffer都关掉再打开一个文件,看看能不能补全参数?

有人用lsp php的么?感觉怎么样?

这是我打开那个文件,删除第10行的.然后有按.触发补全的log:

For information about GNU Emacs and the GNU system, type C-h C-a.
lsp--stdio-wait: Content-Length: 564

{"jsonrpc":"2.0","method":"initialize","params":{"processId":4852,"rootPath":"/home/mark/test/etest/","rootUri":"file:///home/mark/test/etest/","capabilities":{"workspace":{"applyEdit":true,"executeCommand":{"dynamicRegistration":true}},"textDocument":{"synchronization":{"willSave":true,"didSave":true},"symbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"completion":{"completionItem":{"snippetSupport":true}}}},"initializationOptions":{"cacheDirectory":"/home/mark/test/etest/.cquery_cached_index/"}},"id":1}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}}
Output from language server: {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"textDocumentSync":2,"hoverProvider":true,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":",">","#","<","\"","/"]},"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"workspaceSymbolProvider":true,"codeActionProvider":true,"codeLensProvider":{"resolveProvider":false},"documentFormattingProvider":false,"documentRangeFormattingProvider":false,"renameProvider":true,"documentLinkProvider":{"resolveProvider":true},"executeCommandProvider":{"commands":[]}}}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
lsp--send-no-wait: Content-Length: 52

{"jsonrpc":"2.0","method":"initialized","params":{}}
lsp--send-no-wait: Content-Length: 297

{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc","languageId":"cpp","version":0,"text":"struct foo_foo {\n    int bar_bar;\n    int bar(int);\n};\n\nvoid foo()\n{\n    foo_foo foo000;\n    foo000.bar_bar;\n    foo000.\n}\n"}}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/setInactiveRegions","params":{"uri":"file:///home/mark/test/etest/test.cc","inactiveRegions":[]}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/publishSemanticHighlighting","params":{"uri":"file:///home/mark/test/etest/test.cc","symbols":[{"stableId":3,"parentKind":1,"kind":12,"storage":1,"ranges":[{"start":{"line":5,"character":5},"end":{"line":5,"character":8}}]},{"stableId":4,"parentKind":3,"kind":13,"storage":1,"ranges":[{"start":{"line":7,"character":12},"end":{"line":7,"character":18}},{"start":{"line":8,"character":4},"end":{"line":8,"character":10}}]},{"stableId":0,"parentKind":1,"kind":23,"storage":0,"ranges":[{"start":{"line":0,"character":7},"end":{"line":0,"character":14}},{"start":{"line":7,"character":4},"end":{"line":7,"character":11}}]},{"stableId":2,"parentKind":0,"kind":6,"storage":1,"ranges":[{"start":{"line":2,"character":8},"end":{"line":2,"character":11}}]},{"stableId":1,"parentKind":2,"kind":8,"storage":0,"ranges":[{"start":{"line":1,"character":8},"end":{"line":1,"character":15}},{"start":{"line":8,"character":11},"end":{"line":8,"character":18}}]}]}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/setInactiveRegions","params":{"uri":"file:///home/mark/test/etest/test.cc","inactiveRegions":[]}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/publishSemanticHighlighting","params":{"uri":"file:///home/mark/test/etest/test.cc","symbols":[{"stableId":3,"parentKind":1,"kind":12,"storage":1,"ranges":[{"start":{"line":5,"character":5},"end":{"line":5,"character":8}}]},{"stableId":4,"parentKind":3,"kind":13,"storage":1,"ranges":[{"start":{"line":7,"character":12},"end":{"line":7,"character":18}},{"start":{"line":8,"character":4},"end":{"line":8,"character":10}}]},{"stableId":0,"parentKind":1,"kind":23,"storage":0,"ranges":[{"start":{"line":0,"character":7},"end":{"line":0,"character":14}},{"start":{"line":7,"character":4},"end":{"line":7,"character":11}}]},{"stableId":2,"parentKind":0,"kind":6,"storage":1,"ranges":[{"start":{"line":2,"character":8},"end":{"line":2,"character":11}}]},{"stableId":1,"parentKind":2,"kind":8,"storage":0,"ranges":[{"start":{"line":1,"character":8},"end":{"line":1,"character":15}},{"start":{"line":8,"character":11},"end":{"line":8,"character":18}}]}]}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
Output from language server: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/mark/test/etest/test.cc","diagnostics":[{"range":{"start":{"line":10,"character":0},"end":{"line":10,"character":0}},"severity":1,"source":"cquery","message":"expected unqualified-id"},{"range":{"start":{"line":8,"character":4},"end":{"line":8,"character":18}},"severity":2,"source":"cquery","message":"expression result unused [-Wunused-value]"}]}}
lsp--send-no-wait: Content-Length: 237

{"jsonrpc":"2.0","method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc"},"range":{"start":{"line":9,"character":11},"end":{"line":9,"character":11}},"context":{"diagnostics":[]}},"id":2}
Output from language server: {"jsonrpc":"2.0","id":2,"result":[]}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
lsp--send-no-wait: Content-Length: 259

{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc","version":1},"contentChanges":[{"range":{"start":{"line":9,"character":10},"end":{"line":9,"character":11}},"rangeLength":1,"text":""}]}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
Output from language server: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/mark/test/etest/test.cc","diagnostics":[{"range":{"start":{"line":9,"character":10},"end":{"line":9,"character":10}},"severity":1,"source":"cquery","message":"expected ';' after expression"},{"range":{"start":{"line":8,"character":4},"end":{"line":8,"character":18}},"severity":2,"source":"cquery","message":"expression result unused [-Wunused-value]"},{"range":{"start":{"line":9,"character":4},"end":{"line":9,"character":10}},"severity":2,"source":"cquery","message":"expression result unused [-Wunused-value]"}]}}
lsp--send-no-wait: Content-Length: 260

{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc","version":2},"contentChanges":[{"range":{"start":{"line":9,"character":10},"end":{"line":9,"character":10}},"rangeLength":0,"text":"."}]}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
Output from language server: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/mark/test/etest/test.cc","diagnostics":[{"range":{"start":{"line":10,"character":0},"end":{"line":10,"character":0}},"severity":1,"source":"cquery","message":"expected unqualified-id"},{"range":{"start":{"line":8,"character":4},"end":{"line":8,"character":18}},"severity":2,"source":"cquery","message":"expression result unused [-Wunused-value]"}]}}
lsp--stdio-wait: Content-Length: 169

{"jsonrpc":"2.0","method":"textDocument/completion","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc"},"position":{"line":9,"character":11}},"id":3}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
Output from language server: {"jsonrpc":"2.0","id":3,"result":{"isIncomplete":false,"items":[{"label":"operator=","kind":2,"detail":"foo_foo & operator=(const foo_foo &)","documentation":"","sortText":"...........","insertText":"operator=(${1:const foo_foo &})$0","insertTextFormat":2},{"label":"~foo_foo","kind":4,"detail":"void ~foo_foo()","documentation":"","sortText":"........../","insertText":"~foo_foo()","insertTextFormat":1},{"label":"bar_bar","kind":5,"detail":"int bar_bar","documentation":"","sortText":"..........0","insertText":"bar_bar","insertTextFormat":1},{"label":"bar","kind":2,"detail":"int bar(int)","documentation":"","sortText":"..........1","insertText":"bar(${1:int})$0","insertTextFormat":2},{"label":"foo_foo","kind":22,"detail":"foo_foo::","documentation":"","sortText":"..........2","insertText":"foo_foo::","insertTextFormat":1}]}}
lsp--send-no-wait: Content-Length: 237

{"jsonrpc":"2.0","method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc"},"range":{"start":{"line":9,"character":11},"end":{"line":9,"character":11}},"context":{"diagnostics":[]}},"id":4}
Output from language server: {"jsonrpc":"2.0","id":4,"result":[]}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
lsp--send-no-wait: Content-Length: 237

{"jsonrpc":"2.0","method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc"},"range":{"start":{"line":9,"character":11},"end":{"line":9,"character":11}},"context":{"diagnostics":[]}},"id":5}
Output from language server: {"jsonrpc":"2.0","id":5,"result":[]}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
lsp--send-no-wait: Content-Length: 262

{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///home/mark/test/etest/test.cc","version":3},"contentChanges":[{"range":{"start":{"line":9,"character":11},"end":{"line":9,"character":11}},"rangeLength":0,"text":"bar"}]}}
Output from language server: {"jsonrpc":"2.0","method":"$cquery/progress","params":{"indexRequestCount":0,"doIdMapCount":0,"loadPreviousIndexCount":0,"onIdMappedCount":0,"onIndexedCount":0,"activeThreads":0}} [2 times]
Output from language server: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/mark/test/etest/test.cc","diagnostics":[{"range":{"start":{"line":9,"character":14},"end":{"line":9,"character":14}},"severity":1,"source":"cquery","message":"expected ';' after expression"},{"range":{"start":{"line":9,"character":4},"end":{"line":9,"character":14}},"severity":1,"source":"cquery","message":"reference to non-static member function must be called"},{"range":{"start":{"line":8,"character":4},"end":{"line":8,"character":18}},"severity":2,"source":"cquery","message":"expression result unused [-Wunused-value]"}]}}
company-call-backend-raw: Company: backend company-lsp error "Wrong type argument: listp, t" with args (candidates (bar . t))
mwheel-scroll: Beginning of buffer [3 times]
<mouse-6> is undefined
mwheel-scroll: Beginning of buffer
Mark set
next-line: End of buffer [10 times]
next-line: End of buffer

另外,补全失败后有的键不会强制替换成第一个,比如空格,有的键会,比如;

这是故意在第10行补全失败(按.之后输入bax;变成了~foo_foo();)的log:

company是最新版吗? 0.9.6?

抱歉回复晚了。

这个我不确定是什么问题。我这里补全失败后不会有任何替换,而且空格和;都不会提交补全,只有回车会。

我发现在你的log里,当输入bax之后cquery返回了所有可能的成员,而在我这里返回的内容是空。不确定是cquery的版本问题还是bug。@MaskRay

关于函数参数没有补全的问题,你的配置是正确的,而且cquery也的确返回了参数补全信息。我能想到的唯一可能是yasnippet没有启动。试试M-x yas-minor-mode看看管不管用。

喔喔,原来要yasnippet。。。懂了。。。

如果懷疑是cquery問題请改进 Debugging · jacobdufault/cquery Wiki · GitHub

然鹅现在还是不知道怎么给emacs配置lsp-mode,插件已经安装了,已经pip install language-server-package了

有没有教程给个链接