Search code examples
luagloballuacheck

luacheck: ignore globals defined in file


I have a module constants.lua that has a lot of globals defined. How can I ignore all of these in luacheck?

I assume I can build logic to do this inside my .luacheckrc: load constants.lua, see what it added to _G, and then add those to read_globals.

I'm using Lua 5.4.


Solution

  • If you have only variable definitions (no runtime logic) in your constants.lua, then you can load it from luacheckrc. It could even require other files that are also only definitions. Beware of doing too much from here since luacheck needs to process this file on every lint event.

    To load the files from your .luacheckrc:

    -- Your normal luacheck config here. We'll modify this table later.
    read_globals = {
        -- Can manually define globals too.
    }
    
    
    -- Below code will load your constants files and append them to
    -- read_globals.
    
    -- Load script with constants and add to populate dest_globals.
    local function append_globals(dest_globals, script)
        -- Create a fallback env so lua stdlib is available, but we
        -- have a clean list of globals.
        local env = setmetatable({}, {__index = _G})
        local fn = loadfile(script, "t", env)
        fn()
        for key,val in pairs(env) do
            table.insert(dest_globals, key)
        end
    end
    
    -- Pass a global table created above to populate with globals:
    -- read_globals, files["*.lua"].read_globals, etc.
    xpcall(append_globals, print, read_globals, "absolute/path/to/constants.lua")
    

    If constants show up as missing variables, run luacheck on command line to debug (you should get output).

    Absolute vs. Relative paths

    Unfortunately, it uses absolute paths because debug.getinfo and other tricks don't work from within luacheckrc -- they return "chunk" instead of a filename. However, if all your lua code is in a common directory, you can try to get the absolute path from current working directory since luacheck is probably run from the same folder as your lua code:

    local cwd = io.popen("cd"):read('*all')
    -- All code lives in the script folder: c:/proj/script/*.lua
    local root_dir = cwd:match("(.*[/\\])script[/\\]")
    xpcall(append_globals, print, read_globals, root_dir .."script/constants.lua")
    

    Supporting require

    If you embed lua and your host program sets the package path, then you need to set that path to support require. You could use $LUA_PATH_5_4 or modify it at runtime. Put this before any calls to append_globals:

    package.path = package.path .. ";" .. root_dir .."scripts/?.lua"