mirror of
https://github.com/neovim/neovim.git
synced 2026-09-09 15:35:51 +00:00
Problem: LuaLS struggles with the generics used in Nvim's runtime, requiring broad diagnostic suppressions. Indexing is also slow. Solution: Use EmmyLua for type checks in the build and CI. It offers more sophisticated type checking, substantially better support for generics, and much better flow analysis. Correct the affected annotations. Use `@internal`, supported directly by EmmyLua, instead of `@nodoc` for shared internal declarations, and support it in the help parser. AI-assisted
175 lines
4.2 KiB
Lua
175 lines
4.2 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
|
|
local snippet = require('vim.lsp._snippet_grammar')
|
|
local describe, it, before_each = t.describe, t.it, t.before_each
|
|
local type = snippet.NodeType
|
|
|
|
local eq = t.eq
|
|
local exec_lua = n.exec_lua
|
|
|
|
describe('vim.lsp._snippet_grammar', function()
|
|
before_each(n.clear)
|
|
|
|
local parse = function(...)
|
|
local results = exec_lua('return { require("vim.lsp._snippet_grammar").parse(...) }', ...)
|
|
eq(1, #results)
|
|
return results[1].data.children
|
|
end
|
|
|
|
it('parses only text', function()
|
|
eq({
|
|
{ type = type.Text, data = { text = 'TE$}XT' } },
|
|
}, parse('TE\\$\\}XT'))
|
|
end)
|
|
|
|
it('parses tabstops', function()
|
|
eq({
|
|
{ type = type.Tabstop, data = { tabstop = 1 } },
|
|
{ type = type.Tabstop, data = { tabstop = 2 } },
|
|
}, parse('$1${2}'))
|
|
end)
|
|
|
|
it('parses nested placeholders', function()
|
|
eq({
|
|
{
|
|
type = type.Placeholder,
|
|
data = {
|
|
tabstop = 1,
|
|
value = {
|
|
type = type.Placeholder,
|
|
data = {
|
|
tabstop = 2,
|
|
value = { type = type.Tabstop, data = { tabstop = 3 } },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}, parse('${1:${2:${3}}}'))
|
|
end)
|
|
|
|
it('parses variables', function()
|
|
eq({
|
|
{ type = type.Variable, data = { name = 'VAR' } },
|
|
{ type = type.Variable, data = { name = 'VAR' } },
|
|
{
|
|
type = type.Variable,
|
|
data = {
|
|
name = 'VAR',
|
|
default = { type = type.Tabstop, data = { tabstop = 1 } },
|
|
},
|
|
},
|
|
{
|
|
type = type.Variable,
|
|
data = {
|
|
name = 'VAR',
|
|
regex = 'regex',
|
|
options = '',
|
|
format = {
|
|
{
|
|
type = type.Format,
|
|
data = { capture = 1, modifier = 'upcase' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}, parse('$VAR${VAR}${VAR:$1}${VAR/regex/${1:/upcase}/}'))
|
|
end)
|
|
|
|
it('parses choice', function()
|
|
eq({
|
|
{
|
|
type = type.Choice,
|
|
data = { tabstop = 1, values = { ',', '|' } },
|
|
},
|
|
}, parse('${1|\\,,\\||}'))
|
|
end)
|
|
|
|
it('parses format', function()
|
|
eq(
|
|
{
|
|
{
|
|
type = type.Variable,
|
|
data = {
|
|
name = 'VAR',
|
|
regex = 'regex',
|
|
options = '',
|
|
format = {
|
|
{
|
|
type = type.Format,
|
|
data = { capture = 1, modifier = 'upcase' },
|
|
},
|
|
{
|
|
type = type.Format,
|
|
data = { capture = 1, if_text = 'if_text' },
|
|
},
|
|
{
|
|
type = type.Format,
|
|
data = { capture = 1, else_text = 'else_text' },
|
|
},
|
|
{
|
|
type = type.Format,
|
|
data = { capture = 1, if_text = 'if_text', else_text = 'else_text' },
|
|
},
|
|
{
|
|
type = type.Format,
|
|
data = { capture = 1, else_text = 'else_text' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
parse(
|
|
'${VAR/regex/${1:/upcase}${1:+if_text}${1:-else_text}${1:?if_text:else_text}${1:else_text}/}'
|
|
)
|
|
)
|
|
end)
|
|
|
|
it('parses empty strings', function()
|
|
eq({
|
|
{
|
|
type = type.Placeholder,
|
|
data = {
|
|
tabstop = 1,
|
|
value = { type = type.Text, data = { text = '' } },
|
|
},
|
|
},
|
|
{
|
|
type = type.Text,
|
|
data = { text = ' ' },
|
|
},
|
|
{
|
|
type = type.Variable,
|
|
data = {
|
|
name = 'VAR',
|
|
regex = 'erg',
|
|
format = {
|
|
{
|
|
type = type.Format,
|
|
data = { capture = 1, if_text = '' },
|
|
},
|
|
},
|
|
options = 'g',
|
|
},
|
|
},
|
|
}, parse('${1:} ${VAR/erg/${1:+}/g}'))
|
|
end)
|
|
|
|
it('parses closing curly brace as text', function()
|
|
eq(
|
|
{
|
|
{ type = type.Text, data = { text = 'function ' } },
|
|
{ type = type.Tabstop, data = { tabstop = 1 } },
|
|
{ type = type.Text, data = { text = '() {\n ' } },
|
|
{ type = type.Tabstop, data = { tabstop = 0 } },
|
|
{ type = type.Text, data = { text = '\n}' } },
|
|
},
|
|
parse(table.concat({
|
|
'function $1() {',
|
|
' $0',
|
|
'}',
|
|
}, '\n'))
|
|
)
|
|
end)
|
|
end)
|