parser_spec.lua 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local clear = n.clear
  4. local dedent = t.dedent
  5. local eq = t.eq
  6. local insert = n.insert
  7. local exec_lua = n.exec_lua
  8. local pcall_err = t.pcall_err
  9. local feed = n.feed
  10. describe('treesitter parser API', function()
  11. before_each(function()
  12. clear()
  13. exec_lua(function()
  14. vim.g.__ts_debug = 1
  15. end)
  16. end)
  17. it('parses buffer', function()
  18. insert([[
  19. int main() {
  20. int x = 3;
  21. }]])
  22. exec_lua(function()
  23. _G.parser = vim.treesitter.get_parser(0, 'c')
  24. _G.tree = _G.parser:parse()[1]
  25. _G.root = _G.tree:root()
  26. _G.lang = vim.treesitter.language.inspect('c')
  27. end)
  28. eq('<tree>', exec_lua('return tostring(tree)'))
  29. eq('<node translation_unit>', exec_lua('return tostring(root)'))
  30. eq({ 0, 0, 3, 0 }, exec_lua('return {root:range()}'))
  31. eq(1, exec_lua('return root:child_count()'))
  32. exec_lua('child = root:child(0)')
  33. eq('<node function_definition>', exec_lua('return tostring(child)'))
  34. eq({ 0, 0, 2, 1 }, exec_lua('return {child:range()}'))
  35. eq('function_definition', exec_lua('return child:type()'))
  36. eq(true, exec_lua('return child:named()'))
  37. eq('number', type(exec_lua('return child:symbol()')))
  38. eq(true, exec_lua('return lang.symbols[child:type()]'))
  39. exec_lua('anon = root:descendant_for_range(0,8,0,9)')
  40. eq('(', exec_lua('return anon:type()'))
  41. eq(false, exec_lua('return anon:named()'))
  42. eq('number', type(exec_lua('return anon:symbol()')))
  43. eq(false, exec_lua([=[return lang.symbols[string.format('"%s"', anon:type())]]=]))
  44. exec_lua('descendant = root:descendant_for_range(1,2,1,12)')
  45. eq('<node declaration>', exec_lua('return tostring(descendant)'))
  46. eq({ 1, 2, 1, 12 }, exec_lua('return {descendant:range()}'))
  47. eq(
  48. '(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))',
  49. exec_lua('return descendant:sexpr()')
  50. )
  51. feed('2G7|ay')
  52. exec_lua(function()
  53. _G.tree2 = _G.parser:parse()[1]
  54. _G.root2 = _G.tree2:root()
  55. _G.descendant2 = _G.root2:descendant_for_range(1, 2, 1, 13)
  56. end)
  57. eq(false, exec_lua('return tree2 == tree1'))
  58. eq(false, exec_lua('return root2 == root'))
  59. eq('<node declaration>', exec_lua('return tostring(descendant2)'))
  60. eq({ 1, 2, 1, 13 }, exec_lua('return {descendant2:range()}'))
  61. eq(true, exec_lua('return child == child'))
  62. -- separate lua object, but represents same node
  63. eq(true, exec_lua('return child == root:child(0)'))
  64. eq(false, exec_lua('return child == descendant2'))
  65. eq(false, exec_lua('return child == nil'))
  66. eq(false, exec_lua('return child == tree'))
  67. eq('string', exec_lua('return type(child:id())'))
  68. eq(true, exec_lua('return child:id() == child:id()'))
  69. -- separate lua object, but represents same node
  70. eq(true, exec_lua('return child:id() == root:child(0):id()'))
  71. eq(false, exec_lua('return child:id() == descendant2:id()'))
  72. eq(false, exec_lua('return child:id() == nil'))
  73. eq(false, exec_lua('return child:id() == tree'))
  74. -- unchanged buffer: return the same tree
  75. eq(true, exec_lua('return parser:parse()[1] == tree2'))
  76. end)
  77. local test_text = [[
  78. void ui_refresh(void)
  79. {
  80. int width = INT_MAX, height = INT_MAX;
  81. bool ext_widgets[kUIExtCount];
  82. for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
  83. ext_widgets[i] = true;
  84. }
  85. bool inclusive = ui_override();
  86. for (size_t i = 0; i < ui_count; i++) {
  87. UI *ui = uis[i];
  88. width = MIN(ui->width, width);
  89. height = MIN(ui->height, height);
  90. foo = BAR(ui->bazaar, bazaar);
  91. for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
  92. ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
  93. }
  94. }
  95. }]]
  96. it('allows to iterate over nodes children', function()
  97. insert(test_text)
  98. local res = exec_lua(function()
  99. local parser = vim.treesitter.get_parser(0, 'c')
  100. local func_node = parser:parse()[1]:root():child(0)
  101. local res = {}
  102. for node, field in func_node:iter_children() do
  103. table.insert(res, { node:type(), field })
  104. end
  105. return res
  106. end)
  107. eq({
  108. { 'primitive_type', 'type' },
  109. { 'function_declarator', 'declarator' },
  110. { 'compound_statement', 'body' },
  111. }, res)
  112. end)
  113. it('does not get parser for empty filetype', function()
  114. insert(test_text)
  115. eq(
  116. '.../treesitter.lua:0: Parser not found for buffer 1: language could not be determined',
  117. pcall_err(exec_lua, 'vim.treesitter.get_parser(0)')
  118. )
  119. -- Must provide language for buffers with an empty filetype
  120. exec_lua("vim.treesitter.get_parser(0, 'c')")
  121. end)
  122. it('allows to get a child by field', function()
  123. insert(test_text)
  124. local res = exec_lua(function()
  125. local parser = vim.treesitter.get_parser(0, 'c')
  126. _G.func_node = parser:parse()[1]:root():child(0)
  127. local res = {}
  128. for _, node in ipairs(_G.func_node:field('type')) do
  129. table.insert(res, { node:type(), node:range() })
  130. end
  131. return res
  132. end)
  133. eq({ { 'primitive_type', 0, 0, 0, 4 } }, res)
  134. local res_fail = exec_lua(function()
  135. vim.treesitter.get_parser(0, 'c')
  136. return #_G.func_node:field('foo') == 0
  137. end)
  138. assert(res_fail)
  139. end)
  140. it('supports getting text of multiline node', function()
  141. insert(test_text)
  142. local res = exec_lua(function()
  143. local parser = vim.treesitter.get_parser(0, 'c')
  144. local tree = parser:parse()[1]
  145. return vim.treesitter.get_node_text(tree:root(), 0)
  146. end)
  147. eq(test_text, res)
  148. local res2 = exec_lua(function()
  149. local parser = vim.treesitter.get_parser(0, 'c')
  150. local root = parser:parse()[1]:root()
  151. return vim.treesitter.get_node_text(root:child(0):child(0), 0)
  152. end)
  153. eq('void', res2)
  154. end)
  155. it('supports getting text where start of node is one past EOF', function()
  156. local text = [[
  157. def run
  158. a = <<~E
  159. end]]
  160. insert(text)
  161. eq(
  162. '',
  163. exec_lua(function()
  164. local fake_node = {}
  165. function fake_node:start()
  166. return 3, 0, 23
  167. end
  168. function fake_node:end_()
  169. return 3, 0, 23
  170. end
  171. function fake_node:range(bytes)
  172. if bytes then
  173. return 3, 0, 23, 3, 0, 23
  174. end
  175. return 3, 0, 3, 0
  176. end
  177. return vim.treesitter.get_node_text(fake_node, 0)
  178. end)
  179. )
  180. end)
  181. it('supports getting empty text if node range is zero width', function()
  182. local text = [[
  183. ```lua
  184. {}
  185. ```]]
  186. insert(text)
  187. local result = exec_lua(function()
  188. local fake_node = {}
  189. function fake_node:start()
  190. return 1, 0, 7
  191. end
  192. function fake_node:end_()
  193. return 1, 0, 7
  194. end
  195. function fake_node:range()
  196. return 1, 0, 1, 0
  197. end
  198. return vim.treesitter.get_node_text(fake_node, 0) == ''
  199. end)
  200. eq(true, result)
  201. end)
  202. it('allows to set simple ranges', function()
  203. insert(test_text)
  204. local res = exec_lua(function()
  205. _G.parser = vim.treesitter.get_parser(0, 'c')
  206. return { _G.parser:parse()[1]:root():range() }
  207. end)
  208. eq({ 0, 0, 19, 0 }, res)
  209. -- The following sets the included ranges for the current parser
  210. -- As stated here, this only includes the function (thus the whole buffer, without the last line)
  211. local res2 = exec_lua(function()
  212. local root = _G.parser:parse()[1]:root()
  213. _G.parser:set_included_regions({ { root:child(0) } })
  214. _G.parser:invalidate()
  215. return { _G.parser:parse(true)[1]:root():range() }
  216. end)
  217. eq({ 0, 0, 18, 1 }, res2)
  218. eq({ { { 0, 0, 0, 18, 1, 512 } } }, exec_lua [[ return parser:included_regions() ]])
  219. local range_tbl = exec_lua(function()
  220. _G.parser:set_included_regions { { { 0, 0, 17, 1 } } }
  221. _G.parser:parse()
  222. return _G.parser:included_regions()
  223. end)
  224. eq({ { { 0, 0, 0, 17, 1, 508 } } }, range_tbl)
  225. end)
  226. it('allows to set complex ranges', function()
  227. insert(test_text)
  228. local res = exec_lua(function()
  229. local parser = vim.treesitter.get_parser(0, 'c')
  230. local query = vim.treesitter.query.parse('c', '(declaration) @decl')
  231. local nodes = {}
  232. for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
  233. table.insert(nodes, node)
  234. end
  235. parser:set_included_regions({ nodes })
  236. local root = parser:parse(true)[1]:root()
  237. local res = {}
  238. for i = 0, (root:named_child_count() - 1) do
  239. table.insert(res, { root:named_child(i):range() })
  240. end
  241. return res
  242. end)
  243. eq({
  244. { 2, 2, 2, 40 },
  245. { 3, 2, 3, 32 },
  246. { 4, 7, 4, 25 },
  247. { 8, 2, 8, 33 },
  248. { 9, 7, 9, 20 },
  249. { 10, 4, 10, 20 },
  250. { 14, 9, 14, 27 },
  251. }, res)
  252. end)
  253. it('allows to create string parsers', function()
  254. local ret = exec_lua(function()
  255. local parser = vim.treesitter.get_string_parser('int foo = 42;', 'c')
  256. return { parser:parse()[1]:root():range() }
  257. end)
  258. eq({ 0, 0, 0, 13 }, ret)
  259. end)
  260. it('allows to run queries with string parsers', function()
  261. local txt = [[
  262. int foo = 42;
  263. int bar = 13;
  264. ]]
  265. local ret = exec_lua(function(str)
  266. local parser = vim.treesitter.get_string_parser(str, 'c')
  267. local nodes = {}
  268. local query = vim.treesitter.query.parse('c', '((identifier) @id (#eq? @id "foo"))')
  269. for _, node in query:iter_captures(parser:parse()[1]:root(), str) do
  270. table.insert(nodes, { node:range() })
  271. end
  272. return nodes
  273. end, txt)
  274. eq({ { 0, 10, 0, 13 } }, ret)
  275. end)
  276. describe('when creating a language tree', function()
  277. local function get_ranges()
  278. return exec_lua(function()
  279. local result = {}
  280. _G.parser:for_each_tree(function(tree)
  281. table.insert(result, { tree:root():range() })
  282. end)
  283. return result
  284. end)
  285. end
  286. before_each(function()
  287. insert([[
  288. int x = INT_MAX;
  289. #define READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  290. #define READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  291. #define VALUE 123
  292. #define VALUE1 123
  293. #define VALUE2 123
  294. ]])
  295. end)
  296. describe('when parsing regions independently', function()
  297. it('should inject a language', function()
  298. exec_lua(function()
  299. _G.parser = vim.treesitter.get_parser(0, 'c', {
  300. injections = {
  301. c = (
  302. '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) '
  303. .. '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'
  304. ),
  305. },
  306. })
  307. _G.parser:parse(true)
  308. end)
  309. eq('table', exec_lua('return type(parser:children().c)'))
  310. eq(5, exec_lua('return #parser:children().c:trees()'))
  311. eq({
  312. { 0, 0, 7, 0 }, -- root tree
  313. { 3, 14, 3, 17 }, -- VALUE 123
  314. { 4, 15, 4, 18 }, -- VALUE1 123
  315. { 5, 15, 5, 18 }, -- VALUE2 123
  316. { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  317. { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  318. }, get_ranges())
  319. n.feed('ggo<esc>')
  320. eq(5, exec_lua('return #parser:children().c:trees()'))
  321. eq({
  322. { 0, 0, 8, 0 }, -- root tree
  323. { 4, 14, 4, 17 }, -- VALUE 123
  324. { 5, 15, 5, 18 }, -- VALUE1 123
  325. { 6, 15, 6, 18 }, -- VALUE2 123
  326. { 2, 26, 2, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  327. { 3, 29, 3, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  328. }, get_ranges())
  329. end)
  330. end)
  331. describe('when parsing regions combined', function()
  332. it('should inject a language', function()
  333. exec_lua(function()
  334. _G.parser = vim.treesitter.get_parser(0, 'c', {
  335. injections = {
  336. c = (
  337. '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined)) '
  338. .. '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined))'
  339. ),
  340. },
  341. })
  342. _G.parser:parse(true)
  343. end)
  344. eq('table', exec_lua('return type(parser:children().c)'))
  345. eq(2, exec_lua('return #parser:children().c:trees()'))
  346. eq({
  347. { 0, 0, 7, 0 }, -- root tree
  348. { 3, 14, 5, 18 }, -- VALUE 123
  349. -- VALUE1 123
  350. -- VALUE2 123
  351. { 1, 26, 2, 66 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  352. -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  353. }, get_ranges())
  354. n.feed('ggo<esc>')
  355. eq('table', exec_lua('return type(parser:children().c)'))
  356. eq(2, exec_lua('return #parser:children().c:trees()'))
  357. eq({
  358. { 0, 0, 8, 0 }, -- root tree
  359. { 4, 14, 6, 18 }, -- VALUE 123
  360. -- VALUE1 123
  361. -- VALUE2 123
  362. { 2, 26, 3, 66 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  363. -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  364. }, get_ranges())
  365. n.feed('7ggI//<esc>')
  366. exec_lua([[parser:parse({6, 7})]])
  367. eq('table', exec_lua('return type(parser:children().c)'))
  368. eq(2, exec_lua('return #parser:children().c:trees()'))
  369. eq({
  370. { 0, 0, 8, 0 }, -- root tree
  371. { 4, 14, 5, 18 }, -- VALUE 123
  372. -- VALUE1 123
  373. { 2, 26, 3, 66 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  374. -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  375. }, get_ranges())
  376. end)
  377. end)
  378. describe('when using injection.self', function()
  379. it('should inject the source language', function()
  380. exec_lua(function()
  381. _G.parser = vim.treesitter.get_parser(0, 'c', {
  382. injections = {
  383. c = (
  384. '(preproc_def (preproc_arg) @injection.content (#set! injection.self)) '
  385. .. '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.self))'
  386. ),
  387. },
  388. })
  389. _G.parser:parse(true)
  390. end)
  391. eq('table', exec_lua('return type(parser:children().c)'))
  392. eq(5, exec_lua('return #parser:children().c:trees()'))
  393. eq({
  394. { 0, 0, 7, 0 }, -- root tree
  395. { 3, 14, 3, 17 }, -- VALUE 123
  396. { 4, 15, 4, 18 }, -- VALUE1 123
  397. { 5, 15, 5, 18 }, -- VALUE2 123
  398. { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  399. { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  400. }, get_ranges())
  401. n.feed('ggo<esc>')
  402. eq(5, exec_lua('return #parser:children().c:trees()'))
  403. eq({
  404. { 0, 0, 8, 0 }, -- root tree
  405. { 4, 14, 4, 17 }, -- VALUE 123
  406. { 5, 15, 5, 18 }, -- VALUE1 123
  407. { 6, 15, 6, 18 }, -- VALUE2 123
  408. { 2, 26, 2, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  409. { 3, 29, 3, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  410. }, get_ranges())
  411. end)
  412. end)
  413. describe('when using the offset directive', function()
  414. it('should shift the range by the directive amount', function()
  415. exec_lua(function()
  416. _G.parser = vim.treesitter.get_parser(0, 'c', {
  417. injections = {
  418. c = (
  419. '(preproc_def ((preproc_arg) @injection.content (#set! injection.language "c") (#offset! @injection.content 0 2 0 -1))) '
  420. .. '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'
  421. ),
  422. },
  423. })
  424. _G.parser:parse(true)
  425. end)
  426. eq('table', exec_lua('return type(parser:children().c)'))
  427. eq({
  428. { 0, 0, 7, 0 }, -- root tree
  429. { 3, 16, 3, 16 }, -- VALUE 123
  430. { 4, 17, 4, 17 }, -- VALUE1 123
  431. { 5, 17, 5, 17 }, -- VALUE2 123
  432. { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
  433. { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
  434. }, get_ranges())
  435. end)
  436. it('should list all directives', function()
  437. local res_list = exec_lua(function()
  438. local query = vim.treesitter.query
  439. local list = query.list_directives()
  440. table.sort(list)
  441. return list
  442. end)
  443. eq({ 'gsub!', 'offset!', 'set!', 'trim!' }, res_list)
  444. end)
  445. end)
  446. end)
  447. describe('when getting the language for a range', function()
  448. before_each(function()
  449. insert([[
  450. int x = INT_MAX;
  451. #define VALUE 123456789
  452. ]])
  453. end)
  454. it('should return the correct language tree', function()
  455. local result = exec_lua(function()
  456. local parser = vim.treesitter.get_parser(0, 'c', {
  457. injections = {
  458. c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))',
  459. },
  460. })
  461. parser:parse(true)
  462. local sub_tree = parser:language_for_range({ 1, 18, 1, 19 })
  463. return sub_tree == parser:children().c
  464. end)
  465. eq(true, result)
  466. end)
  467. end)
  468. describe('when setting the node for an injection', function()
  469. before_each(function()
  470. insert([[
  471. print()
  472. ]])
  473. end)
  474. it('ignores optional captures #23100', function()
  475. local result = exec_lua(function()
  476. local parser = vim.treesitter.get_parser(0, 'lua', {
  477. injections = {
  478. lua = (
  479. '(function_call '
  480. .. '(arguments '
  481. .. '(string)? @injection.content '
  482. .. '(number)? @injection.content '
  483. .. '(#offset! @injection.content 0 1 0 -1) '
  484. .. '(#set! injection.language "c")))'
  485. ),
  486. },
  487. })
  488. parser:parse(true)
  489. return parser:is_valid()
  490. end)
  491. eq(true, result)
  492. end)
  493. end)
  494. describe('when getting/setting match data', function()
  495. describe('when setting for the whole match', function()
  496. it('should set/get the data correctly', function()
  497. insert([[
  498. int x = 3;
  499. ]])
  500. local result = exec_lua(function()
  501. local query =
  502. vim.treesitter.query.parse('c', '((number_literal) @number (#set! "key" "value"))')
  503. local parser = vim.treesitter.get_parser(0, 'c')
  504. local _, _, metadata = query:iter_matches(parser:parse()[1]:root(), 0, 0, -1)()
  505. return metadata.key
  506. end)
  507. eq('value', result)
  508. end)
  509. describe('when setting a key on a capture', function()
  510. it('it should create the nested table', function()
  511. insert([[
  512. int x = 3;
  513. ]])
  514. local result = exec_lua(function()
  515. local query = vim.treesitter.query.parse(
  516. 'c',
  517. '((number_literal) @number (#set! @number "key" "value"))'
  518. )
  519. local parser = vim.treesitter.get_parser(0, 'c')
  520. local _, _, metadata = query:iter_matches(parser:parse()[1]:root(), 0, 0, -1)()
  521. local _, nested_tbl = next(metadata)
  522. return nested_tbl.key
  523. end)
  524. eq('value', result)
  525. end)
  526. it('it should not overwrite the nested table', function()
  527. insert([[
  528. int x = 3;
  529. ]])
  530. local result = exec_lua(function()
  531. local query = vim.treesitter.query.parse(
  532. 'c',
  533. '((number_literal) @number (#set! @number "key" "value") (#set! @number "key2" "value2"))'
  534. )
  535. local parser = vim.treesitter.get_parser(0, 'c')
  536. local _, _, metadata = query:iter_matches(parser:parse()[1]:root(), 0, 0, -1)()
  537. local _, nested_tbl = next(metadata)
  538. return nested_tbl
  539. end)
  540. local expected = {
  541. ['key'] = 'value',
  542. ['key2'] = 'value2',
  543. }
  544. eq(expected, result)
  545. end)
  546. end)
  547. end)
  548. end)
  549. it('tracks the root range properly (#22911)', function()
  550. insert([[
  551. int main() {
  552. int x = 3;
  553. }]])
  554. local query0 = [[
  555. (declaration) @declaration
  556. (function_definition) @function
  557. ]]
  558. exec_lua(function()
  559. vim.treesitter.start(0, 'c')
  560. end)
  561. local function run_query()
  562. return exec_lua(function()
  563. local query = vim.treesitter.query.parse('c', query0)
  564. local parser = vim.treesitter.get_parser()
  565. local tree = parser:parse()[1]
  566. local res = {}
  567. for id, node in query:iter_captures(tree:root()) do
  568. table.insert(res, { query.captures[id], node:range() })
  569. end
  570. return res
  571. end)
  572. end
  573. eq({
  574. { 'function', 0, 0, 2, 1 },
  575. { 'declaration', 1, 2, 1, 12 },
  576. }, run_query())
  577. n.command 'normal ggO'
  578. insert('int a;')
  579. eq({
  580. { 'declaration', 0, 0, 0, 6 },
  581. { 'function', 1, 0, 3, 1 },
  582. { 'declaration', 2, 2, 2, 12 },
  583. }, run_query())
  584. end)
  585. it('handles ranges when source is a multiline string (#20419)', function()
  586. local source = [==[
  587. vim.cmd[[
  588. set number
  589. set cmdheight=2
  590. set lastsatus=2
  591. ]]
  592. set query = [[;; query
  593. ((function_call
  594. name: [
  595. (identifier) @_cdef_identifier
  596. (_ _ (identifier) @_cdef_identifier)
  597. ]
  598. arguments: (arguments (string content: _ @injection.content)))
  599. (#set! injection.language "c")
  600. (#eq? @_cdef_identifier "cdef"))
  601. ]]
  602. ]==]
  603. local r = exec_lua(function()
  604. local parser = vim.treesitter.get_string_parser(source, 'lua')
  605. parser:parse(true)
  606. local ranges = {}
  607. parser:for_each_tree(function(tstree, tree)
  608. ranges[tree:lang()] = { tstree:root():range(true) }
  609. end)
  610. return ranges
  611. end)
  612. eq({
  613. lua = { 0, 6, 6, 16, 4, 438 },
  614. query = { 6, 20, 113, 15, 6, 431 },
  615. vim = { 1, 0, 16, 4, 6, 89 },
  616. }, r)
  617. -- The above ranges are provided directly from treesitter, however query directives may mutate
  618. -- the ranges but only provide a Range4. Strip the byte entries from the ranges and make sure
  619. -- add_bytes() produces the same result.
  620. local rb = exec_lua(function()
  621. local add_bytes = require('vim.treesitter._range').add_bytes
  622. for lang, range in pairs(r) do
  623. r[lang] = { range[1], range[2], range[4], range[5] }
  624. r[lang] = add_bytes(source, r[lang])
  625. end
  626. return r
  627. end)
  628. eq(rb, r)
  629. end)
  630. it('does not produce empty injection ranges (#23409)', function()
  631. insert [[
  632. Examples: >lua
  633. local a = {}
  634. <
  635. ]]
  636. -- This is not a valid injection since (code) has children and include-children is not set
  637. exec_lua(function()
  638. _G.parser1 = require('vim.treesitter.languagetree').new(0, 'vimdoc', {
  639. injections = {
  640. vimdoc = '((codeblock (language) @injection.language (code) @injection.content))',
  641. },
  642. })
  643. _G.parser1:parse(true)
  644. end)
  645. eq(0, exec_lua('return #vim.tbl_keys(parser1:children())'))
  646. exec_lua(function()
  647. _G.parser2 = require('vim.treesitter.languagetree').new(0, 'vimdoc', {
  648. injections = {
  649. vimdoc = '((codeblock (language) @injection.language (code) @injection.content) (#set! injection.include-children))',
  650. },
  651. })
  652. _G.parser2:parse(true)
  653. end)
  654. eq(1, exec_lua('return #vim.tbl_keys(parser2:children())'))
  655. eq({ { { 1, 0, 21, 2, 0, 42 } } }, exec_lua('return parser2:children().lua:included_regions()'))
  656. end)
  657. it('parsers injections incrementally', function()
  658. insert(dedent [[
  659. >lua
  660. local a = {}
  661. <
  662. >lua
  663. local b = {}
  664. <
  665. >lua
  666. local c = {}
  667. <
  668. >lua
  669. local d = {}
  670. <
  671. >lua
  672. local e = {}
  673. <
  674. >lua
  675. local f = {}
  676. <
  677. >lua
  678. local g = {}
  679. <
  680. ]])
  681. exec_lua(function()
  682. _G.parser = require('vim.treesitter.languagetree').new(0, 'vimdoc', {
  683. injections = {
  684. vimdoc = '((codeblock (language) @injection.language (code) @injection.content) (#set! injection.include-children))',
  685. },
  686. })
  687. end)
  688. --- Do not parse injections by default
  689. eq(
  690. 0,
  691. exec_lua(function()
  692. _G.parser:parse()
  693. return #vim.tbl_keys(_G.parser:children())
  694. end)
  695. )
  696. --- Only parse injections between lines 0, 2
  697. eq(
  698. 1,
  699. exec_lua(function()
  700. _G.parser:parse({ 0, 2 })
  701. return #_G.parser:children().lua:trees()
  702. end)
  703. )
  704. eq(
  705. 2,
  706. exec_lua(function()
  707. _G.parser:parse({ 2, 6 })
  708. return #_G.parser:children().lua:trees()
  709. end)
  710. )
  711. eq(
  712. 7,
  713. exec_lua(function()
  714. _G.parser:parse(true)
  715. return #_G.parser:children().lua:trees()
  716. end)
  717. )
  718. end)
  719. describe('languagetree is_valid()', function()
  720. before_each(function()
  721. insert(dedent [[
  722. Treesitter integration *treesitter*
  723. Nvim integrates the `tree-sitter` library for incremental parsing of buffers:
  724. https://tree-sitter.github.io/tree-sitter/
  725. ]])
  726. feed(':set ft=help<cr>')
  727. exec_lua(function()
  728. vim.treesitter.get_parser(0, 'vimdoc', {
  729. injections = {
  730. vimdoc = '((codeblock (language) @injection.language (code) @injection.content) (#set! injection.include-children))',
  731. },
  732. })
  733. end)
  734. end)
  735. it('is valid excluding, invalid including children initially', function()
  736. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  737. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  738. end)
  739. it('is fully valid after a full parse', function()
  740. exec_lua('vim.treesitter.get_parser():parse(true)')
  741. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  742. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  743. end)
  744. it('is fully valid after a parsing a range on parsed tree', function()
  745. exec_lua('vim.treesitter.get_parser():parse({5, 7})')
  746. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  747. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  748. end)
  749. describe('when adding content with injections', function()
  750. before_each(function()
  751. feed('G')
  752. insert(dedent [[
  753. >lua
  754. local a = {}
  755. <
  756. ]])
  757. end)
  758. it('is fully invalid after changes', function()
  759. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  760. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  761. end)
  762. it('is valid excluding, invalid including children after a rangeless parse', function()
  763. exec_lua('vim.treesitter.get_parser():parse()')
  764. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  765. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  766. end)
  767. it(
  768. 'is fully valid after a range parse that leads to parsing not parsed injections',
  769. function()
  770. exec_lua('vim.treesitter.get_parser():parse({5, 7})')
  771. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  772. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  773. end
  774. )
  775. it(
  776. 'is valid excluding, invalid including children after a range parse that does not lead to parsing not parsed injections',
  777. function()
  778. exec_lua('vim.treesitter.get_parser():parse({2, 4})')
  779. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  780. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  781. end
  782. )
  783. end)
  784. describe('when removing content with injections', function()
  785. before_each(function()
  786. feed('G')
  787. insert(dedent [[
  788. >lua
  789. local a = {}
  790. <
  791. >lua
  792. local a = {}
  793. <
  794. ]])
  795. exec_lua('vim.treesitter.get_parser():parse(true)')
  796. feed('Gd3k')
  797. end)
  798. it('is fully invalid after changes', function()
  799. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  800. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  801. end)
  802. it('is valid excluding, invalid including children after a rangeless parse', function()
  803. exec_lua('vim.treesitter.get_parser():parse()')
  804. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  805. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  806. end)
  807. it('is fully valid after a range parse that leads to parsing modified child tree', function()
  808. exec_lua('vim.treesitter.get_parser():parse({5, 7})')
  809. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  810. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  811. end)
  812. it(
  813. 'is valid excluding, invalid including children after a range parse that does not lead to parsing modified child tree',
  814. function()
  815. exec_lua('vim.treesitter.get_parser():parse({2, 4})')
  816. eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
  817. eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
  818. end
  819. )
  820. end)
  821. end)
  822. end)