Skip to content

Commit b22505b

Browse files
committed
resolve #1105 infer type by type(x)
1 parent e6b8211 commit b22505b

File tree

4 files changed

+106
-20
lines changed

4 files changed

+106
-20
lines changed

changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626

2727
local s = t and t.x or 1 -- `t` in `t.x` is `table`
2828
```
29+
* `CHG` infer type by `type(x)`
30+
```lua
31+
local x
32+
33+
if type(x) == 'string' then
34+
print(x) -- `x` is `string` here
35+
end
36+
```
2937
* `FIX` with clients that support LSP 3.17 (VSCode), workspace diagnostics are triggered every time when opening a file.
3038
* `FIX` [#1204](https://github.com/sumneko/lua-language-server/issues/1204)
3139
* `FIX` [#1208](https://github.com/sumneko/lua-language-server/issues/1208)

script/vm/node.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,32 @@ function mt:remove(name)
224224
return self
225225
end
226226

227+
---@param name string
228+
function mt:narrow(name)
229+
if name ~= 'nil' and self.optional == true then
230+
self.optional = nil
231+
end
232+
for index = #self, 1, -1 do
233+
local c = self[index]
234+
if (c.type == 'global' and c.cate == 'type' and c.name == name)
235+
or (c.type == name)
236+
or (c.type == 'doc.type.integer' and (name == 'number' or name == 'integer'))
237+
or (c.type == 'doc.type.boolean' and name == 'boolean')
238+
or (c.type == 'doc.type.table' and name == 'table')
239+
or (c.type == 'doc.type.array' and name == 'table')
240+
or (c.type == 'doc.type.function' and name == 'function') then
241+
goto CONTINUE
242+
end
243+
table.remove(self, index)
244+
self[c] = nil
245+
::CONTINUE::
246+
end
247+
if #self == 0 then
248+
self[#self+1] = vm.getGlobal('type', name)
249+
end
250+
return self
251+
end
252+
227253
---@param node vm.node
228254
function mt:removeNode(node)
229255
for _, c in ipairs(node) do

script/vm/runner.lua

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -208,30 +208,48 @@ function mt:_lookInto(action, topNode, outNode)
208208
outNode = outNode2
209209
elseif action.op.type == '=='
210210
or action.op.type == '~=' then
211-
local loc, checker
211+
local exp, checker
212212
for i = 1, 2 do
213-
if action[i].type == 'getlocal' and action[i].node == self._loc then
214-
loc = action[i]
215-
checker = action[3-i] -- Copilot tells me use `3-i` instead of `i%2+1`
216-
elseif action[2].type == 'getlocal' and action[2].node == self._loc then
217-
loc = action[3-i]
213+
if guide.isLiteral(action[i]) then
218214
checker = action[i]
215+
exp = action[3-i] -- Copilot tells me use `3-i` instead of `i%2+1`
219216
end
220217
end
221-
if loc then
222-
self:_fastWard(loc.finish, topNode:copy())
223-
if guide.isLiteral(checker) then
224-
local checkerNode = vm.compileNode(checker)
225-
if action.op.type == '==' then
226-
topNode = checkerNode
227-
if outNode then
228-
outNode:removeNode(topNode)
229-
end
230-
else
231-
topNode:removeNode(checkerNode)
232-
if outNode then
233-
outNode = checkerNode
234-
end
218+
if not exp then
219+
goto RETURN
220+
end
221+
if exp.type == 'getlocal'
222+
and exp.node == self._loc then
223+
self:_fastWard(exp.finish, topNode:copy())
224+
local checkerNode = vm.compileNode(checker)
225+
if action.op.type == '==' then
226+
topNode = checkerNode
227+
if outNode then
228+
outNode:removeNode(topNode)
229+
end
230+
else
231+
topNode:removeNode(checkerNode)
232+
if outNode then
233+
outNode = checkerNode
234+
end
235+
end
236+
elseif exp.type == 'call'
237+
and checker.type == 'string'
238+
and exp.node.special == 'type'
239+
and exp.args
240+
and exp.args[1]
241+
and exp.args[1].type == 'getlocal'
242+
and exp.args[1].node == self._loc then
243+
self:_fastWard(exp.finish, topNode:copy())
244+
if action.op.type == '==' then
245+
topNode:narrow(checker[1])
246+
if outNode then
247+
outNode:remove(checker[1])
248+
end
249+
else
250+
topNode:remove(checker[1])
251+
if outNode then
252+
outNode:narrow(checker[1])
235253
end
236254
end
237255
end

test/type_inference/init.lua

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,3 +2580,37 @@ local n
25802580
25812581
n = ff[n and <?n?>.x]
25822582
]]
2583+
2584+
TEST 'integer' [[
2585+
local x
2586+
2587+
if type(x) == 'integer' then
2588+
print(<?x?>)
2589+
end
2590+
]]
2591+
2592+
TEST 'boolean|integer' [[
2593+
local x
2594+
2595+
if type(x) == 'integer'
2596+
or type(x) == 'boolean' then
2597+
print(<?x?>)
2598+
end
2599+
]]
2600+
2601+
TEST 'fun()' [[
2602+
---@type fun()?
2603+
local x
2604+
2605+
if type(x) == 'function' then
2606+
print(<?x?>)
2607+
end
2608+
]]
2609+
2610+
TEST 'function' [[
2611+
local x
2612+
2613+
if type(x) == 'function' then
2614+
print(<?x?>)
2615+
end
2616+
]]

0 commit comments

Comments
 (0)