Skip to content

Commit 4b2a927

Browse files
committed
feat(diagnostics): detect no-unknown-operations for binary operator where both args are known
1 parent de31a1a commit 4b2a927

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

locale/en-us/script.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ DIAG_UNKNOWN =
9292
'Can not infer type.'
9393
DIAG_UNKNOWN_OPERATION_CALL =
9494
'Cannot infer call result for type {}.'
95+
DIAG_UNKNOWN_OPERATION_OPERATOR =
96+
'Cannot infer `{}` result for types {} and {}.'
9597
DIAG_DEPRECATED =
9698
'Deprecated.'
9799
DIAG_DIFFERENT_REQUIRES =

script/core/diagnostics/no-unknown-operations.lua

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ return function (uri, callback)
1717
---@async
1818
guide.eachSourceType(state.ast, 'call', function (source)
1919
await.delay()
20-
local inferred = vm.getInfer(source):view(uri)
21-
if inferred ~= 'unknown' then return end
20+
21+
local resultInfer = vm.getInfer(source):view(uri)
22+
if resultInfer ~= 'unknown' then return end
2223
local functionType = vm.getInfer(source.node)
2324
if functionType:view(uri) == 'unknown' then return end -- we can't say anything about what unknown types support
2425
if functionType:isCallable(uri) then return end
@@ -28,4 +29,27 @@ return function (uri, callback)
2829
message = lang.script('DIAG_UNKNOWN_OPERATION_CALL', functionType:view(uri)),
2930
}
3031
end)
32+
33+
-- binary operators are quite similar to function calls, they introduce an unknown if the result is unknown and none of the
34+
-- parameters are unknown, or if the left side is known to not implement the operator
35+
36+
---@async
37+
guide.eachSourceType(state.ast, 'binary', function (source)
38+
await.delay()
39+
40+
local resultInfer = vm.getInfer(source)
41+
if resultInfer:view(uri) ~= 'unknown' then return end
42+
local left, right = source[1], source[2]
43+
local leftInfer, rightInfer = vm.getInfer(left), vm.getInfer(right)
44+
if leftInfer:view(uri) == 'unknown' then return end
45+
if rightInfer:view(uri) ~= 'unknown' then
46+
-- the operator doesn't work for these types
47+
callback {
48+
start = source.start,
49+
finish = source.finish,
50+
message = lang.script('DIAG_UNKNOWN_OPERATION_OPERATOR', source.op.type, leftInfer:view(uri), rightInfer:view(uri)),
51+
}
52+
return
53+
end
54+
end)
3155
end

script/vm/operator.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ function vm.getOperators(op, node, uri)
111111
for _, set in ipairs(c:getSets(uri)) do
112112
if set.operators and #set.operators > 0 then
113113
for _, operator in ipairs(set.operators) do
114-
table.insert(operators, operator)
114+
if operator.op[1] == op then
115+
table.insert(operators, operator)
116+
end
115117
end
116118
end
117119
end

0 commit comments

Comments
 (0)