Skip to content

Commit c129da3

Browse files
authored
Merge branch 'master' into fix/exact-class-inject-field-msg
2 parents b1aea98 + 669602c commit c129da3

File tree

4 files changed

+76
-38
lines changed

4 files changed

+76
-38
lines changed

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
<!-- Add all new changes here. They will be moved under a version at release -->
55
* `FIX` Incorrect inject-field message for extra table field in exact class
66

7+
* `FIX` adds the `|lambda|` operator to the `Lua.runtime.nonstandardSymbol` configuration template, which allows the use of that option. Previously, support for it existed in the parser, but we could not actually use the option because it is not recognised in the configuration.
8+
* `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)
9+
710
## 3.15.0
811
`2025-6-25`
912
* `NEW` Support custom addons path for enhanced editor flexibility

script/config/template.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ local template = {
223223
'|=', '&=', '<<=', '>>=',
224224
'||', '&&', '!', '!=',
225225
'continue',
226+
'|lambda|',
226227
}),
227228
['Lua.runtime.plugin'] = Type.Or(Type.String, Type.Array(Type.String)) ,
228229
['Lua.runtime.pluginArgs'] = Type.Or(Type.Array(Type.String), Type.Hash(Type.String, Type.String)),

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)