From c9955eaba9134b63774ed5abc5fbab2e1102e312 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 24 Jan 2018 22:49:25 -0800 Subject: [PATCH] Add :LSClientDocumentSymbol --- CHANGELOG.md | 5 ++ README.md | 7 ++ autoload/lsc/config.vim | 2 + autoload/lsc/params.vim | 14 ++++ autoload/lsc/reference.vim | 146 ++++++++++++++++++++++++++++++++++--- doc/lsc.txt | 6 ++ plugin/lsc.vim | 1 + 7 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 autoload/lsc/params.vim diff --git a/CHANGELOG.md b/CHANGELOG.md index 210beda4..985dad5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.2.10-dev + +- Add `:LSClientDocumentSymbol` command to populate the quickfix list with + symbols in the current document. + # 0.2.9+1 - Fix error in calling function message hooks. diff --git a/README.md b/README.md index cb6601b9..24482a72 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ let g:lsc_auto_map = { \ 'GoToDefinition': '', \ 'FindReferences': 'gr', \ 'FindCodeActions': 'ga', + \ 'DocumentSymbol': 'gs', \ 'ShowHover': 'K', \ 'Completion': 'completefunc', \} @@ -115,6 +116,12 @@ cursor moves before the server responds the response will be ignored. While the cursor is on any identifier call `LSClientFindReferences` (`gr` if using the default mappings) to populate the quickfix list with usage locations. +### Document Symbols + +In any enabled buffer call `LSClientDocumentSymbol` (`gs` if using the default +mappings) to populate the quickfix list with the locations of all symbols in +that document. + ### Hover While the cursor is on any identifier call `LSClientShowHover` (`K` if using the diff --git a/autoload/lsc/config.vim b/autoload/lsc/config.vim index b28faa05..28faa054 100644 --- a/autoload/lsc/config.vim +++ b/autoload/lsc/config.vim @@ -4,6 +4,7 @@ let s:default_maps = { \ 'FindCodeActions': 'ga', \ 'Rename': 'gR', \ 'ShowHover': 'K', + \ 'DocumentSymbol': 'gs', \ 'Completion': 'completefunc', \} @@ -25,6 +26,7 @@ function! lsc#config#mapKeys() abort for command in [ \ 'GoToDefinition', \ 'FindReferences', + \ 'DocumentSymbol', \ 'ShowHover', \ 'FindCodeActions', \] diff --git a/autoload/lsc/params.vim b/autoload/lsc/params.vim new file mode 100644 index 00000000..fed893fe --- /dev/null +++ b/autoload/lsc/params.vim @@ -0,0 +1,14 @@ +function! lsc#params#textDocument(...) abort + if a:0 >= 1 + let file_path = a:1 + else + let file_path = expand('%:p') + endif + return {'textDocument': {'uri': lsc#uri#documentUri(file_path)}} +endfunction + +function! lsc#params#documentPosition() abort + return { 'textDocument': {'uri': lsc#uri#documentUri()}, + \ 'position': {'line': line('.') - 1, 'character': col('.') - 1} + \ } +endfunction diff --git a/autoload/lsc/reference.vim b/autoload/lsc/reference.vim index 1e50d3b5..f991fd92 100644 --- a/autoload/lsc/reference.vim +++ b/autoload/lsc/reference.vim @@ -1,7 +1,7 @@ function! lsc#reference#goToDefinition() abort call lsc#file#flushChanges() call lsc#server#userCall('textDocument/definition', - \ s:TextDocumentPositionParams(), + \ lsc#params#documentPosition(), \ lsc#util#gateResult('GoToDefinition', function('GoToDefinition'))) endfunction @@ -22,15 +22,9 @@ function! s:GoToDefinition(result) abort call s:goTo(file, line, character) endfunction -function! s:TextDocumentPositionParams() abort - return { 'textDocument': {'uri': lsc#uri#documentUri()}, - \ 'position': {'line': line('.') - 1, 'character': col('.') - 1} - \ } -endfunction - function! lsc#reference#findReferences() abort call lsc#file#flushChanges() - let params = s:TextDocumentPositionParams() + let params = lsc#params#documentPosition() let params.context = {'includeDeclaration': v:true} call lsc#server#userCall('textDocument/references', params, \ function('setQuickFixReferences')) @@ -92,7 +86,7 @@ endfunction function! lsc#reference#hover() abort call lsc#file#flushChanges() - let params = s:TextDocumentPositionParams() + let params = lsc#params#documentPosition() call lsc#server#userCall('textDocument/hover', params, \ function('showHover')) endfunction @@ -112,3 +106,137 @@ function! s:showHover(result) abort let lines = split(contents, "\n") call lsc#util#displayAsPreview(lines) endfunction + +" Request a list of symbols in the current document and populate the quickfix +" list. +function! lsc#reference#documentSymbols() abort + call lsc#file#flushChanges() + call lsc#server#userCall('textDocument/documentSymbol', + \ lsc#params#textDocument(), + \ function('setQuickFixSymbols')) +endfunction + +function! s:setQuickFixSymbols(results) abort + if empty(a:results) + call lsc#message#show('No symbols found') + endif + + let file_path = lsc#uri#documentPath(a:results[0].location.uri) + call map(a:results, {_, symbol -> s:QuickFixSymbol(bufnr(file_path), symbol)}) + call sort(a:results, 'lsc#util#compareQuickFixItems') + call setqflist(a:results) + copen +endfunction + +" Conver an LSP SymbolInformation to a quick fix item. +" +" Both representations are dictionaries. +" +" SymbolInformation: +" 'location': +" 'uri': file:// URI +" 'range': {'start': {'line', 'characater'}, 'end': {'line', 'character'}} +" 'name': The symbol's name +" 'kind': Integer kind +" 'containerName': The element this symbol is inside +" +" QuickFix Item: (as used) +" 'bufnr': This buffer +" 'lnum': line number +" 'col': column number +" 'text': "SymbolName" [kind] (in containerName)? +function! s:QuickFixSymbol(bufnr, symbol) abort + let item = {'lnum': a:symbol.location.range.start.line + 1, + \ 'col': a:symbol.location.range.start.character + 1, + \ 'bufnr': a:bufnr} + let text = '"'.a:symbol.name.'"' + if !empty(a:symbol.kind) + let text .= ' ['.s:SymbolKind(a:symbol.kind).']' + endif + if !empty(a:symbol.containerName) + let text .= ' in '.a:symbol.containerName + endif + let item.text = text + return item +endfunction + +function! s:SymbolKind(kind) abort + if a:kind == 1 + return 'File' + endif + if a:kind == 2 + return 'Module' + endif + if a:kind == 3 + return 'Namespace' + endif + if a:kind == 4 + return 'Package' + endif + if a:kind == 5 + return 'Class' + endif + if a:kind == 6 + return 'Method' + endif + if a:kind == 7 + return 'Property' + endif + if a:kind == 8 + return 'Field' + endif + if a:kind == 9 + return 'Constructor' + endif + if a:kind == 10 + return 'Enum' + endif + if a:kind == 11 + return 'Interface' + endif + if a:kind == 12 + return 'Function' + endif + if a:kind == 13 + return 'Variable' + endif + if a:kind == 14 + return 'Constant' + endif + if a:kind == 15 + return 'String' + endif + if a:kind == 16 + return 'Number' + endif + if a:kind == 17 + return 'Boolean' + endif + if a:kind == 18 + return 'Array' + endif + if a:kind == 19 + return 'Object' + endif + if a:kind == 20 + return 'Key' + endif + if a:kind == 21 + return 'Null' + endif + if a:kind == 22 + return 'EnumMember' + endif + if a:kind == 23 + return 'Struct' + endif + if a:kind == 24 + return 'Event' + endif + if a:kind == 25 + return 'Operator' + endif + if a:kind == 26 + return 'TypeParameter' + endif +endfunction diff --git a/doc/lsc.txt b/doc/lsc.txt index 6a29e869..0c25de2e 100644 --- a/doc/lsc.txt +++ b/doc/lsc.txt @@ -60,6 +60,11 @@ under the cursor, including it's definition. Sends a "textDocument/references" request with the location set to the cursor's position. With |lsc-default-map| this command is bound to "gr". + *:LSClientDocumentSymbol* +Populate the |quickfix| with a list of the symbols defined in the current +buffer. Sends a "textDocument/documentSymbol" request. With |lsc-default-map| +this command is bound to "gs". + *:LSClientShowHover* Open a |preview| window with hover information corresponding to the element under the cursor. Sends a "textDocument/hover" request with the location set @@ -192,6 +197,7 @@ The default mapping for keys, if you've opted in to "g:lsc_auto_map" are: |:LSClientGoToDefinition| gr |:LSClientFindReferences| +gs |:LSClientDocumentSymbol| ga |:LSClientFindCodeActions| gR |:LSClientRename| K |:LSClientShowHover| diff --git a/plugin/lsc.vim b/plugin/lsc.vim index f2cd7a40..47987728 100644 --- a/plugin/lsc.vim +++ b/plugin/lsc.vim @@ -14,6 +14,7 @@ endif command! LSClientGoToDefinition call lsc#reference#goToDefinition() command! LSClientFindReferences call lsc#reference#findReferences() command! LSClientShowHover call lsc#reference#hover() +command! LSClientDocumentSymbol call lsc#reference#documentSymbols() command! LSClientFindCodeActions call lsc#edit#findCodeActions() command! LSClientAllDiagnostics call lsc#diagnostics#showInQuickFix() command! LSClientRestartServer call IfEnabled('lsc#server#restart')