mirror of
https://github.com/nvim-treesitter/nvim-treesitter-context
synced 2024-09-08 02:25:41 +02:00
test: add generic testing framework
This commit is contained in:
parent
02eefe50e0
commit
1ac390aded
7 changed files with 397 additions and 206 deletions
|
@ -41,5 +41,21 @@ if-statement spans multiple lines.
|
|||
A pull request for supporting a new language requires:
|
||||
|
||||
1. Adding `queries/[LANG]/context.scm` as explained in the previous section.
|
||||
2. Adding `test/test.[LANG EXT]` with code examples the `context.scm` is designed to support.
|
||||
|
||||
2. Adding `test/lang/test.[LANG]` or `test/lang/test.[LANG].[EXT]` with code examples the `context.scm` is designed to support.
|
||||
- These test files use custom comment directives to annotate what lines should be a context. It has the format.
|
||||
|
||||
```c
|
||||
// {{TEST}} -- mark start of test
|
||||
|
||||
int main() { // {{CONTEXT}} -- mark line as a context
|
||||
|
||||
|
||||
// {{CURSOR}} -- where cursor needs to be for contexts to be shown.
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
See `test/lang/test.c` for examples.
|
||||
|
||||
3. Updating `README.md` to mark `[LANG]` as supported.
|
||||
|
|
|
@ -1,96 +1,79 @@
|
|||
#!/bin/bash
|
||||
foo() {
|
||||
|
||||
if [ 1 -eq 1 ]; then
|
||||
# {{TEST}}
|
||||
|
||||
foo() { # {{CONTEXT}}
|
||||
|
||||
if [ 1 -eq 1 ]; then # {{CONTEXT}}
|
||||
echo 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# {{CURSOR}}
|
||||
fi
|
||||
|
||||
case "$i" in
|
||||
1) echo 1
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
# {{TEST}}
|
||||
|
||||
bar() { # {{CONTEXT}}
|
||||
case "$i" in # {{CONTEXT}}
|
||||
1) echo 1 # {{CONTEXT}}
|
||||
|
||||
|
||||
|
||||
# {{CURSOR}}
|
||||
;;
|
||||
2|3) echo 2 or 3
|
||||
;;
|
||||
*) echo default
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
while [ $x -le 5 ]
|
||||
do
|
||||
echo "Welcome $x times"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
x=$(( $x + 1 ))
|
||||
done
|
||||
|
||||
# until is also a while loop
|
||||
until [ $x -gt 5 ]
|
||||
do
|
||||
echo Counter: $x
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
((x++))
|
||||
done
|
||||
|
||||
# select is a for statement
|
||||
select character in Sheldon Leonard Penny Howard Raj
|
||||
do
|
||||
echo "Selected character: $character"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
echo "Selected number: $REPLY"
|
||||
done
|
||||
|
||||
for ((i=0; i<=10000; i++)); do
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
# {{TEST}}
|
||||
|
||||
baz() { # {{CONTEXT}}
|
||||
while [ $x -le 5 ] # {{CONTEXT}}
|
||||
do
|
||||
echo "Welcome $x times"
|
||||
|
||||
x=$(( $x + 1 ))
|
||||
# {{CURSOR}}
|
||||
done
|
||||
}
|
||||
|
||||
# {{TEST}}
|
||||
|
||||
baz2() { # {{CONTEXT}}
|
||||
# until is also a while loop
|
||||
until [ $x -gt 5 ] # {{CONTEXT}}
|
||||
do
|
||||
echo Counter: $x
|
||||
((x++))
|
||||
# {{CURSOR}}
|
||||
done
|
||||
}
|
||||
|
||||
# {{TEST}}
|
||||
|
||||
# select is a for statement
|
||||
select character in Sheldon Leonard Penny Howard Raj # {{CONTEXT}}
|
||||
do
|
||||
echo "Selected character: $character"
|
||||
|
||||
# {{CURSOR}}
|
||||
done
|
||||
|
||||
# {{POPCONTEXT}}
|
||||
|
||||
for ((i=0; i<=10000; i++)); do # {{CONTEXT}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# {{CURSOR}}
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
|
||||
|
|
188
test/lang/test.c
188
test/lang/test.c
|
@ -1,148 +1,90 @@
|
|||
struct Bert {
|
||||
// {{TEST}}
|
||||
|
||||
struct Bert { // {{CONTEXT}}
|
||||
int *f1;
|
||||
// comment
|
||||
int *f2;
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
|
||||
// {{CURSOR}}
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
||||
// {{TEST}}
|
||||
|
||||
typedef enum { // {{CONTEXT}}
|
||||
E1,
|
||||
E2,
|
||||
E3
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// {{CURSOR}}
|
||||
} Myenum;
|
||||
|
||||
int main(int arg1,
|
||||
|
||||
// {{TEST}}
|
||||
|
||||
int main(int arg1, // {{CONTEXT}}
|
||||
char **arg2,
|
||||
char **arg3
|
||||
)
|
||||
char **arg3)
|
||||
{
|
||||
|
||||
if (arg1 == 4
|
||||
if (arg1 == 4 // {{CONTEXT}}
|
||||
&& arg2 == arg3) {
|
||||
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
for (int i = 0; i < arg1; i++) {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
while (1) {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// {{CURSOR}}
|
||||
|
||||
for (int i = 0; i < arg1; i++) { // {{CONTEXT}}
|
||||
|
||||
// {{CURSOR}}
|
||||
while (1) { // {{CONTEXT}}
|
||||
|
||||
|
||||
// {{CURSOR}}
|
||||
}
|
||||
|
||||
do {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
|
||||
} while (1);
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
}
|
||||
|
||||
} else if (arg1 == 4) {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
|
||||
} else {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
switch (arg1) {
|
||||
// comment
|
||||
|
||||
// {{TEST}}
|
||||
|
||||
void foo(int a) { // {{CONTEXT}}
|
||||
if (a) { // {{CONTEXT}}
|
||||
do { // {{CONTEXT}}
|
||||
|
||||
|
||||
|
||||
// {{CURSOR}}
|
||||
} while (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// {{TEST}}
|
||||
|
||||
void bar(int a) { // {{CONTEXT}}
|
||||
if (a) { // {{CONTEXT}}
|
||||
|
||||
} else if (a == 4) { // {{CONTEXT}}
|
||||
// comment
|
||||
} else { // {{CONTEXT}}
|
||||
|
||||
|
||||
|
||||
// {{CURSOR}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// {{TEST}}
|
||||
|
||||
void baz(int a) { // {{CONTEXT}}
|
||||
switch (a) { // {{CONTEXT}}
|
||||
case 0:
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
break;
|
||||
case 1: {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
case 1: { // {{CONTEXT}}
|
||||
|
||||
|
||||
|
||||
// {{CURSOR}}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
13
test/lang/test.lua
Normal file
13
test/lang/test.lua
Normal file
|
@ -0,0 +1,13 @@
|
|||
-- {{TEST}}
|
||||
|
||||
local function foo() -- {{CONTEXT}}
|
||||
|
||||
local function bar() -- {{CONTEXT}}
|
||||
|
||||
|
||||
|
||||
-- {{CURSOR}}
|
||||
|
||||
end
|
||||
|
||||
end
|
148
test/test.c
Normal file
148
test/test.c
Normal file
|
@ -0,0 +1,148 @@
|
|||
struct Bert {
|
||||
int *f1;
|
||||
// comment
|
||||
int *f2;
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
E1,
|
||||
E2,
|
||||
E3
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
} Myenum;
|
||||
|
||||
int main(int arg1,
|
||||
char **arg2,
|
||||
char **arg3
|
||||
)
|
||||
{
|
||||
|
||||
if (arg1 == 4
|
||||
&& arg2 == arg3) {
|
||||
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
for (int i = 0; i < arg1; i++) {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
while (1) {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
}
|
||||
|
||||
do {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
|
||||
} while (1);
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
}
|
||||
|
||||
} else if (arg1 == 4) {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
|
||||
} else {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
|
||||
}
|
||||
|
||||
switch (arg1) {
|
||||
// comment
|
||||
// comment
|
||||
case 0:
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
break;
|
||||
case 1: {
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
// comment
|
||||
} break;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ local clear = helpers.clear
|
|||
local exec_lua = helpers.exec_lua
|
||||
local cmd = helpers.api.nvim_command
|
||||
local feed = helpers.feed
|
||||
local api = helpers.api
|
||||
|
||||
local function install_langs(langs)
|
||||
if type(langs) == 'string' then
|
||||
|
@ -22,7 +23,52 @@ local function install_langs(langs)
|
|||
]], langs)
|
||||
end
|
||||
|
||||
local function get_langs()
|
||||
---@param line string
|
||||
---@return string?
|
||||
local function parse_directive(line)
|
||||
--- @type string?
|
||||
local directive = line:match('{{([A-Z]+)}}')
|
||||
return directive
|
||||
end
|
||||
|
||||
--- @param filename string
|
||||
--- @return table<integer, integer[]>? contexts
|
||||
local function parse_directives(filename)
|
||||
local f = io.open(filename, 'r')
|
||||
if not f then
|
||||
return
|
||||
end
|
||||
|
||||
local context = {} --- @type table<integer,integer[]>
|
||||
local contexts = {} --- @type table<integer,integer[]>
|
||||
|
||||
local i = 0
|
||||
for l in f:lines() do
|
||||
local directive = parse_directive(l)
|
||||
if directive then
|
||||
if directive == 'TEST' then
|
||||
context = {}
|
||||
elseif directive == 'CURSOR' then
|
||||
contexts[i] = vim.deepcopy(context)
|
||||
elseif directive == 'CONTEXT' then
|
||||
table.insert(context, i)
|
||||
elseif directive == 'POPCONTEXT' then
|
||||
table.remove(context, #context)
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
f:close()
|
||||
|
||||
for _, c in pairs(contexts) do
|
||||
table.sort(c)
|
||||
end
|
||||
|
||||
return contexts
|
||||
end
|
||||
|
||||
local langs = {} --- @type string[]
|
||||
do
|
||||
local f = assert(io.open('README.md', 'r'))
|
||||
local readme_langs = {} --- @type table<string,true>
|
||||
for l in f:lines() do
|
||||
|
@ -35,18 +81,16 @@ local function get_langs()
|
|||
f:close()
|
||||
|
||||
f = assert(io.open('nvim-treesitter/lockfile.json', 'r'))
|
||||
local txt = f:read('*a')
|
||||
local j = vim.json.decode(txt)
|
||||
|
||||
local langs = {} --- @type string[]
|
||||
for k in pairs(j) do
|
||||
for k in pairs(vim.json.decode(f:read('*a'))) do
|
||||
if readme_langs[k] then
|
||||
langs[#langs+1] = k
|
||||
readme_langs[k] = nil
|
||||
end
|
||||
end
|
||||
print('Invalid languages:', table.concat(vim.tbl_keys(readme_langs), ', '))
|
||||
return langs
|
||||
if next(readme_langs) then
|
||||
print('Invalid languages:', table.concat(vim.tbl_keys(readme_langs), ', '))
|
||||
end
|
||||
end
|
||||
|
||||
describe('ts_context', function()
|
||||
|
@ -91,7 +135,7 @@ describe('ts_context', function()
|
|||
it('edit a file', function()
|
||||
install_langs('lua')
|
||||
exec_lua[[require'treesitter-context'.setup{}]]
|
||||
cmd('edit test/lang/test_file.lua')
|
||||
cmd('edit test/test_file.lua')
|
||||
exec_lua [[vim.treesitter.start()]]
|
||||
feed'<C-e>'
|
||||
feed'jj'
|
||||
|
@ -141,7 +185,7 @@ describe('ts_context', function()
|
|||
f:close()
|
||||
end)
|
||||
|
||||
for _, lang in ipairs(get_langs()) do
|
||||
for _, lang in ipairs(langs) do
|
||||
it(lang, function()
|
||||
install_langs(lang)
|
||||
|
||||
|
@ -182,6 +226,51 @@ describe('ts_context', function()
|
|||
|
||||
end)
|
||||
|
||||
describe('contexts:', function()
|
||||
for _, lang in ipairs(langs) do
|
||||
it(lang, function()
|
||||
install_langs(lang)
|
||||
|
||||
local test_file = 'test/lang/test.'..lang
|
||||
if not vim.uv.fs_stat(test_file) then
|
||||
pending('No test file')
|
||||
return
|
||||
end
|
||||
|
||||
local contexts = parse_directives(test_file)
|
||||
|
||||
if not contexts or not next(contexts) then
|
||||
pending('No tests')
|
||||
return
|
||||
end
|
||||
|
||||
cmd('edit '..test_file)
|
||||
|
||||
for cursor_row, context_rows in pairs(contexts) do
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
local winid = api.nvim_get_current_win()
|
||||
api.nvim_win_set_cursor(winid, {cursor_row + 1, 0})
|
||||
assert(helpers.fn.getline('.'):match('{{CURSOR}}'))
|
||||
feed(string.format('zt%d<C-y>', #context_rows + 2))
|
||||
|
||||
--- @type [integer,integer,integer,integer][]
|
||||
local ranges = exec_lua([[
|
||||
return require('treesitter-context.context').get(...)
|
||||
]], bufnr, winid)
|
||||
|
||||
local act_context_rows = {} --- @type integer[]
|
||||
for _, r in ipairs(ranges) do
|
||||
table.insert(act_context_rows, r[1])
|
||||
end
|
||||
|
||||
helpers.eq(context_rows, act_context_rows, string.format('test for cursor %d failed', cursor_row))
|
||||
end
|
||||
|
||||
end)
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
describe('language:', function()
|
||||
before_each(function()
|
||||
exec_lua[[require'treesitter-context'.setup{
|
||||
|
@ -240,7 +329,7 @@ describe('ts_context', function()
|
|||
|
||||
it('c', function()
|
||||
install_langs('c')
|
||||
cmd('edit test/lang/test.c')
|
||||
cmd('edit test/test.c')
|
||||
exec_lua [[vim.treesitter.start()]]
|
||||
feed'<C-e>'
|
||||
|
||||
|
|
Loading…
Reference in a new issue