From: Yegappan Lakshmanan Date: Mon, 4 Jan 2021 03:58:17 +0000 (-0800) Subject: Display child symbols in the outline window X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=deecabe1da092f4b810636457574b603f97626d4;p=vim-lsp.git Display child symbols in the outline window --- diff --git a/autoload/handlers.vim b/autoload/handlers.vim index 5bc7f80..4c589fc 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -289,6 +289,68 @@ def LspSymbolKindToName(symkind: number): string return symbolMap[symkind] enddef +# process SymbolInformation[] +def s:processSymbolInfoTable(symbolInfoTable: list>, + symbolTypeTable: dict>>, + symbolLineTable: list>) + var fname: string + var symbolType: string + var name: string + var r: dict> + var symInfo: dict + + for symbol in symbolInfoTable + fname = LspUriToFile(symbol.location.uri) + symbolType = LspSymbolKindToName(symbol.kind) + name = symbol.name + if symbol->has_key('containerName') + if symbol.containerName != '' + name ..= ' [' .. symbol.containerName .. ']' + endif + endif + r = symbol.location.range + + if !symbolTypeTable->has_key(symbolType) + symbolTypeTable[symbolType] = [] + endif + symInfo = {name: name, range: r} + symbolTypeTable[symbolType]->add(symInfo) + symbolLineTable->add(symInfo) + endfor +enddef + +# process DocumentSymbol[] +def s:processDocSymbolTable(docSymbolTable: list>, + symbolTypeTable: dict>>, + symbolLineTable: list>) + var symbolType: string + var name: string + var r: dict> + var symInfo: dict + var symbolDetail: string + var childSymbols: dict>> + + for symbol in docSymbolTable + name = symbol.name + symbolType = LspSymbolKindToName(symbol.kind) + r = symbol.range + if symbol->has_key('detail') + symbolDetail = symbol.detail + endif + if !symbolTypeTable->has_key(symbolType) + symbolTypeTable[symbolType] = [] + endif + childSymbols = {} + if symbol->has_key('children') + s:processDocSymbolTable(symbol.children, childSymbols, symbolLineTable) + endif + symInfo = {name: name, range: r, detail: symbolDetail, + children: childSymbols} + symbolTypeTable[symbolType]->add(symInfo) + symbolLineTable->add(symInfo) + endfor +enddef + # process the 'textDocument/documentSymbol' reply from the LSP server # Open a symbols window and display the symbols as a tree def s:processDocSymbolReply(lspserver: dict, req: dict, reply: dict): void @@ -300,45 +362,19 @@ def s:processDocSymbolReply(lspserver: dict, req: dict, reply: dict>> var symbolLineTable: list> = [] - var name: string - var symbolType: string - var r: dict> - var symbolDetail: string - var symInfo: dict if req.params.textDocument.uri != '' fname = LspUriToFile(req.params.textDocument.uri) endif - for symbol in reply.result - symbolDetail = '' - if symbol->has_key('location') - # interface SymbolInformation - fname = LspUriToFile(symbol.location.uri) - symbolType = LspSymbolKindToName(symbol.kind) - name = symbol.name - if symbol->has_key('containerName') - if symbol.containerName != '' - name ..= ' [' .. symbol.containerName .. ']' - endif - endif - r = symbol.location.range - else - # interface DocumentSymbol - name = symbol.name - symbolType = LspSymbolKindToName(symbol.kind) - r = symbol.range - if symbol->has_key('detail') - symbolDetail = symbol.detail - endif - endif - if !symbolTypeTable->has_key(symbolType) - symbolTypeTable[symbolType] = [] - endif - symInfo = {name: name, range: r, detail: symbolDetail} - symbolTypeTable[symbolType]->add(symInfo) - symbolLineTable->add(symInfo) - endfor + if reply.result[0]->has_key('location') + # SymbolInformation[] + s:processSymbolInfoTable(reply.result, symbolTypeTable, symbolLineTable) + else + # DocumentSymbol[] + s:processDocSymbolTable(reply.result, symbolTypeTable, symbolLineTable) + endif + # sort the symbols by line number symbolLineTable->sort({a, b -> a.range.start.line - b.range.start.line}) lsp#updateOutlineWindow(fname, symbolTypeTable, symbolLineTable) diff --git a/autoload/lsp.vim b/autoload/lsp.vim index 83d1172..2e799c8 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -521,7 +521,8 @@ def s:outlineJumpToSymbol() # Highlight the selected symbol prop_remove({type: 'LspOutlineHighlight'}) - prop_add(line('.'), 3, {type: 'LspOutlineHighlight', + var col: number = match(getline('.'), '\S') + 1 + prop_add(line('.'), col, {type: 'LspOutlineHighlight', length: w:lspSymbols.lnumTable[lnum].name->len()}) # disable the outline window refresh @@ -556,6 +557,39 @@ enddef var skipOutlineRefresh: bool = false +def s:addSymbolText(symbolTypeTable: dict>>, + pfx: string, + text: list, + lnumMap: list>, + children: bool) + var prefix: string = pfx .. ' ' + for [symType, symbols] in items(symbolTypeTable) + if !children + # Add an empty line for the top level symbol types. For types in the + # children symbols, don't add the empty line. + text->extend(['']) + lnumMap->extend([{}]) + endif + if children + text->extend([prefix .. symType]) + prefix ..= ' ' + else + text->extend([symType]) + endif + lnumMap->extend([{}]) + for s in symbols + text->add(prefix .. s.name) + # remember the line number for the symbol + lnumMap->add({name: s.name, lnum: s.range.start.line + 1, + col: s.range.start.character + 1}) + s.outlineLine = lnumMap->len() + if !s.children->empty() + s:addSymbolText(s.children, prefix, text, lnumMap, true) + endif + endfor + endfor +enddef + # update the symbols displayed in the outline window def lsp#updateOutlineWindow(fname: string, symbolTypeTable: dict>>, @@ -586,17 +620,7 @@ def lsp#updateOutlineWindow(fname: string, # First two lines in the buffer display comment information var lnumMap: list> = [{}, {}] var text: list = [] - for [symType, syms] in items(symbolTypeTable) - text->extend(['', symType]) - lnumMap->extend([{}, {}]) - for s in syms - text->add(' ' .. s.name) - # remember the line number for the symbol - lnumMap->add({name: s.name, lnum: s.range.start.line + 1, - col: s.range.start.character + 1}) - s.outlineLine = lnumMap->len() - endfor - endfor + s:addSymbolText(symbolTypeTable, '', text, lnumMap, false) append('$', text) w:lspSymbols = {filename: fname, lnumTable: lnumMap, symbolsByLine: symbolLineTable} @@ -605,6 +629,7 @@ def lsp#updateOutlineWindow(fname: string, if !saveCursor->empty() setpos('.', saveCursor) endif + win_gotoid(prevWinID) # Highlight the current symbol @@ -664,7 +689,9 @@ def s:outlineHighlightCurrentSymbol() endif # Highlight the selected symbol - prop_add(symbolTable[mid].outlineLine, 3, + var col: number = + match(getbufline(bnr, symbolTable[mid].outlineLine)[0], '\S') + 1 + prop_add(symbolTable[mid].outlineLine, col, {bufnr: bnr, type: 'LspOutlineHighlight', length: symbolTable[mid].name->len()}) @@ -702,6 +729,11 @@ def s:openOutlineWindow() :setlocal bufhidden=delete :setlocal noswapfile nobuflisted :setlocal nonumber norelativenumber fdc=0 nowrap winfixheight winfixwidth + :setlocal shiftwidth=2 + :setlocal foldenable + :setlocal foldcolumn=4 + :setlocal foldlevel=4 + :setlocal foldmethod=indent setline(1, ['# File Outline']) :nnoremap q :quit :nnoremap :call outlineJumpToSymbol()