Skip to content

Commit 35ed907

Browse files
authored
Merge pull request #3224 from tomlau10/fix/field-fallback-type
fix: typed `@field` should not override other defined field
2 parents 32fec3c + 45650db commit 35ed907

File tree

3 files changed

+73
-38
lines changed

3 files changed

+73
-38
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44
<!-- Add all new changes here. They will be moved under a version at release -->
5+
* `FIX` Typed `@field` (eg `---@field [string] boolean`) should not override other defined field [#2171](https://github.com/LuaLS/lua-language-server/issues/2171), [#2711](https://github.com/LuaLS/lua-language-server/issues/2711)
56

67
## 3.15.0
78
`2025-6-25`

script/vm/compiler.lua

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -434,44 +434,6 @@ function vm.getClassFields(suri, object, key, pushResult)
434434
pushResult(field, true)
435435
goto CONTINUE
436436
end
437-
if hasFounded[key] then
438-
goto CONTINUE
439-
end
440-
local keyType = type(key)
441-
if keyType == 'table' then
442-
-- ---@field [integer] boolean -> class[integer]
443-
local fieldNode = vm.compileNode(field.field)
444-
if vm.isSubType(suri, key.name, fieldNode) then
445-
local nkey = '|' .. key.name
446-
if not searchedFields[nkey] then
447-
pushResult(field, true)
448-
hasFounded[nkey] = true
449-
end
450-
end
451-
else
452-
local keyObject
453-
if keyType == 'number' then
454-
if math.tointeger(key) then
455-
keyObject = { type = 'integer', [1] = key }
456-
else
457-
keyObject = { type = 'number', [1] = key }
458-
end
459-
elseif keyType == 'boolean'
460-
or keyType == 'string' then
461-
keyObject = { type = keyType, [1] = key }
462-
end
463-
if keyObject and field.field.type ~= 'doc.field.name' then
464-
-- ---@field [integer] boolean -> class[1]
465-
local fieldNode = vm.compileNode(field.field)
466-
if vm.isSubType(suri, keyObject, fieldNode) then
467-
local nkey = '|' .. keyType
468-
if not searchedFields[nkey] then
469-
pushResult(field, true)
470-
hasFounded[nkey] = true
471-
end
472-
end
473-
end
474-
end
475437
::CONTINUE::
476438
end
477439
end
@@ -547,6 +509,59 @@ function vm.getClassFields(suri, object, key, pushResult)
547509
end
548510
copyToSearched()
549511

512+
-- search for typed @field, eg: ---@field [string] boolean
513+
-- only if type for this field key is not found
514+
if not searchedFields[key] and key ~= vm.ANY and key ~= vm.ANYDOC then
515+
for _, set in ipairs(sets) do
516+
if set.type == 'doc.class' then
517+
for _, field in ipairs(set.fields) do
518+
local fieldKey = guide.getKeyName(field)
519+
if fieldKey then
520+
-- already processed above
521+
goto CONTINUE
522+
end
523+
local keyType = type(key)
524+
if keyType == 'table' then
525+
-- ---@field [integer] boolean -> class[integer]
526+
local fieldNode = vm.compileNode(field.field)
527+
if vm.isSubType(suri, key.name, fieldNode) then
528+
local nkey = '|' .. key.name
529+
if not searchedFields[nkey] then
530+
pushResult(field, true)
531+
hasFounded[nkey] = true
532+
end
533+
end
534+
else
535+
local keyObject
536+
if keyType == 'number' then
537+
if math.tointeger(key) then
538+
keyObject = { type = 'integer', [1] = key }
539+
else
540+
keyObject = { type = 'number', [1] = key }
541+
end
542+
elseif keyType == 'boolean'
543+
or keyType == 'string' then
544+
keyObject = { type = keyType, [1] = key }
545+
end
546+
if keyObject and field.field.type ~= 'doc.field.name' then
547+
-- ---@field [integer] boolean -> class[1]
548+
local fieldNode = vm.compileNode(field.field)
549+
if vm.isSubType(suri, keyObject, fieldNode) then
550+
local nkey = '|' .. keyType
551+
if not searchedFields[nkey] then
552+
pushResult(field, true)
553+
hasFounded[nkey] = true
554+
end
555+
end
556+
end
557+
end
558+
::CONTINUE::
559+
end
560+
end
561+
end
562+
copyToSearched()
563+
end
564+
550565
for _, set in ipairs(sets) do
551566
if set.type == 'doc.class' then
552567
-- look into extends(if field not found)

test/type_inference/common.lua

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3608,6 +3608,25 @@ local t
36083608
local <?x?> = t.n
36093609
]]
36103610

3611+
TEST 'function' [[
3612+
---@class A
3613+
---@field [string] boolean
3614+
local t
3615+
function t.f() end
3616+
3617+
local <?f?> = t.f
3618+
]]
3619+
3620+
TEST 'function' [[
3621+
---@class A
3622+
---@field [string] boolean
3623+
local t = {
3624+
f = function () end
3625+
}
3626+
3627+
local <?f?> = t.f
3628+
]]
3629+
36113630
TEST 'string' [[
36123631
---@class string
36133632
---@operator mod: string

0 commit comments

Comments
 (0)