summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2024-08-01 18:15:56 +0800
committerGitHub <noreply@github.com>2024-08-01 18:15:56 +0800
commitbbe49f677745761b9c1906a80b77286bc1f24150 (patch)
treeb9aa881b2da1fab950ea71564401b1a63eb551b1
parented8559ea21ca7e2ccf8886983d33ea57966dcbf9 (diff)
parent585cc203fc3c9c76fa1446dd4743d7029e3570eb (diff)
downloadlua-language-server-bbe49f677745761b9c1906a80b77286bc1f24150.zip
Merge pull request #2770 from NeOzay/inconsistent-behavior-(missing-fields)
improve the missing-fields logic to be able to correctly handle classes defined several times
-rw-r--r--changelog.md3
-rw-r--r--script/core/diagnostics/missing-fields.lua78
-rw-r--r--test/diagnostics/missing-fields.lua122
3 files changed, 170 insertions, 33 deletions
diff --git a/changelog.md b/changelog.md
index 04d013f3..d92faf22 100644
--- a/changelog.md
+++ b/changelog.md
@@ -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)
diff --git a/script/core/diagnostics/missing-fields.lua b/script/core/diagnostics/missing-fields.lua
index 210920fd..5ce650ec 100644
--- a/script/core/diagnostics/missing-fields.lua
+++ b/script/core/diagnostics/missing-fields.lua
@@ -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
diff --git a/test/diagnostics/missing-fields.lua b/test/diagnostics/missing-fields.lua
index ab87f81d..8c1ffbbb 100644
--- a/test/diagnostics/missing-fields.lua
+++ b/test/diagnostics/missing-fields.lua
@@ -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}!>
+]] \ No newline at end of file