inspect_tree_spec.lua (10228B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local clear = n.clear 5 local insert = n.insert 6 local dedent = t.dedent 7 local eq = t.eq 8 local exec_lua = n.exec_lua 9 local feed = n.feed 10 11 describe('vim.treesitter.inspect_tree', function() 12 before_each(clear) 13 14 local expect_tree = function(x) 15 local expected = vim.split(vim.trim(dedent(x)), '\n') 16 local actual = n.buf_lines(0) ---@type string[] 17 eq(expected, actual) 18 end 19 20 it('working', function() 21 insert([[ 22 print() 23 ]]) 24 25 exec_lua(function() 26 vim.treesitter.start(0, 'lua') 27 vim.treesitter.inspect_tree() 28 end) 29 30 expect_tree [[ 31 (chunk ; [0, 0] - [2, 0] 32 (function_call ; [0, 0] - [0, 7] 33 name: (identifier) ; [0, 0] - [0, 5] 34 arguments: (arguments))) ; [0, 5] - [0, 7] 35 ]] 36 end) 37 38 it('sets correct buffer name', function() 39 t.skip(t.is_zig_build(), 'vim.treesitter not found after chdir with build.zig') 40 41 n.api.nvim_set_current_dir(t.paths.test_source_path .. '/test/functional/fixtures') 42 n.command('edit lua/syntax_error.lua') 43 eq('lua/syntax_error.lua', n.fn.bufname('%')) 44 local full_path = n.api.nvim_buf_get_name(0) 45 46 n.exec_lua('vim.treesitter.start(0, "lua")') 47 n.exec_lua('vim.treesitter.inspect_tree()') 48 local expected = [[ 49 (chunk ; [0, 0] - [1, 0] 50 (ERROR ; [0, 0] - [0, 21] 51 (identifier) ; [0, 5] - [0, 8] 52 (identifier) ; [0, 9] - [0, 15] 53 (identifier))) ; [0, 16] - [0, 21] 54 ]] 55 expect_tree(expected) 56 eq('Syntax tree for lua/syntax_error.lua', n.fn.bufname('%')) 57 58 n.command('bwipe!') 59 eq('lua/syntax_error.lua', n.fn.bufname('%')) 60 61 n.api.nvim_set_current_dir('pack') 62 eq(full_path, n.fn.bufname('%')) 63 64 n.exec_lua('vim.treesitter.inspect_tree()') 65 expect_tree(expected) 66 eq('Syntax tree for ' .. full_path, n.fn.bufname('%')) 67 end) 68 69 it('can toggle to show anonymous nodes', function() 70 insert([[ 71 print('hello') 72 ]]) 73 74 exec_lua(function() 75 vim.treesitter.start(0, 'lua') 76 vim.treesitter.inspect_tree() 77 end) 78 feed('a') 79 80 expect_tree [[ 81 (chunk ; [0, 0] - [2, 0] 82 (function_call ; [0, 0] - [0, 14] 83 name: (identifier) ; [0, 0] - [0, 5] 84 arguments: (arguments ; [0, 5] - [0, 14] 85 "(" ; [0, 5] - [0, 6] 86 (string ; [0, 6] - [0, 13] 87 start: "'" ; [0, 6] - [0, 7] 88 content: (string_content) ; [0, 7] - [0, 12] 89 end: "'") ; [0, 12] - [0, 13] 90 ")"))) ; [0, 13] - [0, 14] 91 ]] 92 end) 93 94 it('works for injected trees', function() 95 insert([[ 96 ```lua 97 return 98 ``` 99 ]]) 100 101 exec_lua(function() 102 vim.treesitter.start(0, 'markdown') 103 vim.treesitter.get_parser():parse() 104 vim.treesitter.inspect_tree() 105 end) 106 107 expect_tree [[ 108 (document ; [0, 0] - [4, 0] 109 (section ; [0, 0] - [4, 0] 110 (fenced_code_block ; [0, 0] - [3, 0] 111 (fenced_code_block_delimiter) ; [0, 0] - [0, 3] 112 (info_string ; [0, 3] - [0, 6] 113 (language)) ; [0, 3] - [0, 6] 114 (block_continuation) ; [1, 0] - [1, 0] 115 (code_fence_content ; [1, 0] - [2, 0] 116 (chunk ; [1, 0] - [2, 0] 117 (return_statement)) ; [1, 0] - [1, 6] 118 (block_continuation)) ; [2, 0] - [2, 0] 119 (fenced_code_block_delimiter)))) ; [2, 0] - [2, 3] 120 ]] 121 end) 122 123 it('works with multiple injection on the same node', function() 124 insert([[--* #include<stdio.h>]]) 125 exec_lua(function() 126 vim.treesitter.query.set( 127 'lua', 128 'injections', 129 [[ 130 (comment 131 content: (_) @injection.content 132 (#set! injection.language "markdown")) 133 (comment 134 content: (_) @injection.content 135 (#set! injection.language "c") 136 (#offset! @injection.content 0 1 0 0)) 137 ]] 138 ) 139 vim.treesitter.start(0, 'lua') 140 vim.treesitter.get_parser():parse(true) 141 vim.treesitter.inspect_tree() 142 end) 143 feed('I') 144 expect_tree [[ 145 (chunk ; [0, 0] - [1, 0] lua 146 (comment ; [0, 0] - [0, 21] lua 147 content: (comment_content ; [0, 2] - [0, 21] lua 148 (document ; [0, 2] - [0, 21] markdown 149 (section ; [0, 2] - [0, 21] markdown 150 (list ; [0, 2] - [0, 21] markdown 151 (list_item ; [0, 2] - [0, 21] markdown 152 (list_marker_star) ; [0, 2] - [0, 4] markdown 153 (paragraph ; [0, 4] - [0, 21] markdown 154 (inline ; [0, 4] - [0, 21] markdown 155 (inline))))))) ; [0, 4] - [0, 21] markdown_inline 156 (translation_unit ; [0, 4] - [0, 21] c 157 (preproc_include ; [0, 4] - [0, 21] c 158 path: (system_lib_string)))))) ; [0, 12] - [0, 21] c 159 ]] 160 end) 161 162 it('can toggle to show languages', function() 163 insert([[ 164 ```lua 165 return 166 ``` 167 ]]) 168 169 exec_lua(function() 170 vim.treesitter.start(0, 'markdown') 171 vim.treesitter.get_parser():parse() 172 vim.treesitter.inspect_tree() 173 end) 174 feed('I') 175 176 expect_tree [[ 177 (document ; [0, 0] - [4, 0] markdown 178 (section ; [0, 0] - [4, 0] markdown 179 (fenced_code_block ; [0, 0] - [3, 0] markdown 180 (fenced_code_block_delimiter) ; [0, 0] - [0, 3] markdown 181 (info_string ; [0, 3] - [0, 6] markdown 182 (language)) ; [0, 3] - [0, 6] markdown 183 (block_continuation) ; [1, 0] - [1, 0] markdown 184 (code_fence_content ; [1, 0] - [2, 0] markdown 185 (chunk ; [1, 0] - [2, 0] lua 186 (return_statement)) ; [1, 0] - [1, 6] lua 187 (block_continuation)) ; [2, 0] - [2, 0] markdown 188 (fenced_code_block_delimiter)))) ; [2, 0] - [2, 3] markdown 189 ]] 190 end) 191 192 it('updates source and tree buffer windows and closes them correctly', function() 193 local name = t.tmpname() 194 n.command('edit ' .. name) 195 insert([[ 196 print() 197 ]]) 198 n.command('set filetype=lua | write') 199 200 -- setup two windows for the source buffer 201 exec_lua(function() 202 _G.source_win = vim.api.nvim_get_current_win() 203 _G.source_win2 = vim.api.nvim_open_win(0, false, { 204 win = 0, 205 split = 'left', 206 }) 207 end) 208 209 -- setup three windows for the tree buffer 210 exec_lua(function() 211 vim.treesitter.inspect_tree() 212 _G.tree_win = vim.api.nvim_get_current_win() 213 _G.tree_win2 = vim.api.nvim_open_win(0, false, { 214 win = 0, 215 split = 'left', 216 }) 217 _G.tree_win3 = vim.api.nvim_open_win(0, false, { 218 win = 0, 219 split = 'left', 220 }) 221 end) 222 223 -- close original source window without closing tree views 224 exec_lua('vim.api.nvim_set_current_win(source_win)') 225 feed(':quit<CR>') 226 eq('', n.api.nvim_get_vvar('errmsg')) 227 eq(true, exec_lua('return vim.api.nvim_win_is_valid(tree_win)')) 228 eq(true, exec_lua('return vim.api.nvim_win_is_valid(tree_win2)')) 229 eq(true, exec_lua('return vim.api.nvim_win_is_valid(tree_win3)')) 230 231 -- navigates correctly to the remaining source buffer window 232 exec_lua('vim.api.nvim_set_current_win(tree_win)') 233 feed('<CR>') 234 eq('', n.api.nvim_get_vvar('errmsg')) 235 eq(true, exec_lua('return vim.api.nvim_get_current_win() == source_win2')) 236 237 -- close original tree window 238 exec_lua(function() 239 vim.api.nvim_set_current_win(_G.tree_win2) 240 vim.api.nvim_win_close(_G.tree_win, false) 241 end) 242 243 -- navigates correctly to the remaining source buffer window 244 feed('<CR>') 245 eq('', n.api.nvim_get_vvar('errmsg')) 246 eq(true, exec_lua('return vim.api.nvim_get_current_win() == source_win2')) 247 248 -- close source buffer window and all remaining tree windows 249 n.expect_exit(n.command, 'quit') 250 end) 251 252 it('shows which nodes are missing', function() 253 insert([[ 254 int main() { 255 if (a.) { 256 // ^ MISSING field_identifier here 257 if (1) d() 258 // ^ MISSING ";" here 259 } 260 } 261 ]]) 262 263 exec_lua(function() 264 vim.treesitter.start(0, 'c') 265 vim.treesitter.inspect_tree() 266 end) 267 feed('a') 268 269 expect_tree [[ 270 (translation_unit ; [0, 0] - [8, 0] 271 (function_definition ; [0, 0] - [6, 1] 272 type: (primitive_type) ; [0, 0] - [0, 3] 273 declarator: (function_declarator ; [0, 4] - [0, 10] 274 declarator: (identifier) ; [0, 4] - [0, 8] 275 parameters: (parameter_list ; [0, 8] - [0, 10] 276 "(" ; [0, 8] - [0, 9] 277 ")")) ; [0, 9] - [0, 10] 278 body: (compound_statement ; [0, 11] - [6, 1] 279 "{" ; [0, 11] - [0, 12] 280 (if_statement ; [1, 4] - [5, 5] 281 "if" ; [1, 4] - [1, 6] 282 condition: (parenthesized_expression ; [1, 7] - [1, 11] 283 "(" ; [1, 7] - [1, 8] 284 (field_expression ; [1, 8] - [1, 10] 285 argument: (identifier) ; [1, 8] - [1, 9] 286 operator: "." ; [1, 9] - [1, 10] 287 field: (MISSING field_identifier)) ; [1, 10] - [1, 10] 288 ")") ; [1, 10] - [1, 11] 289 consequence: (compound_statement ; [1, 12] - [5, 5] 290 "{" ; [1, 12] - [1, 13] 291 (comment) ; [2, 4] - [2, 41] 292 (if_statement ; [3, 8] - [4, 36] 293 "if" ; [3, 8] - [3, 10] 294 condition: (parenthesized_expression ; [3, 11] - [3, 14] 295 "(" ; [3, 11] - [3, 12] 296 (number_literal) ; [3, 12] - [3, 13] 297 ")") ; [3, 13] - [3, 14] 298 consequence: (expression_statement ; [3, 15] - [4, 36] 299 (call_expression ; [3, 15] - [3, 18] 300 function: (identifier) ; [3, 15] - [3, 16] 301 arguments: (argument_list ; [3, 16] - [3, 18] 302 "(" ; [3, 16] - [3, 17] 303 ")")) ; [3, 17] - [3, 18] 304 (comment) ; [4, 8] - [4, 36] 305 (MISSING ";"))) ; [4, 36] - [4, 36] 306 "}")) ; [5, 4] - [5, 5] 307 "}"))) ; [6, 0] - [6, 1] 308 ]] 309 end) 310 end)