node_spec.lua (6862B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local clear = n.clear 5 local eq = t.eq 6 local exec_lua = n.exec_lua 7 local insert = n.insert 8 local assert_alive = n.assert_alive 9 10 before_each(clear) 11 12 local function lua_eval(lua_expr) 13 return exec_lua('return ' .. lua_expr) 14 end 15 16 describe('treesitter node API', function() 17 it('double free tree', function() 18 insert('F') 19 exec_lua(function() 20 vim.treesitter.start(0, 'lua') 21 vim.treesitter.get_parser(0):parse() 22 vim.treesitter.get_node():tree() 23 vim.treesitter.get_node():tree() 24 collectgarbage() 25 end) 26 assert_alive() 27 end) 28 29 it('double free tree 2', function() 30 exec_lua(function() 31 local parser = vim.treesitter.get_parser(0, 'c') 32 local x = parser:parse()[1]:root():tree() 33 vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, { 'y' }) 34 parser:parse() 35 vim.api.nvim_buf_set_text(0, 0, 0, 0, 1, { 'z' }) 36 parser:parse() 37 collectgarbage() 38 x:root() 39 end) 40 assert_alive() 41 end) 42 43 it('get_node() with lang given', function() 44 -- this buffer doesn't have filetype set! 45 insert('local foo = function() end') 46 exec_lua(function() 47 vim.treesitter.get_parser(0, 'lua'):parse() 48 _G.node = vim.treesitter.get_node({ 49 bufnr = 0, 50 pos = { 0, 6 }, -- on "foo" 51 lang = 'lua', 52 }) 53 end) 54 eq('foo', lua_eval('vim.treesitter.get_node_text(node, 0)')) 55 eq('identifier', lua_eval('node:type()')) 56 end) 57 58 it('get_node() with anonymous nodes included', function() 59 insert([[print('test')]]) 60 61 exec_lua(function() 62 _G.parser = vim.treesitter.get_parser(0, 'lua') 63 _G.tree = _G.parser:parse()[1] 64 _G.node = vim.treesitter.get_node({ 65 bufnr = 0, 66 pos = { 0, 6 }, -- on the first apostrophe 67 include_anonymous = true, 68 }) 69 end) 70 71 eq("'", lua_eval('node:type()')) 72 eq(false, lua_eval('node:named()')) 73 end) 74 75 it('can move between siblings', function() 76 insert([[ 77 int main(int x, int y, int z) { 78 return x + y * z 79 } 80 ]]) 81 82 exec_lua(function() 83 local parser = assert(vim.treesitter.get_parser(0, 'c')) 84 local tree = parser:parse()[1] 85 _G.root = tree:root() 86 vim.treesitter.language.inspect('c') 87 88 function _G.node_text(node) 89 return vim.treesitter.get_node_text(node, 0) 90 end 91 end) 92 93 exec_lua 'node = root:descendant_for_range(0, 9, 0, 14)' 94 eq('int x', lua_eval('node_text(node)')) 95 96 exec_lua 'node = node:next_sibling()' 97 eq(',', lua_eval('node_text(node)')) 98 99 exec_lua 'node = node:next_sibling()' 100 eq('int y', lua_eval('node_text(node)')) 101 102 exec_lua 'node = node:prev_sibling()' 103 eq(',', lua_eval('node_text(node)')) 104 105 exec_lua 'node = node:prev_sibling()' 106 eq('int x', lua_eval('node_text(node)')) 107 108 exec_lua 'node = node:next_named_sibling()' 109 eq('int y', lua_eval('node_text(node)')) 110 111 exec_lua 'node = node:prev_named_sibling()' 112 eq('int x', lua_eval('node_text(node)')) 113 end) 114 115 it('can retrieve the children of a node', function() 116 insert([[ 117 int main() { 118 int x = 3; 119 }]]) 120 121 local len = exec_lua(function() 122 local tree = vim.treesitter.get_parser(0, 'c'):parse()[1] 123 local node = assert(tree:root():child(0)) 124 _G.children = node:named_children() 125 126 return #_G.children 127 end) 128 129 eq(3, len) 130 eq('<node compound_statement>', lua_eval('tostring(children[3])')) 131 end) 132 133 it('can retrieve the tree root given a node', function() 134 insert([[ 135 int main() { 136 int x = 3; 137 }]]) 138 139 exec_lua(function() 140 local tree = vim.treesitter.get_parser(0, 'c'):parse()[1] 141 _G.root = tree:root() 142 _G.node = _G.root:child(0):child(2) 143 end) 144 145 eq(lua_eval('tostring(root)'), lua_eval('tostring(node:root())')) 146 end) 147 148 it('can compute the byte length of a node', function() 149 insert([[ 150 int main() { 151 int x = 3; 152 }]]) 153 154 exec_lua(function() 155 local tree = vim.treesitter.get_parser(0, 'c'):parse()[1] 156 _G.root = tree:root() 157 _G.child = _G.root:child(0):child(0) 158 end) 159 160 eq(28, lua_eval('root:byte_length()')) 161 eq(3, lua_eval('child:byte_length()')) 162 end) 163 164 it('child_with_descendant() works', function() 165 insert([[ 166 int main() { 167 int x = 3; 168 }]]) 169 170 exec_lua(function() 171 local tree = vim.treesitter.get_parser(0, 'c'):parse()[1] 172 _G.root = assert(tree:root()) 173 _G.main = assert(_G.root:child(0)) 174 _G.body = assert(_G.main:child(2)) 175 _G.statement = assert(_G.body:child(1)) 176 _G.declarator = assert(_G.statement:child(1)) 177 _G.value = assert(_G.declarator:child(1)) 178 end) 179 180 eq(lua_eval('main:type()'), lua_eval('root:child_with_descendant(value):type()')) 181 eq(lua_eval('body:type()'), lua_eval('main:child_with_descendant(value):type()')) 182 eq(lua_eval('statement:type()'), lua_eval('body:child_with_descendant(value):type()')) 183 eq(lua_eval('declarator:type()'), lua_eval('statement:child_with_descendant(value):type()')) 184 eq(lua_eval('value:type()'), lua_eval('declarator:child_with_descendant(value):type()')) 185 eq(vim.NIL, lua_eval('value:child_with_descendant(value)')) 186 end) 187 188 it('gets all children with a given field name', function() 189 insert([[ 190 function foo(a,b,c) 191 end 192 ]]) 193 194 exec_lua(function() 195 local tree = vim.treesitter.get_parser(0, 'lua'):parse()[1] 196 _G.parameters_node = assert(tree:root():named_descendant_for_range(0, 18, 0, 18)) 197 _G.children_by_field = _G.parameters_node:field('name') 198 end) 199 200 eq('parameters', lua_eval('parameters_node:type()')) 201 eq(3, lua_eval('#children_by_field')) 202 eq('a', lua_eval('vim.treesitter.get_node_text(children_by_field[1], 0)')) 203 eq('b', lua_eval('vim.treesitter.get_node_text(children_by_field[2], 0)')) 204 eq('c', lua_eval('vim.treesitter.get_node_text(children_by_field[3], 0)')) 205 end) 206 207 it('node access after tree edit', function() 208 insert([[ 209 function x() 210 return true 211 end 212 ]]) 213 exec_lua(function() 214 local tree = vim.treesitter.get_parser(0, 'lua'):parse()[1] 215 216 -- ensure treesitter does not try to edit the tree inplace 217 tree:copy() 218 219 local node = tree:root():child(0) 220 vim.api.nvim_buf_set_lines(0, 1, 2, false, {}) 221 vim.schedule(function() 222 collectgarbage() 223 local a, b, c, d = node:range() 224 _G.range = { a, b, c, d } 225 end) 226 end) 227 eq({ 0, 0, 2, 3 }, lua_eval('range')) 228 end) 229 230 it('tree:root() is idempotent', function() 231 insert([[ 232 function x() 233 return true 234 end 235 ]]) 236 exec_lua(function() 237 local tree = vim.treesitter.get_parser(0, 'lua'):parse()[1] 238 assert(tree:root() == tree:root()) 239 assert(tree:root() == tree:root():tree():root()) 240 end) 241 end) 242 end)