mpeterv / luacheck

A tool for linting and static analysis of Lua code.
MIT License
1.92k stars 322 forks source link

Correctly label non local variables after setfenv calls in 5.1 #158

Open personalnadir opened 6 years ago

personalnadir commented 6 years ago

In Lua 5.1 I am in the habit of writing Lua files in the from:

local M={}
modulename=M

local table=table

setfenv(1,M)

function thatUsesTable()
  ...
end

return M

Taken from Programming in Lua 15.4 .

Currently luacheck marks the function thatUsesTable as setting non-standard global variable. However due to the setfenv call above it thatUsesTable is set on the table modulename/M.

I know setfenv/getfenv have been moved to debug in later versions of Lua, but it would be nice to have Luacheck recognise that all code after a setfenv is non-global unless the second parameter is the global table.

mpeterv commented 6 years ago

This would be convenient, but it's not easy to detect all setfenv calls (e.g. they may be wrapped in some auxiliary function like the old module()), and more importantly, the best practice is to use local table instead of setfenv or module (http://kiki.to/blog/2014/03/31/rule-2-return-a-local-table/).

There is already some support for modules using globals, try putting -- luacheck: allow defined, module after the setfenv call.

personalnadir commented 6 years ago

Thanks for the link and the inline instruction, both very useful.

A brute force approach might be to evaluate getfenv(0)==getfenv(1) after each function call. I'm assuming that only setfenv changes the environment in 5.1. I know there's the new _ENV variable in 5.2.

mpeterv commented 6 years ago

Luacheck doesn't execute the checked code in any way (not even in abstract interpretation sense) so it can't evaluate anything like that.