diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index f987f0e353..1f12478ecb 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -4287,31 +4287,19 @@ by |vim.Pos| objects. as format conversions. Fields: ~ - • {row} (`integer`) 0-based byte index. - • {col} (`integer`) 0-based byte index. - • {buf} (`integer`) buffer handle. - • {to_lsp} (`fun(pos: vim.Pos, position_encoding: lsp.PositionEncodingKind)`) - See |Pos:to_lsp()|. - • {lsp} (`fun(buf: integer, pos: lsp.Position, position_encoding: lsp.PositionEncodingKind)`) - See |Pos:lsp()|. - • {to_cursor} (`fun(pos: vim.Pos): integer, integer`) See - |Pos:to_cursor()|. - • {cursor} (`fun(buf: integer, pos: [integer, integer])`) See - |Pos:cursor()|. - • {to_extmark} (`fun(pos: vim.Pos): integer, integer`) See - |Pos:to_extmark()|. - • {extmark} (`fun(buf: integer, row: integer, col: integer)`) See - |Pos:extmark()|. + • {row} (`integer`) 0-based byte index. + • {col} (`integer`) 0-based byte index. + • {buf} (`integer`) buffer handle. -Pos:cursor({buf}, {pos}) *Pos:cursor()* +cursor({buf}, {pos}) *vim.pos.cursor()* Creates a new |vim.Pos| from cursor position (see |api-indexing|). Parameters: ~ • {buf} (`integer`) • {pos} (`[integer, integer]`) -Pos:extmark({buf}, {row}, {col}) *Pos:extmark()* +extmark({buf}, {row}, {col}) *vim.pos.extmark()* Creates a new |vim.Pos| from extmark position (see |api-indexing|). Parameters: ~ @@ -4319,7 +4307,7 @@ Pos:extmark({buf}, {row}, {col}) *Pos:extmark()* • {row} (`integer`) • {col} (`integer`) -Pos:lsp({buf}, {pos}, {position_encoding}) *Pos:lsp()* +lsp({buf}, {pos}, {position_encoding}) *vim.pos.lsp()* Creates a new |vim.Pos| from `lsp.Position`. Example: >lua @@ -4337,7 +4325,7 @@ Pos:lsp({buf}, {pos}, {position_encoding}) *Pos:lsp()* • {pos} (`lsp.Position`) • {position_encoding} (`lsp.PositionEncodingKind`) -Pos:to_cursor({pos}) *Pos:to_cursor()* +to_cursor({pos}) *vim.pos.to_cursor()* Converts |vim.Pos| to cursor position (see |api-indexing|). Parameters: ~ @@ -4347,7 +4335,7 @@ Pos:to_cursor({pos}) *Pos:to_cursor()* (`integer`) (`integer`) -Pos:to_extmark({pos}) *Pos:to_extmark()* +to_extmark({pos}) *vim.pos.to_extmark()* Converts |vim.Pos| to extmark position (see |api-indexing|). Parameters: ~ @@ -4357,7 +4345,7 @@ Pos:to_extmark({pos}) *Pos:to_extmark()* (`integer`) (`integer`) -Pos:to_lsp({pos}, {position_encoding}) *Pos:to_lsp()* +to_lsp({pos}, {position_encoding}) *vim.pos.to_lsp()* Converts |vim.Pos| to `lsp.Position`. Example: >lua @@ -4413,30 +4401,14 @@ Provides operations to compare, calculate, and convert ranges represented by < Fields: ~ - • {start_row} (`integer`) 0-based byte index. - • {start_col} (`integer`) 0-based byte index. - • {end_row} (`integer`) 0-based byte index. - • {end_col} (`integer`) 0-based byte index. - • {buf} (`integer`) Optional buffer handle. - • {is_empty} (`fun(self: vim.Range): boolean`) See - |Range:is_empty()|. - • {has} (`fun(outer: vim.Range, inner: vim.Range|vim.Pos): boolean`) - See |Range:has()|. - • {intersect} (`fun(r1: vim.Range, r2: vim.Range): vim.Range?`) See - |Range:intersect()|. - • {to_lsp} (`fun(range: vim.Range, position_encoding: lsp.PositionEncodingKind): lsp.Range`) - See |Range:to_lsp()|. - • {lsp} (`fun(buf: integer, range: lsp.Range, position_encoding: lsp.PositionEncodingKind)`) - See |Range:lsp()|. - • {to_extmark} (`fun(range: vim.Range)`) See |Range:to_extmark()|. - • {extmark} (`fun(buf: integer, start_row: integer, start_col: integer, end_row: integer, end_col: integer)`) - See |Range:extmark()|. - • {to_cursor} (`fun(range: vim.Range)`) See |Range:to_cursor()|. - • {cursor} (`fun(buf: integer, start_pos: [integer, integer], end_pos: [integer, integer])`) - See |Range:cursor()|. + • {start_row} (`integer`) 0-based byte index. + • {start_col} (`integer`) 0-based byte index. + • {end_row} (`integer`) 0-based byte index. + • {end_col} (`integer`) 0-based byte index. + • {buf} (`integer`) Optional buffer handle. -Range:cursor({buf}, {start_pos}, {end_pos}) *Range:cursor()* +cursor({buf}, {start_pos}, {end_pos}) *vim.range.cursor()* Creates a new |vim.Range| from mark-like range (see |api-indexing|). Example: >lua @@ -4453,8 +4425,8 @@ Range:cursor({buf}, {start_pos}, {end_pos}) *Range:cursor()* • {start_pos} (`[integer, integer]`) • {end_pos} (`[integer, integer]`) - *Range:extmark()* -Range:extmark({buf}, {start_row}, {start_col}, {end_row}, {end_col}) + *vim.range.extmark()* +extmark({buf}, {start_row}, {start_col}, {end_row}, {end_col}) Creates a new |vim.Range| from extmark range (see |api-indexing|). Example: >lua @@ -4470,7 +4442,7 @@ Range:extmark({buf}, {start_row}, {start_col}, {end_row}, {end_col}) • {end_row} (`integer`) • {end_col} (`integer`) -Range:has({outer}, {inner}) *Range:has()* +has({outer}, {inner}) *vim.range.has()* Checks whether {outer} range contains {inner} range or position. Parameters: ~ @@ -4481,7 +4453,7 @@ Range:has({outer}, {inner}) *Range:has()* (`boolean`) `true` if {outer} range fully contains {inner} range or position. -Range:intersect({r1}, {r2}) *Range:intersect()* +intersect({r1}, {r2}) *vim.range.intersect()* Computes the common range shared by the given ranges. Parameters: ~ @@ -4492,13 +4464,16 @@ Range:intersect({r1}, {r2}) *Range:intersect()* (`vim.Range?`) range that is present inside both `r1` and `r2`. `nil` if such range does not exist. See |vim.Range|. -Range:is_empty() *Range:is_empty()* +is_empty({range}) *vim.range.is_empty()* Checks whether the given range is empty; i.e., start >= end. - Return: ~ - (`boolean`) `true` if the given range is empty + Parameters: ~ + • {range} (`vim.Range`) See |vim.Range|. -Range:lsp({buf}, {range}, {position_encoding}) *Range:lsp()* + Return: ~ + (`boolean`) `true` if the given range is empty. + +lsp({buf}, {range}, {position_encoding}) *vim.range.lsp()* Creates a new |vim.Range| from `lsp.Range`. Example: >lua @@ -4516,7 +4491,7 @@ Range:lsp({buf}, {range}, {position_encoding}) *Range:lsp()* • {range} (`lsp.Range`) • {position_encoding} (`lsp.PositionEncodingKind`) -Range:to_cursor({range}) *Range:to_cursor()* +to_cursor({range}) *vim.range.to_cursor()* Converts |vim.Range| to mark-like range (see |api-indexing|). Example: >lua @@ -4530,7 +4505,7 @@ Range:to_cursor({range}) *Range:to_cursor()* Parameters: ~ • {range} (`vim.Range`) See |vim.Range|. -Range:to_extmark({range}) *Range:to_extmark()* +to_extmark({range}) *vim.range.to_extmark()* Converts |vim.Range| to extmark range (see |api-indexing|). Example: >lua @@ -4544,7 +4519,7 @@ Range:to_extmark({range}) *Range:to_extmark()* Parameters: ~ • {range} (`vim.Range`) See |vim.Range|. -Range:to_lsp({range}, {position_encoding}) *Range:to_lsp()* +to_lsp({range}, {position_encoding}) *vim.range.to_lsp()* Converts |vim.Range| to `lsp.Range`. Example: >lua diff --git a/runtime/lua/vim/pos.lua b/runtime/lua/vim/pos.lua index 85f6cbe084..2be36dd785 100644 --- a/runtime/lua/vim/pos.lua +++ b/runtime/lua/vim/pos.lua @@ -39,12 +39,12 @@ local validate = vim.validate ---@field private [1] integer underlying representation of row ---@field private [2] integer underlying representation of col ---@field private [3] integer underlying representation of buf -local Pos = {} +local M = {} ---@private ---@param pos vim.Pos ---@param key any -function Pos.__index(pos, key) +function M.__index(pos, key) if key == 'row' then return pos[1] elseif key == 'col' then @@ -53,14 +53,14 @@ function Pos.__index(pos, key) return pos[3] end - return Pos[key] + return M[key] end ---@package ---@param buf integer ---@param row integer ---@param col integer -function Pos.new(buf, row, col) +function M.new(buf, row, col) validate('buf', buf, 'number') validate('row', row, 'number') validate('col', col, 'number') @@ -70,7 +70,7 @@ function Pos.new(buf, row, col) row, col, buf, - }, Pos) + }, M) return self end @@ -98,17 +98,17 @@ local function cmp_pos(p1, p2) end ---@private -function Pos.__lt(...) +function M.__lt(...) return cmp_pos(...) == -1 end ---@private -function Pos.__le(...) +function M.__le(...) return cmp_pos(...) ~= 1 end ---@private -function Pos.__eq(...) +function M.__eq(...) return cmp_pos(...) == 0 end @@ -131,7 +131,7 @@ end --- ``` ---@param pos vim.Pos ---@param position_encoding lsp.PositionEncodingKind -function Pos.to_lsp(pos, position_encoding) +function M.to_lsp(pos, position_encoding) validate('pos', pos, 'table') validate('position_encoding', position_encoding, 'string') @@ -161,7 +161,7 @@ end ---@param buf integer ---@param pos lsp.Position ---@param position_encoding lsp.PositionEncodingKind -function Pos.lsp(buf, pos, position_encoding) +function M.lsp(buf, pos, position_encoding) validate('buf', buf, 'number') validate('pos', pos, 'table') validate('position_encoding', position_encoding, 'string') @@ -175,27 +175,27 @@ function Pos.lsp(buf, pos, position_encoding) col = vim.str_byteindex(get_line(buf, row), position_encoding, col, false) end - return Pos.new(buf, row, col) + return M.new(buf, row, col) end --- Converts |vim.Pos| to cursor position (see |api-indexing|). ---@param pos vim.Pos ---@return integer, integer -function Pos.to_cursor(pos) +function M.to_cursor(pos) return pos.row + 1, pos.col end --- Creates a new |vim.Pos| from cursor position (see |api-indexing|). ---@param buf integer ---@param pos [integer, integer] -function Pos.cursor(buf, pos) - return Pos.new(buf, pos[1] - 1, pos[2]) +function M.cursor(buf, pos) + return M.new(buf, pos[1] - 1, pos[2]) end --- Converts |vim.Pos| to extmark position (see |api-indexing|). ---@param pos vim.Pos ---@return integer, integer -function Pos.to_extmark(pos) +function M.to_extmark(pos) local line_count = api.nvim_buf_line_count(pos.buf) local row = pos.row @@ -212,16 +212,16 @@ end ---@param buf integer ---@param row integer ---@param col integer -function Pos.extmark(buf, row, col) - return Pos.new(buf, row, col) +function M.extmark(buf, row, col) + return M.new(buf, row, col) end -- Overload `Range.new` to allow calling this module as a function. -setmetatable(Pos, { +setmetatable(M, { __call = function(_, ...) - return Pos.new(...) + return M.new(...) end, }) ----@cast Pos +fun(buf: integer, row: integer, col: integer): vim.Pos +---@cast M +fun(buf: integer, row: integer, col: integer): vim.Pos -return Pos +return M diff --git a/runtime/lua/vim/range.lua b/runtime/lua/vim/range.lua index 8c992fef9b..685fa6a303 100644 --- a/runtime/lua/vim/range.lua +++ b/runtime/lua/vim/range.lua @@ -47,12 +47,12 @@ local api = vim.api ---@field private [3] integer underlying representation of end_row ---@field private [4] integer underlying representation of end_col ---@field private [5] integer underlying representation of buf -local Range = {} +local M = {} ---@private ---@param pos vim.Range ---@param key any -function Range.__index(pos, key) +function M.__index(pos, key) if key == 'start_row' then return pos[1] elseif key == 'start_col' then @@ -65,13 +65,13 @@ function Range.__index(pos, key) return pos[5] end - return Range[key] + return M[key] end ---@package ---@overload fun(start: vim.Pos, end_: vim.Pos): vim.Range ---@overload fun(buf: integer, start_row: integer, start_col: integer, end_row: integer, end_col: integer): vim.Range -function Range.new(...) +function M.new(...) ---@type integer, integer, integer, integer, integer|nil local start_row, start_col, end_row, end_col, buf @@ -101,7 +101,7 @@ function Range.new(...) end_row, end_col, buf, - }, Range) + }, M) return self end @@ -155,7 +155,7 @@ end ---@private ---@param r1 vim.Range ---@param r2 vim.Range -function Range.__lt(r1, r2) +function M.__lt(r1, r2) local r1_inclusive_end_row, r1_inclusive_end_col = to_inclusive_pos(r1.buf, r1.end_row, r1.end_col) return cmp_pos(r1_inclusive_end_row, r1_inclusive_end_col, r2.start_row, r2.start_col) == -1 @@ -164,7 +164,7 @@ end ---@private ---@param r1 vim.Range ---@param r2 vim.Range -function Range.__le(r1, r2) +function M.__le(r1, r2) local r1_inclusive_end_row, r1_inclusive_end_col = to_inclusive_pos(r1.buf, r1.end_row, r1.end_col) return cmp_pos(r1_inclusive_end_row, r1_inclusive_end_col, r2.start_row, r2.start_col) ~= 1 @@ -173,19 +173,20 @@ end ---@private ---@param r1 vim.Range ---@param r2 vim.Range -function Range.__eq(r1, r2) +function M.__eq(r1, r2) return cmp_pos(r1.start_row, r1.start_col, r2.start_row, r2.start_col) == 0 and cmp_pos(r1.end_row, r1.end_col, r2.end_row, r2.end_col) == 0 end --- Checks whether the given range is empty; i.e., start >= end. --- ----@return boolean `true` if the given range is empty -function Range:is_empty() +---@param range vim.Range +---@return boolean `true` if the given range is empty. +function M.is_empty(range) local inclusive_end_row, inclusive_end_col = - to_inclusive_pos(self.buf, self.end_row, self.end_col) + to_inclusive_pos(range.buf, range.end_row, range.end_col) - return cmp_pos(self.start_row, self.start_col, inclusive_end_row, inclusive_end_col) ~= -1 + return cmp_pos(range.start_row, range.start_col, inclusive_end_row, inclusive_end_col) ~= -1 end --- Checks whether {outer} range contains {inner} range or position. @@ -193,7 +194,7 @@ end ---@param outer vim.Range ---@param inner vim.Range|vim.Pos ---@return boolean `true` if {outer} range fully contains {inner} range or position. -function Range.has(outer, inner) +function M.has(outer, inner) if getmetatable(inner) == vim.pos then ---@cast inner -vim.Range return cmp_pos(outer.start_row, outer.start_col, inner.row, inner.col) ~= 1 @@ -226,7 +227,7 @@ end ---@param r2 vim.Range Second range to intersect ---@return vim.Range? range that is present inside both `r1` and `r2`. --- `nil` if such range does not exist. -function Range.intersect(r1, r2) +function M.intersect(r1, r2) if r1.buf ~= r2.buf then return nil end @@ -245,7 +246,7 @@ function Range.intersect(r1, r2) local rs = cmp_pos(r1.start_row, r1.start_col, r2.start_row, r2.start_col) ~= 1 and r2 or r1 local re = cmp_pos(r1.end_row, r1.end_col, r2.end_row, r2.end_col) ~= -1 and r2 or r1 - return Range.new(r1.buf, rs.start_row, rs.start_col, re.end_row, re.end_col) + return M.new(r1.buf, rs.start_row, rs.start_col, re.end_row, re.end_col) end --- Converts |vim.Range| to `lsp.Range`. @@ -261,7 +262,7 @@ end ---@param range vim.Range ---@param position_encoding lsp.PositionEncodingKind ---@return lsp.Range -function Range.to_lsp(range, position_encoding) +function M.to_lsp(range, position_encoding) validate('range', range, 'table') validate('position_encoding', position_encoding, 'string', true) @@ -287,7 +288,7 @@ end ---@param buf integer ---@param range lsp.Range ---@param position_encoding lsp.PositionEncodingKind -function Range.lsp(buf, range, position_encoding) +function M.lsp(buf, range, position_encoding) validate('buf', buf, 'number') validate('range', range, 'table') validate('position_encoding', position_encoding, 'string') @@ -297,7 +298,7 @@ function Range.lsp(buf, range, position_encoding) local start = vim.pos.lsp(buf, range['start'], position_encoding) local end_ = vim.pos.lsp(buf, range['end'], position_encoding) - return Range.new(start, end_) + return M.new(start, end_) end --- Converts |vim.Range| to extmark range (see |api-indexing|). @@ -311,7 +312,7 @@ end --- local extmark_range = range:to_extmark() --- ``` ---@param range vim.Range -function Range.to_extmark(range) +function M.to_extmark(range) validate('range', range, 'table') local srow, scol = vim.pos(range.buf, range.start_row, range.start_col):to_extmark() @@ -332,7 +333,7 @@ end ---@param start_col integer ---@param end_row integer ---@param end_col integer -function Range.extmark(buf, start_row, start_col, end_row, end_col) +function M.extmark(buf, start_row, start_col, end_row, end_col) validate('buf', buf, 'number') validate('start_row', start_row, 'number') validate('start_col', start_col, 'number') @@ -342,7 +343,7 @@ function Range.extmark(buf, start_row, start_col, end_row, end_col) local start = vim.pos.extmark(buf, start_row, start_col) local end_ = vim.pos.extmark(buf, end_row, end_col) - return Range.new(start, end_) + return M.new(start, end_) end --- Converts |vim.Range| to mark-like range (see |api-indexing|). @@ -356,7 +357,7 @@ end --- local cursor_range = range:to_cursor() --- ``` ---@param range vim.Range -function Range.to_cursor(range) +function M.to_cursor(range) validate('range', range, 'table') local srow, scol = vim.pos(range.buf, range.start_row, range.start_col):to_cursor() @@ -378,7 +379,7 @@ end ---@param buf integer ---@param start_pos [integer, integer] ---@param end_pos [integer, integer] -function Range.cursor(buf, start_pos, end_pos) +function M.cursor(buf, start_pos, end_pos) validate('buf', buf, 'number') validate('range', start_pos, 'table') validate('range', end_pos, 'table') @@ -386,16 +387,16 @@ function Range.cursor(buf, start_pos, end_pos) local start = vim.pos.cursor(buf, start_pos) local end_ = vim.pos.cursor(buf, end_pos) - return Range.new(start, end_) + return M.new(start, end_) end -- Overload `Range.new` to allow calling this module as a function. -setmetatable(Range, { +setmetatable(M, { __call = function(_, ...) - return Range.new(...) + return M.new(...) end, }) ----@cast Range +fun(start: vim.Pos, end_: vim.Pos): vim.Range ----@cast Range +fun(buf: integer, start_row: integer, start_col: integer, end_row: integer, end_col: integer): vim.Range +---@cast M +fun(start: vim.Pos, end_: vim.Pos): vim.Range +---@cast M +fun(buf: integer, start_row: integer, start_col: integer, end_row: integer, end_col: integer): vim.Range -return Range +return M diff --git a/src/gen/gen_vimdoc.lua b/src/gen/gen_vimdoc.lua index 257a7d1f62..6609381042 100755 --- a/src/gen/gen_vimdoc.lua +++ b/src/gen/gen_vimdoc.lua @@ -67,6 +67,17 @@ local function contains(t, xs) return vim.tbl_contains(xs, t) end +--- True if the `.` class member should render like a module function. +--- @param fun nvim.gen_vimdoc.HelptagTarget +--- @return boolean +local function is_module_fun(fun) + return fun.classvar ~= nil + and fun.member_sep == '.' + and fun.modvar ~= nil + and fun.module ~= nil + and fun.classvar == fun.modvar +end + --- @type {level:integer, prerelease:boolean}? local nvim_api_info_ @@ -99,6 +110,9 @@ end --- @return string local function fn_helptag_fmt_common(fun) local fn_sfx = fun.table and '' or '()' + if is_module_fun(fun) then + return fmt('%s.%s%s', fun.module, fun.name, fn_sfx) + end if fun.classvar then return fmt('%s:%s%s', fun.classvar, fun.name, fn_sfx) end @@ -663,8 +677,9 @@ end --- @param class nvim.luacats.parser.class --- @param classes table +--- @param hidden_fields? table> --- @param cfg nvim.gen_vimdoc.Config -local function render_class(class, classes, cfg) +local function render_class(class, classes, hidden_fields, cfg) if class.access or class.nodoc or class.inlinedoc then return end @@ -683,7 +698,15 @@ local function render_class(class, classes, cfg) table.insert(ret, md_to_vimdoc(class.desc, INDENTATION, INDENTATION, TEXT_WIDTH)) end - local fields_txt = render_fields_or_params(class.fields, nil, classes, cfg) + local class_hidden = hidden_fields and hidden_fields[class.name] + local fields = class.fields + if class_hidden then + fields = vim.tbl_filter(function(field) + return not class_hidden[field.name] + end, fields) + end + + local fields_txt = render_fields_or_params(fields, nil, classes, cfg) if not fields_txt:match('^%s*$') then table.insert(ret, '\n Fields: ~\n') table.insert(ret, fields_txt) @@ -694,12 +717,22 @@ local function render_class(class, classes, cfg) end --- @param classes table +--- @param funs nvim.luacats.parser.fun[] --- @param cfg nvim.gen_vimdoc.Config -local function render_classes(classes, cfg) +local function render_classes(classes, funs, cfg) local ret = {} --- @type string[] + -- Hide `.` members of returned class-modules from class Fields; + -- they render as module functions. + local hidden_fields = {} --- @type table> + for _, fun in ipairs(funs) do + if is_module_fun(fun) and fun.class then + hidden_fields[fun.class] = hidden_fields[fun.class] or {} + hidden_fields[fun.class][fun.name] = true + end + end for _, class in vim.spairs(classes) do - ret[#ret + 1] = render_class(class, classes, cfg) + ret[#ret + 1] = render_class(class, classes, hidden_fields, cfg) end return table.concat(ret) @@ -718,7 +751,7 @@ local function render_fun_header(fun, cfg) end local nm = fun.name - if fun.classvar then + if fun.classvar and not is_module_fun(fun) then nm = fmt('%s:%s', fun.classvar, nm) end if nm == 'vim.bo' then @@ -735,8 +768,12 @@ local function render_fun_header(fun, cfg) if #proto + #tag > TEXT_WIDTH - 8 then table.insert(ret, fmt('%78s\n', tag)) local name, pargs = proto:match('([^(]+%()(.*)') - table.insert(ret, name) - table.insert(ret, wrap(pargs, 0, #name, TEXT_WIDTH)) + if name then + table.insert(ret, name) + table.insert(ret, wrap(pargs, 0, #name, TEXT_WIDTH)) + else + table.insert(ret, proto) + end else local pad = TEXT_WIDTH - #proto - #tag table.insert(ret, proto .. string.rep(' ', pad) .. tag) @@ -1115,7 +1152,7 @@ local function gen_target(cfg) cfg, briefs, render_funs(funs, all_classes, cfg), - render_classes(classes, cfg) + render_classes(classes, funs, cfg) ) end diff --git a/src/gen/luacats_parser.lua b/src/gen/luacats_parser.lua index 98185d7498..796dcd0b93 100644 --- a/src/gen/luacats_parser.lua +++ b/src/gen/luacats_parser.lua @@ -30,6 +30,7 @@ local luacats_grammar = require('gen.luacats_grammar') --- @field module? string --- @field modvar? string --- @field classvar? string +--- @field member_sep? '.'|':' --- @field deprecated? true --- @field async? true --- @field since? string @@ -324,6 +325,7 @@ local function process_lua_line(line, state, classes, classvars, has_indent) cur_obj.name = fun_or_meth_nm cur_obj.class = class cur_obj.classvar = parent_tbl + cur_obj.member_sep = sep -- Add self param to methods if sep == ':' then cur_obj.params = cur_obj.params or {} @@ -333,7 +335,6 @@ local function process_lua_line(line, state, classes, classvars, has_indent) }) end - -- Add method as the field to the class table.insert(classes[class].fields, fun2field(cur_obj)) return end diff --git a/test/functional/script/luacats_parser_spec.lua b/test/functional/script/luacats_parser_spec.lua index f689f5a22f..68b322285e 100644 --- a/test/functional/script/luacats_parser_spec.lua +++ b/test/functional/script/luacats_parser_spec.lua @@ -1,5 +1,6 @@ local t = require('test.testutil') +local dedent = t.dedent local eq = t.eq local parser = require('gen.luacats_parser') @@ -104,4 +105,76 @@ describe('luacats parser', function() ]], exp ) + + it('tracks class member declaration style', function() + local classes, funs = parser.parse_str( + dedent([[ --- @class vim.MyClass + local MyClass = {} + + --- Dot member. + --- @param obj vim.MyClass + function MyClass.dot_member(obj) + end + + --- Colon member. + function MyClass:colon_member() + end + + return MyClass + ]]), + 'runtime/lua/vim/myclass.lua' + ) + + eq('vim.MyClass', classes['vim.MyClass'].name) + eq({ + classvar = 'MyClass', + desc = 'Dot member.', + kind = 'field', + name = 'dot_member', + type = 'fun(obj: vim.MyClass)', + }, classes['vim.MyClass'].fields[1]) + eq({ + classvar = 'MyClass', + desc = 'Colon member.', + kind = 'field', + name = 'colon_member', + type = 'fun(self: vim.MyClass)', + }, classes['vim.MyClass'].fields[2]) + + eq('.', funs[1].member_sep) + eq('MyClass', funs[1].classvar) + eq('MyClass', funs[1].modvar) + eq('obj', funs[1].params[1].name) + + eq(':', funs[2].member_sep) + eq('self', funs[2].params[1].name) + eq('vim.MyClass', funs[2].params[1].type) + end) + + it('keeps non-returned dot members as class fields', function() + local classes = parser.parse_str( + dedent([[ --- @class vim.Helper + local Helper = {} + + --- @class vim.Module + local M = {} + + --- Helper field. + --- @param helper vim.Helper + function Helper.field(helper) + end + + return M + ]]), + 'runtime/lua/vim/module.lua' + ) + + eq({ + classvar = 'Helper', + desc = 'Helper field.', + kind = 'field', + name = 'field', + type = 'fun(helper: vim.Helper)', + }, classes['vim.Helper'].fields[1]) + end) end)