neoclide / coc.nvim

Nodejs extension host for vim & neovim, load extensions like VSCode and host language servers.
Other
24.47k stars 956 forks source link

Switch function between source/header in Clangd #929

Closed widgetii closed 5 years ago

widgetii commented 5 years ago

Is your feature request related to a problem? Please describe. Clangd language server from 6 version supports custom protocol extension which lets editor switch between main source and header file (in C/C++ world - files with c/h extensions). https://clangd.github.io/extensions.html#switch-between-sourceheader

Describe the solution you'd like Add new language server call to get the URI of the corresponding header file and open it in vim and vice versa

Describe alternatives you've considered Use old-school vim plugins like https://github.com/derekwyatt/vim-fswitch or https://github.com/Kris2k/A.vim but without actual context from language server

widgetii commented 5 years ago

@chemzqm Is it possible to make arbitrary call to current language server (clangd in this case) using coc.nvim API to obtain return data and process them later? It seems that the task can it accomplished using few lines in vimscript

chemzqm commented 5 years ago

Checkout :h CocRequest()

nathanblair commented 5 years ago

I tried this with

:call CocRequest('clangd', \ 'textDocument/switchSourceHeader', \ {'textDocument': {'uri': 'file:///headerFile.hpp'}})

But this just returns with a failed to decode request

From looking at the docs for CocRequest it looks like this is the right syntax and is consistent with the example so I don't know what the error could be for?

Would the CocRequest not work because this request endpoint is an extension of the protocol?

chemzqm commented 5 years ago

No

nathanblair commented 5 years ago

Whoops! Solved it. I think it must have been something with the way the file was expanding at runtime. Either way, I got this to work using:

execute 'edit' CocRequest('clangd', 'textDocument/switchSourceHeader', {'uri': 'file://'.expand("%:p")})

And then just set put that in a function and called it with a keybinding!

Excellent work!

mellery451 commented 5 years ago

@nathanblair that's a great tip - but it doesn't work for me ...instead I get a new buffer opened called v:null. Is there any additional configuration for this to work? I'm using vim 8.1 and clangd/coc are both up-to-date (latest stable releases)

widgetii commented 5 years ago

@mellery451 My slightly reworked version (if it can be helpful), works on NVim

function! s:EditAlternate()
    let l:alter = CocRequest('clangd', 'textDocument/switchSourceHeader', {'uri': 'file://'.expand("%:p")})
    " remove file:/// from response
    let l:alter = substitute(l:alter, "file://", "", "")
    execute 'edit ' . l:alter
endfunction
autocmd vimrc FileType cpp nmap <leader>x :call <SID>EditAlternate()<CR>
mellery451 commented 5 years ago

@widgetii thanks for that update. Still doesn't work for me, but verbose logging tells me that it's some sort of clangd issue. I have no idea why its returning null since the request looks basically right to me. I guess I'll keep investigating that angle.

V[09:48:56.269] <<< {"id":1,"jsonrpc":"2.0","method":"textDocument/switchSourceHeader","params":{"uri":"file:///Users/ellery1/work/path/to/source.cpp"}}
I[09:48:56.269] <-- textDocument/switchSourceHeader(1)
I[09:48:56.269] --> reply:textDocument/switchSourceHeader(1) 0 ms
V[09:48:56.269] >>> {"id":1,"jsonrpc":"2.0","result":null}
mellery451 commented 5 years ago

turns out clangd doesn't like my source/header directory structure, so I opened https://github.com/clangd/clangd/issues/182. The snippets above work great as long as clangd cooperates - Thanks for the tips @widgetii and @nathanblair.

balta2ar commented 4 years ago

@MaskRay is it possible to support textDocument/switchSourceHeader in ccls as well?

fannheyward commented 4 years ago

Sorry for the noise, I've created coc-clangd, added some clangd protocol extensions support:

  1. Switch between source/header, using :CocCommand clangd.switchSourceHeader
  2. File status monitor, shows on statusline
  3. Force diagnostics generation, default true
  4. Diagnostic categories & inline fixes, can be used for diagnostic format
  5. Symbol info under cursor, using CocCommand clangd.symbolInfo, currently just echoed
lee-shun commented 3 years ago

hello guys, do you know how to config the ccls to do the same function?

jinastro commented 1 year ago

Sorry for the noise, I've created coc-clangd, added some clangd protocol extensions support:

  1. Switch between source/header, using :CocCommand clangd.switchSourceHeader
  2. File status monitor, shows on statusline
  3. Force diagnostics generation, default true
  4. Diagnostic categories & inline fixes, can be used for diagnostic format
  5. Symbol info under cursor, using CocCommand clangd.symbolInfo, currently just echoed

Thanks very much for your work, but I found that it returns like"file not found" when I swtich from header file to source file, would you know how to solve this problem?

fannheyward commented 1 year ago

@jinastro create an issue in coc-clangd with server response please.