neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

luacats_grammar_spec.lua (6785B)


      1 local t = require('test.testutil')
      2 
      3 local eq = t.eq
      4 
      5 local grammar = require('gen.luacats_grammar')
      6 
      7 describe('luacats grammar', function()
      8  --- @param text string
      9  --- @param exp table<string,string>
     10  local function test(text, exp)
     11    it(string.format('can parse %q', text), function()
     12      eq(exp, grammar:match(text))
     13    end)
     14  end
     15 
     16  test('@param hello vim.type', {
     17    kind = 'param',
     18    name = 'hello',
     19    type = 'vim.type',
     20  })
     21 
     22  test('@param hello vim.type this is a description', {
     23    kind = 'param',
     24    name = 'hello',
     25    type = 'vim.type',
     26    desc = 'this is a description',
     27  })
     28 
     29  test('@param hello vim.type|string this is a description', {
     30    kind = 'param',
     31    name = 'hello',
     32    type = 'vim.type|string',
     33    desc = 'this is a description',
     34  })
     35 
     36  test('@param hello vim.type?|string? this is a description', {
     37    kind = 'param',
     38    name = 'hello',
     39    type = 'vim.type?|string?',
     40    desc = 'this is a description',
     41  })
     42 
     43  test('@return string hello this is a description', {
     44    kind = 'return',
     45    {
     46      name = 'hello',
     47      type = 'string',
     48    },
     49    desc = 'this is a description',
     50  })
     51 
     52  test('@return fun() hello this is a description', {
     53    kind = 'return',
     54    {
     55      name = 'hello',
     56      type = 'fun()',
     57    },
     58    desc = 'this is a description',
     59  })
     60 
     61  test('@return fun(a: string[]): string hello this is a description', {
     62    kind = 'return',
     63    {
     64      name = 'hello',
     65      type = 'fun(a: string[]): string',
     66    },
     67    desc = 'this is a description',
     68  })
     69 
     70  test('@return fun(a: table<string,any>): string hello this is a description', {
     71    kind = 'return',
     72    {
     73      name = 'hello',
     74      type = 'fun(a: table<string,any>): string',
     75    },
     76    desc = 'this is a description',
     77  })
     78 
     79  test('@param ... string desc', {
     80    kind = 'param',
     81    name = '...',
     82    type = 'string',
     83    desc = 'desc',
     84  })
     85 
     86  test('@param level (integer|string) desc', {
     87    kind = 'param',
     88    name = 'level',
     89    type = 'integer|string',
     90    desc = 'desc',
     91  })
     92 
     93  test('@return (string command) the command and arguments', {
     94    kind = 'return',
     95    {
     96      name = 'command',
     97      type = 'string',
     98    },
     99    desc = 'the command and arguments',
    100  })
    101 
    102  test('@return (string command, string[] args) the command and arguments', {
    103    kind = 'return',
    104    {
    105      name = 'command',
    106      type = 'string',
    107    },
    108    {
    109      name = 'args',
    110      type = 'string[]',
    111    },
    112    desc = 'the command and arguments',
    113  })
    114 
    115  test('@param rfc "rfc2396" | "rfc2732" | "rfc3986" | nil', {
    116    kind = 'param',
    117    name = 'rfc',
    118    type = '"rfc2396" | "rfc2732" | "rfc3986" | nil',
    119  })
    120 
    121  test('@param position_encoding "utf-8" | "utf-16" | "utf-32" | nil', {
    122    kind = 'param',
    123    name = 'position_encoding',
    124    type = '"utf-8" | "utf-16" | "utf-32" | nil',
    125  })
    126 
    127  -- handle a : after the param type
    128  test('@param a b: desc', {
    129    kind = 'param',
    130    name = 'a',
    131    type = 'b',
    132    desc = 'desc',
    133  })
    134 
    135  test(
    136    '@field prefix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)',
    137    {
    138      kind = 'field',
    139      name = 'prefix?',
    140      type = 'string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)',
    141    }
    142  )
    143 
    144  test('@field [integer] integer', {
    145    kind = 'field',
    146    name = '[integer]',
    147    type = 'integer',
    148  })
    149 
    150  test('@field [1] integer', {
    151    kind = 'field',
    152    name = '[1]',
    153    type = 'integer',
    154  })
    155 
    156  test('@param type `T` this is a generic type', {
    157    desc = 'this is a generic type',
    158    kind = 'param',
    159    name = 'type',
    160    type = '`T`',
    161  })
    162 
    163  test('@param type [number,string,"good"|"bad"] this is a tuple type', {
    164    desc = 'this is a tuple type',
    165    kind = 'param',
    166    name = 'type',
    167    type = '[number,string,"good"|"bad"]',
    168  })
    169 
    170  test('@class vim.diagnostic.JumpOpts', {
    171    kind = 'class',
    172    name = 'vim.diagnostic.JumpOpts',
    173  })
    174 
    175  test('@class vim.diagnostic.JumpOpts : vim.diagnostic.GetOpts', {
    176    kind = 'class',
    177    name = 'vim.diagnostic.JumpOpts',
    178    parent = 'vim.diagnostic.GetOpts',
    179  })
    180 
    181  test('@param opt? { cmd?: string[] } Options', {
    182    kind = 'param',
    183    name = 'opt?',
    184    type = '{ cmd?: string[] }',
    185    desc = 'Options',
    186  })
    187 
    188  ---@type [string, string?][]
    189  local test_cases = {
    190    { 'foo' },
    191    { 'foo   ', 'foo' }, -- trims whitespace
    192    { 'true' },
    193    { 'vim.type' },
    194    { 'vim-type' },
    195    { 'vim_type' },
    196    { 'foo.bar-baz_baz' },
    197    { '`ABC`' },
    198    { '42' },
    199    { '-42' },
    200    { '(foo)', 'foo' }, -- removes unnecessary parens
    201    { 'true?' },
    202    { '(true)?' },
    203    { 'string[]' },
    204    { 'string|number' },
    205    { '(string)[]' },
    206    { '(string|number)[]' },
    207    { 'coalesce??', 'coalesce?' }, -- removes unnecessary ?
    208    { 'number?|string' },
    209    { "'foo'|'bar'|'baz'" },
    210    { '"foo"|"bar"|"baz"' },
    211    { '(number)?|string' }, --
    212    { 'number[]|string' },
    213    { 'string[]?' },
    214    { 'foo?[]' },
    215    { 'vim.type?|string?   ', 'vim.type?|string?' },
    216    { 'number[][]' },
    217    { 'number[][][]' },
    218    { 'number[][]?' },
    219    { 'string|integer[][]?' },
    220 
    221    -- tuples
    222    { '[string]' },
    223    { '[1]' },
    224    { '[string, number]' },
    225    { '[string, number]?' },
    226    { '[string, number][]' },
    227    { '[string, number]|string' },
    228    { '[string|number, number?]' },
    229    { 'string|[string, number]' },
    230    { '(true)?|[foo]' },
    231    { '[fun(a: string):boolean]' },
    232 
    233    -- dict
    234    { '{[string]:string}' },
    235    { '{ [ string ] : string }' },
    236    { '{ [ string|any ] : string }' },
    237    { '{[string]: string, [number]: boolean}' },
    238 
    239    -- key-value table
    240    { 'table<string,any>' },
    241    { 'table' },
    242    { 'string|table|boolean' },
    243    { 'string|table|(boolean)' },
    244 
    245    -- table literal
    246    { '{foo: number}' },
    247    { '{foo: string, bar: [number, boolean]?}' },
    248    { 'boolean|{reverse?:boolean}' },
    249    { '{ cmd?: string[] }' },
    250 
    251    -- function
    252    { 'fun(a: string, b:foo|bar): string' },
    253    { 'fun(a?: string): string' },
    254    { 'fun(a?: string): number?,string?' },
    255    { '(fun(a: string, b:foo|bar): string)?' },
    256    { 'fun(a: string, b:foo|bar): string, string' },
    257    { 'fun(a: string, b:foo|bar)' },
    258    { 'fun(_, foo, bar): string' },
    259    { 'fun(...): number' },
    260    { 'fun( ... ): number' },
    261    { 'fun(...:number): number' },
    262    { 'fun( ... : number): number' },
    263 
    264    -- generics
    265    { 'elem_or_list<string>' },
    266    {
    267      'elem_or_list<fun(client: vim.lsp.Client, init_result: lsp.InitializeResult)>',
    268      nil,
    269    },
    270  }
    271 
    272  for _, tc in ipairs(test_cases) do
    273    local ty, exp_ty = tc[1], tc[2]
    274    if exp_ty == nil then
    275      exp_ty = ty
    276    end
    277 
    278    local var, desc = 'x', 'some desc'
    279    local param = string.format('@param %s %s %s', var, ty, desc)
    280    test(param, {
    281      kind = 'param',
    282      name = var,
    283      type = exp_ty,
    284      desc = desc,
    285    })
    286  end
    287 end)