Skip to content

Commit dca751c

Browse files
committed
diagnostic for enum
1 parent 04c6711 commit dca751c

File tree

10 files changed

+149
-22
lines changed

10 files changed

+149
-22
lines changed

script/core/hover/init.lua

+15-13
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,21 @@ local function getHover(source)
9292
end
9393

9494
local accept = {
95-
['local'] = true,
96-
['setlocal'] = true,
97-
['getlocal'] = true,
98-
['setglobal'] = true,
99-
['getglobal'] = true,
100-
['field'] = true,
101-
['method'] = true,
102-
['string'] = true,
103-
['number'] = true,
104-
['integer'] = true,
105-
['doc.type.name'] = true,
106-
['function'] = true,
107-
['doc.module'] = true,
95+
['local'] = true,
96+
['setlocal'] = true,
97+
['getlocal'] = true,
98+
['setglobal'] = true,
99+
['getglobal'] = true,
100+
['field'] = true,
101+
['method'] = true,
102+
['string'] = true,
103+
['number'] = true,
104+
['integer'] = true,
105+
['doc.type.name'] = true,
106+
['doc.class.name'] = true,
107+
['doc.enum.name'] = true,
108+
['function'] = true,
109+
['doc.module'] = true,
108110
}
109111

110112
---@async

script/core/hover/label.lua

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ local function asDocTypeName(source)
3636
return '(alias) ' .. doc.alias[1] .. ' ' .. lang.script('HOVER_EXTENDS', vm.getInfer(doc.extends):view(guide.getUri(source)))
3737
end
3838
if doc.type == 'doc.enum' then
39-
return '(enum) ' .. doc.enum[1] .. ' ' .. lang.script('HOVER_EXTENDS', vm.getInfer(doc.extends):view(guide.getUri(source)))
39+
return '(enum) ' .. doc.enum[1]
4040
end
4141
end
4242
end
@@ -216,7 +216,8 @@ return function (source, oop)
216216
elseif source.type == 'number'
217217
or source.type == 'integer' then
218218
return asNumber(source)
219-
elseif source.type == 'doc.type.name' then
219+
elseif source.type == 'doc.type.name'
220+
or source.type == 'doc.enum.name' then
220221
return asDocTypeName(source)
221222
elseif source.type == 'doc.field' then
222223
return asDocFieldName(source)

script/parser/guide.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ local type = type
44
---@class parser.object
55
---@field bindDocs parser.object[]
66
---@field bindGroup parser.object[]
7-
---@field bindSource parser.object[]
7+
---@field bindSource parser.object
88
---@field value parser.object
99
---@field parent parser.object
1010
---@field type string

script/parser/luadoc.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -1829,7 +1829,8 @@ local function bindCommentsAndFields(binded)
18291829
end
18301830
bindCommentsToDoc(doc, comments)
18311831
comments = {}
1832-
elseif doc.type == 'doc.alias' then
1832+
elseif doc.type == 'doc.alias'
1833+
or doc.type == 'doc.enum' then
18331834
bindCommentsToDoc(doc, comments)
18341835
comments = {}
18351836
elseif doc.type == 'doc.comment' then

script/vm/compiler.lua

