]> Sergey Matveev's repositories - vim-lsp.git/blob - autoload/lsp/typehierarchy.vim
Update diags location list when the diags for the buffer changes. Update comments
[vim-lsp.git] / autoload / lsp / typehierarchy.vim
1 vim9script
2
3 # Functions for dealing with type hierarchy (super types/sub types)
4
5 import './util.vim'
6 import './symbol.vim'
7
8 # Parse the type hierarchy in "typeHier" and displays a tree of type names
9 # in the current buffer.  This function is called recursively to display the
10 # super/sub type hierarchy.
11 #
12 # Returns the line number where the next type name should be added.
13 def TypeTreeGenerate(isSuper: bool, typeHier: dict<any>, pfx_arg: string,
14                         typeTree: list<string>, typeUriMap: list<dict<any>>)
15
16   var itemHasChildren = false
17   if isSuper
18     if typeHier->has_key('parents') && !typeHier.parents->empty()
19       itemHasChildren = true
20     endif
21   else
22     if typeHier->has_key('children') && !typeHier.children->empty()
23       itemHasChildren = true
24     endif
25   endif
26
27   var itemBranchPfx: string
28   if itemHasChildren
29     itemBranchPfx = '▾ '
30   else
31     itemBranchPfx = pfx_arg->empty() ? '' : '  '
32   endif
33
34   var typestr: string
35   var kindstr = symbol.SymbolKindToName(typeHier.kind)
36   if kindstr != ''
37     typestr = $'{pfx_arg}{itemBranchPfx}{typeHier.name} ({kindstr[0]})'
38   else
39     typestr = $'{pfx_arg}{itemBranchPfx}{typeHier.name}'
40   endif
41   typeTree->add(typestr)
42   typeUriMap->add(typeHier)
43
44   # last item to process
45   if !itemHasChildren
46     return
47   endif
48
49   var items: list<dict<any>>
50   items = isSuper ? typeHier.parents : typeHier.children
51
52   for item in items
53     TypeTreeGenerate(isSuper, item, $'{pfx_arg}| ', typeTree, typeUriMap)
54   endfor
55 enddef
56
57 # Display a popup with the file containing a type and highlight the line and
58 # the type name.
59 def UpdateTypeHierFileInPopup(lspserver: dict<any>, typeUriMap: list<dict<any>>)
60   if lspserver.typeHierPopup->winbufnr() == -1
61     return
62   endif
63
64   lspserver.typeHierFilePopup->popup_close()
65
66   var n = line('.', lspserver.typeHierPopup) - 1
67   var fname: string = util.LspUriToFile(typeUriMap[n].uri)
68
69   var bnr = fname->bufadd()
70   if bnr == 0
71     return
72   endif
73
74   var popupAttrs = {
75     title: $"{fname->fnamemodify(':t')} ({fname->fnamemodify(':h')})",
76     wrap: false,
77     fixed: true,
78     minheight: 10,
79     maxheight: 10,
80     minwidth: winwidth(0) - 38,
81     maxwidth: winwidth(0) - 38,
82     cursorline: true,
83     border: [],
84     line: 'cursor+1',
85     col: 1
86   }
87   lspserver.typeHierFilePopup = popup_create(bnr, popupAttrs)
88   var cmds =<< trim eval END
89     [{typeUriMap[n].range.start.line + 1}, 1]->cursor()
90     :normal! z.
91   END
92   win_execute(lspserver.typeHierFilePopup, cmds)
93
94   lspserver.typeHierFilePopup->clearmatches()
95   var start_col = util.GetLineByteFromPos(bnr,
96                                         typeUriMap[n].selectionRange.start) + 1
97   var end_col = util.GetLineByteFromPos(bnr, typeUriMap[n].selectionRange.end)
98   var pos = [[typeUriMap[n].selectionRange.start.line + 1,
99              start_col, end_col - start_col + 1]]
100   matchaddpos('Search', pos, 10, -1, {window: lspserver.typeHierFilePopup})
101 enddef
102
103 def TypeHierPopupFilter(lspserver: dict<any>, typeUriMap: list<dict<any>>,
104                         popupID: number, key: string): bool
105   popupID->popup_filter_menu(key)
106   if lspserver.typeHierPopup->winbufnr() == -1
107     # popup is closed
108     if lspserver.typeHierFilePopup->winbufnr() != -1
109       lspserver.typeHierFilePopup->popup_close()
110     endif
111     lspserver.typeHierFilePopup = -1
112     lspserver.typeHierPopup = -1
113   else
114     UpdateTypeHierFileInPopup(lspserver, typeUriMap)
115   endif
116
117   return true
118 enddef
119
120 def TypeHierPopupCallback(lspserver: dict<any>, typeUriMap: list<dict<any>>,
121                           popupID: number, selIdx: number)
122   if lspserver.typeHierFilePopup->winbufnr() != -1
123     lspserver.typeHierFilePopup->popup_close()
124   endif
125   lspserver.typeHierFilePopup = -1
126   lspserver.typeHierPopup = -1
127
128   if selIdx <= 0
129     # popup is canceled
130     return
131   endif
132
133   # Save the current cursor location in the tag stack.
134   util.PushCursorToTagStack()
135   util.JumpToLspLocation(typeUriMap[selIdx - 1], '')
136 enddef
137
138 # Show the super or sub type hierarchy items "types" as a tree in a popup
139 # window
140 export def ShowTypeHierarchy(lspserver: dict<any>, isSuper: bool, types: dict<any>)
141
142   if lspserver.typeHierPopup->winbufnr() != -1
143     # If the type hierarchy popup window is already present, close it.
144     lspserver.typeHierPopup->popup_close()
145   endif
146
147   var typeTree: list<string>
148   var typeUriMap: list<dict<any>>
149
150   # Generate a tree of the type hierarchy items
151   TypeTreeGenerate(isSuper, types, '', typeTree, typeUriMap)
152
153   # Display a popup window with the type hierarchy tree and a popup window for
154   # the file.
155   var popupAttrs = {
156       title: $'{isSuper ? "Super" : "Sub"}Type Hierarchy',
157       wrap: 0,
158       pos: 'topleft',
159       line: 'cursor+1',
160       col: winwidth(0) - 34,
161       minheight: 10,
162       maxheight: 10,
163       minwidth: 30,
164       maxwidth: 30,
165       mapping: false,
166       fixed: true,
167       filter: function(TypeHierPopupFilter, [lspserver, typeUriMap]),
168       callback: function(TypeHierPopupCallback, [lspserver, typeUriMap])
169     }
170   lspserver.typeHierPopup = popup_menu(typeTree, popupAttrs)
171   UpdateTypeHierFileInPopup(lspserver, typeUriMap)
172 enddef
173
174 # vim: tabstop=8 shiftwidth=2 softtabstop=2