language_spec.lua 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local clear = n.clear
  4. local eq = t.eq
  5. local command = n.command
  6. local exec_lua = n.exec_lua
  7. local pcall_err = t.pcall_err
  8. local matches = t.matches
  9. local insert = n.insert
  10. local NIL = vim.NIL
  11. before_each(clear)
  12. describe('treesitter language API', function()
  13. -- error tests not requiring a parser library
  14. it('handles missing language', function()
  15. eq(
  16. '.../treesitter.lua:0: Parser could not be created for buffer 1 and language "borklang"',
  17. pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')")
  18. )
  19. eq(NIL, exec_lua("return vim.treesitter.get_parser(0, 'borklang', { error = false })"))
  20. -- actual message depends on platform
  21. matches(
  22. "Failed to load parser for language 'borklang': uv_dlopen: .+",
  23. pcall_err(
  24. exec_lua,
  25. "parser = vim.treesitter.language.add('borklang', { path = 'borkbork.so' })"
  26. )
  27. )
  28. eq(NIL, exec_lua("return vim.treesitter.language.add('borklang')"))
  29. eq(
  30. false,
  31. exec_lua("return pcall(vim.treesitter.language.add, 'borklang', { path = 'borkbork.so' })")
  32. )
  33. matches(
  34. 'Failed to load parser: uv_dlsym: .+',
  35. pcall_err(exec_lua, 'vim.treesitter.language.add("c", { symbol_name = "borklang" })')
  36. )
  37. end)
  38. it('does not load parser for invalid language name', function()
  39. eq(NIL, exec_lua('vim.treesitter.language.add("/foo/")'))
  40. end)
  41. it('inspects language', function()
  42. local keys, fields, symbols = unpack(exec_lua(function()
  43. local lang = vim.treesitter.language.inspect('c')
  44. local keys = {}
  45. for k, v in pairs(lang) do
  46. if type(v) == 'boolean' then
  47. keys[k] = v
  48. else
  49. keys[k] = true
  50. end
  51. end
  52. return { keys, lang.fields, lang.symbols }
  53. end))
  54. eq({ fields = true, symbols = true, _abi_version = true, _wasm = false }, keys)
  55. local fset = {}
  56. for _, f in pairs(fields) do
  57. eq('string', type(f))
  58. fset[f] = true
  59. end
  60. eq(true, fset['directive'])
  61. eq(true, fset['initializer'])
  62. local has_named, has_anonymous, has_supertype
  63. for symbol, named in pairs(symbols) do
  64. eq('string', type(symbol))
  65. eq('boolean', type(named))
  66. if symbol == 'for_statement' and named == true then
  67. has_named = true
  68. elseif symbol == '"|="' and named == false then
  69. has_anonymous = true
  70. elseif symbol == 'statement' and named == true then
  71. has_supertype = true
  72. end
  73. end
  74. eq(
  75. { has_named = true, has_anonymous = true, has_supertype = true },
  76. { has_named = has_named, has_anonymous = has_anonymous, has_supertype = has_supertype }
  77. )
  78. end)
  79. it(
  80. 'checks if vim.treesitter.get_parser tries to create a new parser on filetype change',
  81. function()
  82. command('set filetype=c')
  83. -- Should not throw an error when filetype is c
  84. eq('c', exec_lua('return vim.treesitter.get_parser(0):lang()'))
  85. command('set filetype=borklang')
  86. -- Should throw an error when filetype changes to borklang
  87. eq(
  88. '.../treesitter.lua:0: Parser could not be created for buffer 1 and language "borklang"',
  89. pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0, 'borklang')")
  90. )
  91. eq(NIL, exec_lua("return vim.treesitter.get_parser(0, 'borklang', { error = false })"))
  92. end
  93. )
  94. it('retrieve the tree given a range', function()
  95. insert([[
  96. int main() {
  97. int x = 3;
  98. }]])
  99. eq(
  100. '<node translation_unit>',
  101. exec_lua(function()
  102. local langtree = vim.treesitter.get_parser(0, 'c')
  103. local tree = langtree:tree_for_range({ 1, 3, 1, 3 })
  104. return tostring(tree:root())
  105. end)
  106. )
  107. end)
  108. it('retrieve the tree given a range when range is out of bounds relative to buffer', function()
  109. insert([[
  110. int main() {
  111. int x = 3;
  112. }]])
  113. eq(
  114. '<node translation_unit>',
  115. exec_lua(function()
  116. local langtree = vim.treesitter.get_parser(0, 'c')
  117. local tree = langtree:tree_for_range({ 10, 10, 10, 10 })
  118. return tostring(tree:root())
  119. end)
  120. )
  121. end)
  122. it('retrieve the node given a range', function()
  123. insert([[
  124. int main() {
  125. int x = 3;
  126. }]])
  127. eq(
  128. '<node primitive_type>',
  129. exec_lua(function()
  130. local langtree = vim.treesitter.get_parser(0, 'c')
  131. local node = langtree:named_node_for_range({ 1, 3, 1, 3 })
  132. return tostring(node)
  133. end)
  134. )
  135. end)
  136. it('retrieve an anonymous node given a range', function()
  137. insert([[vim.fn.input()]])
  138. exec_lua(function()
  139. _G.langtree = vim.treesitter.get_parser(0, 'lua')
  140. _G.node = _G.langtree:node_for_range({ 0, 3, 0, 3 })
  141. end)
  142. eq('.', exec_lua('return node:type()'))
  143. end)
  144. end)