@@ -11,6 +11,9 @@ local M = {}
1111-- start (optional): The location of the start of this symbol (default @symbol)
1212-- end (optional): The location of the end of this symbol (default @start)
1313
14+ --- @param bufnr ? integer
15+ --- @return boolean
16+ --- @return string ? msg
1417M .is_supported = function (bufnr )
1518 local lang = helpers .get_buf_lang (bufnr )
1619 if not helpers .has_parser (lang ) then
@@ -22,28 +25,23 @@ M.is_supported = function(bufnr)
2225 return true , nil
2326end
2427
25- M .fetch_symbols_sync = function (bufnr )
26- bufnr = bufnr or 0
27- local extensions = require (" aerial.backends.treesitter.extensions" )
28- local get_node_text = vim .treesitter .get_node_text
29- local include_kind = config .get_filter_kind_map (bufnr )
30- local parser = helpers .get_parser (bufnr )
31- local items = {}
32- if not parser then
33- backends .set_symbols (bufnr , items , { backend_name = " treesitter" , lang = " unknown" })
34- return
35- end
36- local lang = parser :lang ()
37- local syntax_tree = parser :parse ()[1 ]
38- local query = helpers .get_query (lang )
39- if not query or not syntax_tree then
28+ --- @param bufnr integer
29+ --- @param lang string
30+ --- @param query vim.treesitter.Query
31+ --- @param syntax_tree ? TSTree
32+ local function set_symbols_from_treesitter (bufnr , lang , query , syntax_tree )
33+ if not syntax_tree then
4034 backends .set_symbols (
4135 bufnr ,
42- items ,
36+ {} ,
4337 { backend_name = " treesitter" , lang = lang , syntax_tree = syntax_tree }
4438 )
4539 return
4640 end
41+ local extensions = require (" aerial.backends.treesitter.extensions" )
42+ local get_node_text = vim .treesitter .get_node_text
43+ local include_kind = config .get_filter_kind_map (bufnr )
44+ local items = {}
4745 -- This will track a loose hierarchy of recent node+items.
4846 -- It is used to determine node parents for the tree structure.
4947 local stack = {}
@@ -79,26 +77,33 @@ M.fetch_symbols_sync = function(bufnr)
7977 local name_match = match .name or {}
8078 local selection_match = match .selection or {}
8179 local symbol_node = (match .symbol or match .type or {}).node
80+ if not symbol_node then
81+ goto continue
82+ end
8283 -- The location capture groups are optional. We default to the
8384 -- location of the @symbol capture
8485 local start_node = (match .start or {}).node or symbol_node
8586 local end_node = (match [" end" ] or {}).node or start_node
8687 local parent_item , parent_node , level = ext .get_parent (stack , match , symbol_node )
8788 -- Sometimes our queries will match the same node twice.
8889 -- Detect that (symbol_node == parent_node), and skip dupes.
89- if not symbol_node or symbol_node == parent_node then
90+ if symbol_node == parent_node then
9091 goto continue
9192 end
9293 local kind = match .kind
9394 if not kind then
94- vim .api .nvim_err_writeln (
95- string.format (" Missing 'kind' metadata in query file for language %s" , lang )
95+ vim .api .nvim_echo (
96+ { { string.format (" Missing 'kind' metadata in query file for language %s" , lang ) } },
97+ true ,
98+ { err = true }
9699 )
97100 break
98101 elseif not vim .lsp .protocol .SymbolKind [kind ] then
99- vim .api .nvim_err_writeln (
100- string.format (" Invalid 'kind' metadata '%s' in query file for language %s" , kind , lang )
101- )
102+ vim .api .nvim_echo ({
103+ {
104+ string.format (" Invalid 'kind' metadata '%s' in query file for language %s" , kind , lang ),
105+ },
106+ }, true , { err = true })
102107 break
103108 end
104109 local range = helpers .range_from_nodes (start_node , end_node )
@@ -166,12 +171,71 @@ M.fetch_symbols_sync = function(bufnr)
166171 )
167172end
168173
169- M .fetch_symbols = M .fetch_symbols_sync
174+ --- @param bufnr integer
175+ --- @return nil | vim.treesitter.LanguageTree parser
176+ --- @return nil | vim.treesitter.Query query
177+ local function get_lang_and_query (bufnr )
178+ local parser = helpers .get_parser (bufnr )
179+ if not parser then
180+ backends .set_symbols (bufnr , {}, { backend_name = " treesitter" , lang = " unknown" })
181+ return
182+ end
183+ local lang = parser :lang ()
184+ local query = helpers .get_query (lang )
185+ if not query then
186+ backends .set_symbols (bufnr , {}, { backend_name = " treesitter" , lang = lang })
187+ return
188+ end
189+ return parser , query
190+ end
191+
192+ --- @param bufnr ? integer
193+ M .fetch_symbols_sync = function (bufnr )
194+ bufnr = bufnr or 0
195+ local parser , query = get_lang_and_query (bufnr )
196+ if not parser or not query then
197+ return
198+ end
199+ local lang = parser :lang ()
200+ local syntax_tree = parser :parse ()[1 ]
201+ set_symbols_from_treesitter (bufnr , lang , query , syntax_tree )
202+ end
203+
204+ --- @param bufnr ? integer
205+ M .fetch_symbols = function (bufnr )
206+ if not bufnr or bufnr == 0 then
207+ bufnr = vim .api .nvim_get_current_buf ()
208+ end
209+ local parser , query = get_lang_and_query (bufnr )
210+ if not parser or not query then
211+ return
212+ end
213+ local lang = parser :lang ()
214+ local syntax_trees = parser :parse (nil , function (err , syntax_trees )
215+ if err then
216+ vim .api .nvim_echo (
217+ { { string.format (" Error parsing buffer: %s" , err ) } },
218+ true ,
219+ { err = true }
220+ )
221+ backends .set_symbols (bufnr , {}, { backend_name = " treesitter" , lang = lang })
222+ return
223+ else
224+ assert (syntax_trees )
225+ set_symbols_from_treesitter (bufnr , lang , query , syntax_trees [1 ])
226+ end
227+ end )
228+ if syntax_trees then
229+ set_symbols_from_treesitter (bufnr , lang , query , syntax_trees [1 ])
230+ end
231+ end
170232
233+ --- @param bufnr integer
171234M .attach = function (bufnr )
172235 util .add_change_watcher (bufnr , " treesitter" )
173236end
174237
238+ --- @param bufnr integer
175239M .detach = function (bufnr )
176240 util .remove_change_watcher (bufnr , " treesitter" )
177241end
0 commit comments