Skip to content

Commit c2018e0

Browse files
committed
support ---@Class (exact)
#1990
1 parent cb16010 commit c2018e0

File tree

4 files changed

+99
-13
lines changed

4 files changed

+99
-13
lines changed

changelog.md

+10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@
2121

2222
assert(isAnimalType(animal, 'Cat'))
2323
```
24+
* `NEW` `---@class` supports attribute `exact`
25+
```lua
26+
---@class (exact) Point
27+
---@field x number
28+
---@field y number
29+
local m = {}
30+
m.x = 1 -- OK
31+
m.y = 2 -- OK
32+
m.z = 3 -- Warning
33+
```
2434

2535
* `FIX` wrong hover and signature for method with varargs and overloads
2636
* `FIX` [#2155]

script/core/diagnostics/inject-field.lua

+68-13
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,29 @@ return function (uri, callback)
3737
return
3838
end
3939

40+
local isExact
4041
local class = vm.getDefinedClass(uri, node)
4142
if class then
42-
return
43+
for _, doc in ipairs(class:getSets(uri)) do
44+
if vm.docHasAttr(doc, 'exact') then
45+
isExact = true
46+
break
47+
end
48+
end
49+
if not isExact then
50+
return
51+
end
52+
if src.type == 'setmethod'
53+
and not guide.getSelfNode(node) then
54+
return
55+
end
4356
end
4457

4558
for _, def in ipairs(vm.getDefs(src)) do
4659
local dnode = def.node
47-
if dnode and vm.getDefinedClass(uri, dnode) then
60+
if dnode
61+
and not isExact
62+
and vm.getDefinedClass(uri, dnode) then
4863
return
4964
end
5065
if def.type == 'doc.type.field' then
@@ -55,16 +70,19 @@ return function (uri, callback)
5570
end
5671
end
5772

58-
local howToFix = lang.script('DIAG_INJECT_FIELD_FIX_CLASS', {
59-
node = hname(node),
60-
fix = '---@class',
61-
})
62-
for _, ndef in ipairs(vm.getDefs(node)) do
63-
if ndef.type == 'doc.type.table' then
64-
howToFix = lang.script('DIAG_INJECT_FIELD_FIX_TABLE', {
65-
fix = '[any]: any',
66-
})
67-
break
73+
local howToFix = ''
74+
if not isExact then
75+
howToFix = lang.script('DIAG_INJECT_FIELD_FIX_CLASS', {
76+
node = hname(node),
77+
fix = '---@class',
78+
})
79+
for _, ndef in ipairs(vm.getDefs(node)) do
80+
if ndef.type == 'doc.type.table' then
81+
howToFix = lang.script('DIAG_INJECT_FIELD_FIX_TABLE', {
82+
fix = '[any]: any',
83+
})
84+
break
85+
end
6886
end
6987
end
7088

@@ -79,7 +97,7 @@ return function (uri, callback)
7997
finish = src.field.finish,
8098
message = message,
8199
}
82-
elseif src.type == 'setfield' and src.method then
100+
elseif src.type == 'setmethod' and src.method then
83101
callback {
84102
start = src.method.start,
85103
finish = src.method.finish,
@@ -89,4 +107,41 @@ return function (uri, callback)
89107
end
90108
guide.eachSourceType(ast.ast, 'setfield', checkInjectField)
91109
guide.eachSourceType(ast.ast, 'setmethod', checkInjectField)
110+
111+
---@async
112+
local function checkExtraTableField(src)
113+
await.delay()
114+
115+
if not src.bindSource then
116+
return
117+
end
118+
if not vm.docHasAttr(src, 'exact') then
119+
return
120+
end
121+
local value = src.bindSource.value
122+
if not value or value.type ~= 'table' then
123+
return
124+
end
125+
for _, field in ipairs(value) do
126+
local defs = vm.getDefs(field)
127+
for _, def in ipairs(defs) do
128+
if def.type == 'doc.field' then
129+
goto nextField
130+
end
131+
end
132+
local message = lang.script('DIAG_INJECT_FIELD', {
133+
class = vm.getInfer(src):view(uri),
134+
field = guide.getKeyName(src),
135+
fix = '',
136+
})
137+
callback {
138+
start = field.start,
139+
finish = field.finish,
140+
message = message,
141+
}
142+
::nextField::
143+
end
144+
end
145+
146+
guide.eachSourceType(ast.ast, 'doc.class', checkExtraTableField)
92147
end

script/parser/luadoc.lua

+1
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ local docSwitch = util.switch()
841841
operators = {},
842842
calls = {},
843843
}
844+
result.docAttr = parseDocAttr(result)
844845
result.class = parseName('doc.class.name', result)
845846
if not result.class then
846847
pushWarning {

test/diagnostics/inject-field.lua

+20
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,23 @@ local t
6262
t.x = 1 -- OK
6363
t.y = 2 -- OK
6464
]]
65+
66+
67+
TEST [[
68+
---@class (exact) Class
69+
---@field x number
70+
local m = {
71+
x = 1, -- OK
72+
<!y!> = 2, -- Warning
73+
}
74+
75+
m.x = 1 -- OK
76+
m.<!y!> = 2 -- Warning
77+
78+
function m:init() -- OK
79+
self.x = 1 -- OK
80+
self.<!y!> = 2 -- Warning
81+
function self:<!xx!>() -- Warning
82+
end
83+
end
84+
]]

0 commit comments

Comments
 (0)