Skip to content

Commit

Permalink
Also stops tracking at the *end* of control flow blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
arichard4 committed May 10, 2022
1 parent 071f25e commit ef20234
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
27 changes: 27 additions & 0 deletions spec/table_field_limitations_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,33 @@ y[1] = 1
]])
end)

it("halts checking at the end of control flow blocks with jumps", function()
assert_warnings({}, [[
local x = {1}
if math.rand(0,1) ~= 1 then
x = {}
end
x[1] = x[1]
local y = {1}
if math.random(0,1) == 1 then
y[1] = 2
else
y = {}
end
y[1] = y[1]
local a = {1}
while math.random(0,1) == 1 do
a = {}
end
a[1] = a[1]
]])
end)

it("stops checking if a function is called", function()
assert_warnings({
{line = 8, column = 3, name = 'y', end_column = 3, field = 'x', code = '315', set_is_nil = '' },
Expand Down
11 changes: 10 additions & 1 deletion src/luacheck/stages/check_table_fields.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ function ClosureState:__init(chstate)
self.external_references_accessed = {}

self.max_item = 0

-- Luacheck's linearized item format doesn't explicitly have a node for the "end" tag
-- This tracks where end tags would be, so that we can stop tracking
-- This pattern won't be workable if this eventually gets extended to support control flow
self.jump_destinations = {}
end

-- Start keeping track of a local table
Expand Down Expand Up @@ -417,6 +422,7 @@ function ClosureState:handle_eval(item)
end

function ClosureState:handle_jump(item)
self.jump_destinations[item.to] = true
if item.to > self.max_item then
-- return; see comment under handle_control_flow_item
self:on_scope_end()
Expand All @@ -428,7 +434,7 @@ end
local item_callbacks = {
Noop = ClosureState.handle_control_flow_item,
Jump = ClosureState.handle_jump,
Cjump = ClosureState.stop_tracking_tables,
Cjump = ClosureState.handle_jump,
Eval = ClosureState.handle_eval,
Local = ClosureState.handle_local_or_set_item,
Set = ClosureState.handle_local_or_set_item
Expand All @@ -453,6 +459,9 @@ local function detect_unused_table_fields(closure, check_state)
closure_state.max_item = #closure.items

for item_index = 1, #closure.items do
if closure_state.jump_destinations[item_index] then
closure_state:stop_tracking_tables()
end
-- Function declaration: function could potentially survive this scope
-- Preserving a reference to its upvalues
local item = closure.items[item_index]
Expand Down

0 comments on commit ef20234

Please sign in to comment.