Skip to content

Commit 3f815c8

Browse files
committed
new diagnostic: need-check-nil
1 parent a7afda1 commit 3f815c8

File tree

7 files changed

+86
-11
lines changed

7 files changed

+86
-11
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* `NEW` generic: resolve `T[]` by `table<integer, type>` or `---@field [integer] type`
2727
* `NEW` resolve `class[1]` by `---@field [integer] type`
2828
* `NEW` diagnostic: `missing-parameter`
29+
* `NEW` diagnostic: `need-check-nil`
2930
* `CHG` diagnostic: no longer mark `redundant-parameter` as `Unnecessary`
3031
* `FIX` diagnostic: `unused-function` does not recognize recursion
3132
* `FIX` [#1051](https://github.com/sumneko/lua-language-server/issues/1051)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
local files = require 'files'
2+
local guide = require 'parser.guide'
3+
local vm = require 'vm'
4+
local lang = require 'language'
5+
6+
return function (uri, callback)
7+
local state = files.getState(uri)
8+
if not state then
9+
return
10+
end
11+
12+
guide.eachSourceType(state.ast, 'getlocal', function (src)
13+
local checkNil
14+
local nxt = src.next
15+
if nxt then
16+
if nxt.type == 'getfield'
17+
or nxt.type == 'getmethod'
18+
or nxt.type == 'getindex'
19+
or nxt.type == 'call' then
20+
checkNil = true
21+
end
22+
end
23+
local call = src.parent
24+
if call and call.type == 'call' and call.node == src then
25+
checkNil = true
26+
end
27+
if not checkNil then
28+
return
29+
end
30+
local node = vm.compileNode(src)
31+
if node:hasFalsy() then
32+
callback {
33+
start = src.start,
34+
finish = src.finish,
35+
message = lang.script('DIAG_MISS_NEED_CHECK_NIL'),
36+
}
37+
end
38+
end)
39+
end

script/proto/define.lua

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ m.DiagnosticSeverity = {
99
}
1010

1111
---@alias DiagnosticDefaultSeverity
12-
---| '"Hint"'
13-
---| '"Information"'
14-
---| '"Warning"'
15-
---| '"Error"'
12+
---| 'Hint'
13+
---| 'Information'
14+
---| 'Warning'
15+
---| 'Error'
1616

1717
--- 诊断类型与默认等级
1818
---@type table<string, DiagnosticDefaultSeverity>
@@ -48,6 +48,7 @@ m.DiagnosticDefaultSeverity = {
4848
['await-in-sync'] = 'Warning',
4949
['not-yieldable'] = 'Warning',
5050
['discard-returns'] = 'Warning',
51+
['need-check-nil'] = 'Warning',
5152
['type-check'] = 'Warning',
5253

5354
['duplicate-doc-alias'] = 'Warning',
@@ -64,9 +65,9 @@ m.DiagnosticDefaultSeverity = {
6465
}
6566

6667
---@alias DiagnosticDefaultNeededFileStatus
67-
---| '"Any"'
68-
---| '"Opened"'
69-
---| '"None"'
68+
---| 'Any'
69+
---| 'Opened'
70+
---| 'None'
7071

7172
-- 文件状态
7273
m.FileStatus = {
@@ -108,6 +109,7 @@ m.DiagnosticDefaultNeededFileStatus = {
108109
['await-in-sync'] = 'None',
109110
['not-yieldable'] = 'None',
110111
['discard-returns'] = 'Opened',
112+
['need-check-nil'] = 'Opened',
111113
['type-check'] = 'None',
112114

113115
['duplicate-doc-alias'] = 'Any',

script/vm/compiler.lua

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,9 +1435,8 @@ local compilerSwitch = util.switch()
14351435
elseif r1 == false then
14361436
vm.setNode(source, node1)
14371437
else
1438-
vm.getNode(source):merge(node1)
1439-
vm.getNode(source):setTruly()
14401438
vm.getNode(source):merge(node2)
1439+
vm.getNode(source):addOptional()
14411440
end
14421441
end
14431442
if source.op.type == 'or' then

script/vm/node.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function mt:isOptional()
8080
end
8181

8282
---@return boolean
83-
function mt:isFalsy()
83+
function mt:hasFalsy()
8484
if self.optional then
8585
return true
8686
end

script/vm/sign.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ function mt:resolve(uri, args, removeGeneric)
128128
local function buildArgNode(argNode, knownTypes)
129129
local newArgNode = vm.createNode()
130130
for n in argNode:eachObject() do
131-
if argNode:isFalsy() then
131+
if argNode:hasFalsy() then
132132
goto CONTINUE
133133
end
134134
local view = infer.viewObject(n)

test/diagnostics/common.lua

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,3 +1460,37 @@ end
14601460
14611461
<!T:ff!>()
14621462
]]
1463+
1464+
TEST [[
1465+
---@type string?
1466+
local x
1467+
1468+
S = <!x!>:upper()
1469+
]]
1470+
1471+
TEST [[
1472+
---@type string?
1473+
local x
1474+
1475+
if x then
1476+
S = x:upper()
1477+
end
1478+
]]
1479+
1480+
TEST [[
1481+
---@type string?
1482+
local x
1483+
1484+
if not x then
1485+
x = ''
1486+
end
1487+
1488+
S = x:upper()
1489+
]]
1490+
1491+
TEST [[
1492+
---@type fun()?
1493+
local x
1494+
1495+
S = <!x!>()
1496+
]]

0 commit comments

Comments
 (0)