Skip to content

Commit

Permalink
Merge pull request #2770 from NeOzay/inconsistent-behavior-(missing-f…
Browse files Browse the repository at this point in the history
…ields)

improve the missing-fields logic to be able to correctly handle classes defined several times
  • Loading branch information
sumneko committed Aug 1, 2024
2 parents ed8559e + 585cc20 commit bbe49f6
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 33 deletions.
3 changes: 2 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
* `CHG` Improve performance of multithreaded `--check` and `undefined-field` diagnostic
* `FIX` Addons can now self-recommend as expected. Fixed by correcting the `wholeMatch` function
* `FIX` Now correctly evaluates the visibility of fields in a class when they are defined directly in the object. use for completion and invisible dianostic. [#2752](https://github.com/LuaLS/lua-language-server/issues/2752)
* `NEW` added lua regular expression support for Lua.doc.<scope>Name [#2753](https://github.com/LuaLS/lua-language-server/pull/2753)
* `NEW` Added lua regular expression support for `Lua.doc.<scope>Name` [#2753](https://github.com/LuaLS/lua-language-server/pull/2753)
* `FIX` Bad triggering of the `inject-field` diagnostic, when the fields are declared at the creation of the object [#2746](https://github.com/LuaLS/lua-language-server/issues/2746)
* `CHG` Change spacing of parameter inlay hints to match other LSPs, like `rust-analyzer`
* `FIX` Inconsistent type narrow behavior of function call args [#2758](https://github.com/LuaLS/lua-language-server/issues/2758)
* `FIX` Improve the `missing-fields` logic to be able to correctly handle classes defined several times [#22770](https://github.com/LuaLS/lua-language-server/pull/2770)
* `FIX` Typos in annotation descriptions
* `NEW` You can now click on "References" in CodeLen to display the reference list
* `FIX` incorrect `CompletionItemKind` for postfix snippets [#2773](https://github.com/LuaLS/lua-language-server/pull/2773)
Expand Down
78 changes: 46 additions & 32 deletions script/core/diagnostics/missing-fields.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,61 +15,75 @@ return function (uri, callback)
guide.eachSourceType(state.ast, 'table', function (src)
await.delay()

vm.removeNode(src) -- the node is not updated correctly, reason still unknown
local defs = vm.getDefs(src)
local sortedDefs = {}
for _, def in ipairs(defs) do
if def.type == 'doc.class' and def.bindSource then
if guide.isInRange(def.bindSource, src.start) then
if def.type == 'doc.class' then
if def.bindSource and guide.isInRange(def.bindSource, src.start) then
return
end
local className = def.class[1]
if not sortedDefs[className] then
sortedDefs[className] = {}
end
local samedefs = sortedDefs[className]
samedefs[#samedefs+1] = def
end
if def.type == 'doc.type.array'
or def.type == 'doc.type.table' then
return
end
end

local myKeys
local warnings = {}
for _, def in ipairs(defs) do
if def.type == 'doc.class' then
if not def.fields then
return
for className, samedefs in pairs(sortedDefs) do
local missedKeys = {}
for _, def in ipairs(samedefs) do
if not def.fields or #def.fields == 0 then
goto continue
end

if not myKeys then
myKeys = {}
for _, field in ipairs(src) do
local key = vm.getKeyName(field) or field.tindex
if key then
myKeys[key] = true
end
end
end

local requiresKeys = {}
for _, field in ipairs(def.fields) do
if not field.optional
and not vm.compileNode(field):isNullable() then
local key = vm.getKeyName(field)
if key and not requiresKeys[key] then
requiresKeys[key] = true
requiresKeys[#requiresKeys+1] = key
if not key then
local fieldnode = vm.compileNode(field.field)[1]
if fieldnode and fieldnode.type == 'doc.type.integer' then
---@cast fieldnode parser.object
key = vm.getKeyName(fieldnode)
end
end
end
end

if #requiresKeys == 0 then
return
end
local myKeys = {}
for _, field in ipairs(src) do
local key = vm.getKeyName(field)
if key then
myKeys[key] = true
end
end

local missedKeys = {}
for _, key in ipairs(requiresKeys) do
if not myKeys[key] then
missedKeys[#missedKeys+1] = ('`%s`'):format(key)
if key and not myKeys[key] then
if type(key) == "number" then
missedKeys[#missedKeys+1] = ('`[%s]`'):format(key)
else
missedKeys[#missedKeys+1] = ('`%s`'):format(key)
end
end
end
end
::continue::
end

if #missedKeys == 0 then
return
end

warnings[#warnings+1] = lang.script('DIAG_MISSING_FIELDS', def.class[1], table.concat(missedKeys, ', '))
if #missedKeys == 0 then
return
end

warnings[#warnings+1] = lang.script('DIAG_MISSING_FIELDS', className, table.concat(missedKeys, ', '))
end

if #warnings == 0 then
Expand Down
122 changes: 122 additions & 0 deletions test/diagnostics/missing-fields.lua
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,125 @@ local t = {
y = 1,
}
]]

TEST [[
---@diagnostic disable: unused-local
---@class Foo
---@field a number
---@field b number
---@field c number
---@class Foo
---@class Bar
---@field ba number
---@field bb number
---@field bc number
---@class Bar
---@field bd number
---@type Foo|Bar
local x = {
ba = 1,
bb = 2,
bc = 3,
bd = 4,
}
]]

TEST [[
---@diagnostic disable: unused-local
---@class Foo
---@field a number
---@field b number
---@field c number
---@class Foo
---@class Bar
---@field ba number
---@field bb number
---@field bc number
---@class Bar
---@field bd number
---@type Foo|Bar
local x = {
a = 1,
b = 2,
c = 3,
}
]]

TEST [[
---@diagnostic disable: unused-local
---@class Foo
---@field a number
---@field b number
---@field c number
---@class Foo
---@class Bar
---@field ba number
---@field bb number
---@field bc number
---@class Bar
---@field bd number
---@type Foo|Bar
local x = <!{
a = 1,
b = 2,
}!>
]]

TEST [[
---@diagnostic disable: unused-local
---@class Foo
---@field a number
---@field b number
---@field c number
---@class Foo
---@class Bar
---@field ba number
---@field bb number
---@field bc number
---@class Bar
---@field bd number
---@type Foo|Bar
local x = <!{
ba = 1,
bb = 2,
bd = 4,
}!>
]]

TEST[[
---@class A
---@field [1] string
---@field x number
---@type A
local t = {x = 1, ""}
]]

TEST[[
---@class A
---@field [1] string
---@field x number
---@type A
local t = <!{x = 1}!>
]]

0 comments on commit bbe49f6

Please sign in to comment.