From a25f8c8611575057dfb7ceb1c368371b80a368be Mon Sep 17 00:00:00 2001 From: bbassie <17990055+bbassie@users.noreply.github.com> Date: Thu, 27 Aug 2026 22:25:24 +0000 Subject: [PATCH] Fix lua lint warnings reported by emmylua The largest source was compat.lua returning the setmetatable call directly, which made emmylua infer the module type from the metatable rather than the LibCompat class, hiding every field from consumers. The remaining fixes are nil guards on gui element and character accesses, type annotations for research_sync's script data and player_auth's rcon arguments, casts where the api's read/write union types are wider than the values at runtime, and scoped diagnostic disables for the vendored json.lua and the version fallback code that touches apis removed from the current typedefs. Co-Authored-By: Claude Fable 5 --- packages/host/lua/export/control.lua | 3 +++ packages/host/modules/clusterio/compat.lua | 7 +++++-- packages/host/modules/clusterio/json.lua | 3 +++ .../module/restore_position.lua | 5 +++-- plugins/inventory_sync/module/serialize.lua | 19 ++++++++++--------- plugins/player_auth/module/auth.lua | 13 ++++++++----- plugins/research_sync/module/sync.lua | 11 ++++++++++- plugins/statistics_exporter/module/export.lua | 1 + 8 files changed, 43 insertions(+), 19 deletions(-) diff --git a/packages/host/lua/export/control.lua b/packages/host/lua/export/control.lua index ae895a8c..402dc1b7 100644 --- a/packages/host/lua/export/control.lua +++ b/packages/host/lua/export/control.lua @@ -1,3 +1,6 @@ +--- Undefined fields are expected, the typedefs only cover the latest version +--- @diagnostic disable: undefined-field + local function send_json(channel, data) data = helpers and helpers.table_to_json(data) or game.table_to_json(data) print("\f$ipc:" .. channel .. "?j" .. data) diff --git a/packages/host/modules/clusterio/compat.lua b/packages/host/modules/clusterio/compat.lua index cafee324..4cd2d7c1 100644 --- a/packages/host/modules/clusterio/compat.lua +++ b/packages/host/modules/clusterio/compat.lua @@ -10,7 +10,8 @@ Implementation Guidelines local lib_json = require("json") ---- @diagnostic disable: deprecated +--- Undefined fields are expected, the typedefs only cover the latest version +--- @diagnostic disable: deprecated, undefined-field --- @class LibCompat --- @field script_data table @@ -238,4 +239,6 @@ set_script_data() compat.on_init = set_script_data --- @package compat.on_load = set_script_data --- @package -return setmetatable(compat, compat_mt) +-- Not returned directly because that would infer the metatable type rather than LibCompat +setmetatable(compat, compat_mt) +return compat diff --git a/packages/host/modules/clusterio/json.lua b/packages/host/modules/clusterio/json.lua index be01e897..01a01382 100644 --- a/packages/host/modules/clusterio/json.lua +++ b/packages/host/modules/clusterio/json.lua @@ -22,6 +22,9 @@ -- SOFTWARE. -- +--- Vendored file, the forward declared recursion is not worth annotating +--- @diagnostic disable: need-check-nil + local json = { _version = "0.1.2" } ------------------------------------------------------------------------------- diff --git a/plugins/inventory_sync/module/restore_position.lua b/plugins/inventory_sync/module/restore_position.lua index f2513133..91da5ea7 100644 --- a/plugins/inventory_sync/module/restore_position.lua +++ b/plugins/inventory_sync/module/restore_position.lua @@ -21,9 +21,10 @@ return function(player, record) player.driving = true -- Teleport to safe location if unable to enter vehicle - if not player.driving and player.controller_type == defines.controllers.character then + local character = player.character + if not player.driving and character and player.controller_type == defines.controllers.character then local safe_position = record.vehicle.surface.find_non_colliding_position( - player.character.name, player.position, 32, 1/8 + character.name, player.position, 32, 1/8 ) if safe_position then player.teleport(safe_position, player.surface) diff --git a/plugins/inventory_sync/module/serialize.lua b/plugins/inventory_sync/module/serialize.lua index a46f6472..9c0aa509 100644 --- a/plugins/inventory_sync/module/serialize.lua +++ b/plugins/inventory_sync/module/serialize.lua @@ -207,14 +207,14 @@ end --- @return QuickBarSlotEncoded local function serialize_filter(filter) if filter.quality == "normal" and filter.comparator == "=" then - return filter.name + return filter.name --[[@as string]] end return { t = "f", - n = filter.name, - q = filter.quality, - c = filter.comparator, + n = filter.name --[[@as string]], + q = filter.quality --[[@as string]], + c = filter.comparator --[[@as string]], } end @@ -234,7 +234,7 @@ function serialize.serialize_quick_bar_slot(slot) if v2_0_quick_bar_api then -- 2.0 gives us an item filter which supports quality - --- @cast slot ItemFilter + --- @cast slot -QuickBarSlot, -LuaItemPrototype return serialize_filter(slot) end @@ -267,7 +267,7 @@ function serialize.deserialize_quick_bar_slot(entry) quality = entry.q, comparator = entry.c, }, - } + } --[[@as QuickBarSlot]] end print("Warning: Unsupported serialized quick bar slot type '" .. tostring(entry.t) .. "'") @@ -292,7 +292,7 @@ function serialize.deserialize_quick_bar_slot(entry) -- Return a string (member of ItemPrototypeIdentification) -- Pre 2.0 this was the only method of encoding used - return entry + return entry --[[@as string]] end --- @param player LuaPlayer @@ -709,7 +709,8 @@ local function ensure_character(player) local surface = player.surface if v2_space_platform and surface.platform then local planet_surface = find_planet_surface(surface.platform) - player.teleport(player.force.get_spawn_position(planet_surface), planet_surface) + local force = player.force --[[@as LuaForce]] + player.teleport(force.get_spawn_position(planet_surface), planet_surface) end -- Create and return the character @@ -721,7 +722,7 @@ local function ensure_character(player) player.surface.name, tostring(player.connected), tostring(player.driving) )) end - return player.character + return assert(player.character) end --- @class FailedDeserializationPlayerData diff --git a/plugins/player_auth/module/auth.lua b/plugins/player_auth/module/auth.lua index ad195f89..7bbdb9da 100644 --- a/plugins/player_auth/module/auth.lua +++ b/plugins/player_auth/module/auth.lua @@ -132,6 +132,7 @@ function auth.add_commands() end if event.parameter then + --- @type string[] local args = {} for w in string.gmatch(event.parameter, "[^ ]+") do args[#args + 1] = w @@ -149,7 +150,7 @@ function auth.add_commands() end local player_name, url, code = table.unpack(args) - local player = game.players[player_name] + local player = game.get_player(player_name) if not player then rcon.print("Player " .. player_name .. " does not exist") return @@ -159,7 +160,7 @@ function auth.add_commands() elseif command == "code_set" then local player_name = args[1] - local player = game.players[player_name] + local player = game.get_player(player_name) if not player then rcon.print("Player " .. player_name .. " does not exist") return @@ -171,7 +172,7 @@ function auth.add_commands() elseif command == "error" then local player_name = table.remove(args, 1) - local player = game.players[player_name] + local player = game.get_player(player_name) if not player then rcon.print("Player " .. player_name .. " does not exist") return @@ -192,10 +193,12 @@ auth.events[defines.events.on_gui_click] = function(event) end if event.element.name == "player_auth_dialog_close_button" then - event.element.parent.parent.destroy() + local parent = assert(event.element.parent) + assert(parent.parent).destroy() elseif event.element.name == "player_auth_verify_code_button" then - local verify_code = event.element.parent.player_auth_verify_code_input.text + local parent = assert(event.element.parent) + local verify_code = assert(parent.player_auth_verify_code_input).text local player_name = game.players[event.player_index].name clusterio_api.send_json("player_auth", { type = "set_verify_code", diff --git a/plugins/research_sync/module/sync.lua b/plugins/research_sync/module/sync.lua index 7db1f20d..701f4f7e 100644 --- a/plugins/research_sync/module/sync.lua +++ b/plugins/research_sync/module/sync.lua @@ -30,8 +30,17 @@ local function set_technology_progress(tech, progress) end end +--- @class ResearchSyncTechnology +--- @field level uint +--- @field researched boolean? +--- @field progress double? + +--- @class ResearchSyncData +--- @field technologies table +--- @field ignore_research_finished boolean + --- @param no_early_return boolean? ---- @return table +--- @return ResearchSyncData local function get_script_data(no_early_return) local research_sync = compat.script_data.research_sync if research_sync and not no_early_return then diff --git a/plugins/statistics_exporter/module/export.lua b/plugins/statistics_exporter/module/export.lua index 33626000..6a4bb75b 100644 --- a/plugins/statistics_exporter/module/export.lua +++ b/plugins/statistics_exporter/module/export.lua @@ -32,6 +32,7 @@ function statistics_exporter.export() for _, force in pairs(game.forces) do local flow_statistics = {} for _, statName in pairs(statistics) do + --- @type LuaFlowStatistics local stat = v2_stats and force["get_" .. statName](surface.index) or force[statName] flow_statistics[statName] = { input = stat.input_counts,