
-----------------------------------------------------
local core_utils = require "luacheck.core_utils" or luacheck.core_utils

local reachability

local function noop_callback() end

local function reachability_callback(_, _, item, chstate, nested)
   if not item then
      return true
   end

   if not nested and item.lines then
      for _, subline in ipairs(item.lines) do
         reachability(chstate, subline, true)
      end
   end

   for _, action_key in ipairs({"accesses", "mutations"}) do
      local item_var_map = item[action_key]

      if item_var_map then
         for var, accessing_nodes in pairs(item_var_map) do
            if not var.empty then
               local all_possible_values_empty = true

               for _, possible_value in ipairs(item.used_values[var]) do
                  if not possible_value.empty then
                     all_possible_values_empty = false
                     break
                  end
               end

               if all_possible_values_empty then
                  for _, accessing_node in ipairs(accessing_nodes) do
                     chstate:warn_uninit(accessing_node, action_key == "mutations")
                  end
               end
            end
         end
      end
   end
end

-- Emits warnings: unreachable code, uninitialized access.
function reachability(chstate, line, nested)
   local reachable_indexes = {}
   core_utils.walk_line_once(line, reachable_indexes, 1, reachability_callback, chstate, nested)

   for i, item in ipairs(line.items) do
      if not reachable_indexes[i] then
         if item.location then
            chstate:warn_unreachable(item.location, item.loop_end, item.token)
            core_utils.walk_line_once(line, reachable_indexes, i, noop_callback)
         end
      end
   end
end

luacheck.reachability = reachability
return reachability