+4-4
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ local function bindDocs(source)
3232
vm.setNode(source, vm.compileNode(doc))
3333
return true
3434
end
35-
if doc.type == 'doc.enum' then
36-
vm.setNode(source, vm.compileNode(doc))
37-
return true
38-
end
3935
if doc.type == 'doc.param' then
4036
local node = vm.compileNode(doc)
4137
if doc.optional then
@@ -1586,6 +1582,10 @@ local compilerSwitch = util.switch()
15861582
: call(function (source)
15871583
vm.setNode(source, vm.compileNode(source.parent))
15881584
end)
1585+
: case 'doc.enum.name'
1586+
: call(function (source)
1587+
vm.setNode(source, vm.compileNode(source.parent))
1588+
end)
15891589
: case 'doc.field'
15901590
: call(function (source)
15911591
if not source.extends then

script/vm/global.lua

+24
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ end
130130

131131
---@class parser.object
132132
---@field _globalNode vm.global|false
133+
---@field _enums? (string|integer)[]
133134

134135
---@type table<string, vm.global>
135136
local allGlobals = {}
@@ -329,6 +330,29 @@ local compilerGlobalSwitch = util.switch()
329330
local enum = vm.declareGlobal('type', name, uri)
330331
enum:addSet(uri, source)
331332
source._globalNode = enum
333+
334+
local tbl = source.bindSource and source.bindSource.value
335+
if not tbl or tbl.type ~= 'table' then
336+
return
337+
end
338+
source._enums = {}
339+
for _, field in ipairs(tbl) do
340+
if field.type == 'tablefield'
341+
or field.type == 'tableindex' then
342+
if not field.value then
343+
goto CONTINUE
344+
end
345+
local key = guide.getKeyName(field)
346+
if not key then
347+
goto CONTINUE
348+
end
349+
if field.value.type == 'integer'
350+
or field.value.type == 'string' then
351+
source._enums[#source._enums+1] = field.value[1]
352+
end
353+
::CONTINUE::
354+
end
355+
end
332356
end)
333357
: case 'doc.type.name'
334358
: call(function (source)

script/vm/type.lua

+54
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
local vm = require 'vm.vm'
33
local guide = require 'parser.guide'
44
local config = require 'config.config'
5+
local util = require 'utility'
56

67
---@param object vm.node.object
78
---@return string?
@@ -40,6 +41,51 @@ local function getNodeName(object)
4041
return nil
4142
end
4243

44+
---@param parentName string
45+
---@param child vm.node.object
46+
---@param uri uri
47+
---@return boolean?
48+
local function checkEnum(parentName, child, uri)
49+
local parentClass = vm.getGlobal('type', parentName)
50+
if not parentClass then
51+
return nil
52+
end
53+
for _, set in ipairs(parentClass:getSets(uri)) do
54+
if set.type == 'doc.enum' then
55+
if child.type ~= 'string'
56+
and child.type ~= 'doc.type.string'
57+
and child.type ~= 'integer'
58+
and child.type ~= 'number'
59+
and child.type ~= 'doc.type.integer' then
60+
return false
61+
end
62+
return util.arrayHas(set._enums, child[1])
63+
end
64+
end
65+
66+
return nil
67+
end
68+
69+
---@param parent vm.node.object
70+
---@param child vm.node.object
71+
---@return boolean
72+
local function checkValue(parent, child)
73+
if parent.type == 'doc.type.integer' then
74+
if child.type == 'integer'
75+
or child.type == 'doc.type.integer'
76+
or child.type == 'number' then
77+
return parent[1] == child[1]
78+
end
79+
elseif parent.type == 'doc.type.string' then
80+
if child.type == 'string'
81+
or child.type == 'doc.type.string' then
82+
return parent[1] == child[1]
83+
end
84+
end
85+
86+
return true
87+
end
88+
4389
---@param uri uri
4490
---@param child vm.node|string|vm.node.object
4591
---@param parent vm.node|string|vm.node.object
@@ -121,6 +167,9 @@ function vm.isSubType(uri, child, parent, mark)
121167
end
122168

123169
if childName == parentName then
170+
if not checkValue(parent, child) then
171+
return false
172+
end
124173
return true
125174
end
126175

@@ -144,6 +193,11 @@ function vm.isSubType(uri, child, parent, mark)
144193
return true
145194
end
146195

196+
local isEnum = checkEnum(parentName, child, uri)
197+
if isEnum ~= nil then
198+
return isEnum
199+
end
200+
147201
-- TODO: check duck
148202
if parentName == 'table' and not guide.isBasicType(childName) then
149203
return true

test/diagnostics/type-check.lua

+35
Original file line numberDiff line numberDiff line change
@@ -729,5 +729,40 @@ local x = G
729729
]]
730730
config.set(nil, 'Lua.type.weakUnionCheck', false)
731731

732+
TEST [[
733+
---@type 1|2
734+
local x
735+
736+
x = 1
737+
x = 2
738+
<!x!> = 3
739+
]]
740+
741+
TEST [[
742+
---@type 'x'|'y'
743+
local x
744+
745+
x = 'x'
746+
x = 'y'
747+
<!x!> = 'z'
748+
]]
749+
750+
TEST [[
751+
---@enum A
752+
local t = {
753+
x = 1,
754+
y = 2,
755+
}
756+
757+
---@param x A
758+
local function f(x)
759+
end
760+
761+
f(<!t!>)
762+
f(t.x)
763+
f(1)
764+
f(<!3!>)
765+
]]
766+
732767
config.remove(nil, 'Lua.diagnostics.disable', 'unused-local')
733768
config.remove(nil, 'Lua.diagnostics.disable', 'undefined-global')

test/hover/init.lua

+10
Original file line numberDiff line numberDiff line change
@@ -2120,3 +2120,13 @@ local <?s?>
21202120
[[
21212121
local s: 'a'
21222122
]]
2123+
2124+
TEST [[
2125+
---@enum <?A?>
2126+
local m = {
2127+
x = 1,
2128+
}
2129+
]]
2130+
[[
2131+
(enum) A
2132+
]]

test/type_inference/init.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -3720,7 +3720,7 @@ TEST '-2|-3|1' [[
37203720
local <?n?>
37213721
]]
37223722

3723-
TEST 'A' [[
3723+
TEST 'table' [[
37243724
---@enum A
37253725
local m = {}
37263726

0 commit comments

Comments
 (0)