diff --git a/changelog.md b/changelog.md index 8b5f93f76..7008e34e7 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,20 @@ ``` * `NEW` Test CLI: `--name=` `-n=`: run specify unit test * `FIX` Fixed the error that the configuration file pointed to by the `--configpath` option was not read and loaded. +* `NEW` `---@class` supports attribute `partial`, which will not check missing inherited fields [#3023](https://github.com/LuaLS/lua-language-server/issues/3023) + ```lua + ---@class Config + ---@field a number + + ---@class (partial) Config.P: Config + ---@field b number + + ---@type Config.P[] + local cfgs = {} + cfgs[1] = { b = 1 } -- no warning + cfgs[2] = {} -- only warns missing `b` + ``` + This enables the previous missing field check behavior before [#2970](https://github.com/LuaLS/lua-language-server/issues/2970) ## 3.13.5 `2024-12-20` diff --git a/script/core/diagnostics/missing-fields.lua b/script/core/diagnostics/missing-fields.lua index 2459f7cf8..ed9bf1a6a 100644 --- a/script/core/diagnostics/missing-fields.lua +++ b/script/core/diagnostics/missing-fields.lua @@ -26,6 +26,18 @@ return function (uri, callback) local className = def.class[1] if not sortedDefs[className] then sortedDefs[className] = {} + -- check if this class is a `partial` class + -- a partial class will not check missing inherited fields + local class = vm.getGlobal('type', className) + ---@cast class -nil + for _, set in ipairs(class:getSets(uri)) do + if set.type == 'doc.class' + and vm.docHasAttr(set, 'partial') + then + sortedDefs[className].isPartial = true + break + end + end end local samedefs = sortedDefs[className] samedefs[#samedefs+1] = def @@ -41,8 +53,8 @@ return function (uri, callback) for className, samedefs in pairs(sortedDefs) do local missedKeys = {} for _, def in ipairs(samedefs) do - local fields = vm.getFields(def) - if #fields == 0 then + local fields = samedefs.isPartial and def.fields or vm.getFields(def) + if not fields or #fields == 0 then goto continue end @@ -78,6 +90,12 @@ return function (uri, callback) end end ::continue:: + + if not samedefs.isPartial then + -- if not partial class, then all fields in this class have already been checked + -- because in the above uses `vm.getFields` to get all fields + break + end end if #missedKeys == 0 then diff --git a/test/diagnostics/missing-fields.lua b/test/diagnostics/missing-fields.lua index 4b460531c..66abfe162 100644 --- a/test/diagnostics/missing-fields.lua +++ b/test/diagnostics/missing-fields.lua @@ -462,4 +462,38 @@ local function f(b) end f ]] +-- partial class + +TEST[[ +---@class A +---@field x number + +---@class (partial) B: A + +---@type B +local t = {} +]] + +TEST[[ +---@class A +---@field x number + +---@class (partial) B: A +---@field y number + +---@type B +local t = +]] + +TEST[[ +---@class A +---@field x number + +---@class (partial) B: A +---@field y number + +---@type B +local t = {y = 1} +]] + --