luacheck icon indicating copy to clipboard operation
luacheck copied to clipboard

Possibility to check misc libraries usage

Open johnd0e opened this issue 6 years ago • 13 comments

Currently Luacheck can check known globals usage. It would be great to extend this ability to check table fields in libraries that need require to access them.

johnd0e avatar Sep 13 '17 18:09 johnd0e

Yes, this is a nice idea!

For modules within same package as the file being checked Luacheck could read source of required modules and infer available fields from there. This will require an option to map module names to files somewhere in config.

For external modules, module definitions can become part of standards for std option, e.g.

{
   globals = {...}, -- some globals provided by a package
   modules = {
       module_name = {...} -- fields of the module, same format as globals
   }

This should work reasonable well if standards are autoloaded from luacheck.std.<name> modules. E.g.

-- .luacheckrc or equivalent
std = "+far"
-- luacheck/std/far.lua
return {
   ... -- definitions for FAR-specific globals and mofules
}

mpeterv avatar Sep 13 '17 21:09 mpeterv

std = "+far"

Oh, as I see _G part can be omitted. Nice. Is it documented?

BTW, before 0.19.0 _G meaning was different: read globals from current environment. Why that feature removed?

Can you reintroduce it (with some other name)?

johnd0e avatar Sep 15 '17 09:09 johnd0e

For external modules, module definitions can become part of standards for std option

That would be great. And definitions for some popular modules may came bundled with Luacheck.

This will require an option to map module names to files somewhere in config.

I suppose in many cases such mapping can be done using current package.path.

johnd0e avatar Sep 15 '17 09:09 johnd0e

Oh, as I see _G part can be omitted. Nice. Is it documented?

It's mentioned here:

Leading plus sign adds new sets to default [set of standard globals] instead of replacing it.

mpeterv avatar Sep 15 '17 10:09 mpeterv

BTW, before 0.19.0 _G meaning was different: read globals from current environment. Why that feature removed? Can you reintroduce it (with some other name)?

I wanted to have more consistent default behaviour across environments running luacheck. Even with command-line luacheck previous behaviour had issues, e.g., if the optionally used luafilesystem library was installed, luacheck would allow working with lfs global because the library sets it on require. It's bad to have CI pass or fail depending on some minor environment changes like that.

Additionally, now that global fields can be described, there is even larger gap between what luacheck can guess about some unknown present globals and what a user with knowledge about the globals can specify in a custom std. Previously luacheck pessimistically assumed that unknown globals are mutable, now it would also have to assume that they can have any fields.

If you want to mimic older behaviour, it should be simple to replicate it by adding all keys in _G table to some custom std.

mpeterv avatar Sep 15 '17 10:09 mpeterv

I suppose in many cases such mapping can be done using current package.path.

Often modules being checked are not in package.path during development. E.g. luacheck itself has modules in src/, but src/?.lua is not in package.path. So using package.path by default can have unexpected results, because it will pick up currently installed versions of modules instead of local development ones.

mpeterv avatar Sep 15 '17 10:09 mpeterv

So using package.path by default can have unexpected results

You are right, we need some option, Can it be in form package.path?

johnd0e avatar Sep 15 '17 12:09 johnd0e

If you want to mimic older behaviour, it should be simple to replicate it by adding all keys in _G table to some custom std.

Not so easy, if I want to add all tables with their fields and so on (in order to take advantage of new luacheck possibilities).

It is not so hard, but if I ever begin to solve such task then I better build proper custom set (as I've done for FAR).

So what I am trying to say: it would be convenient to have similar option out of the box. (Obviously it is not subject of current issue, sorry)

johnd0e avatar Sep 15 '17 12:09 johnd0e

You are right, we need some option, Can it be in form package.path?

Sometimes source file layout is weird and does not correspond to any package.path. So probably will need something like

modules = {
   ["foo"] = "src/foo/init.lua",
   ["foo.*"] = "src"
}

Not so easy, if I want to add all tables with their fields and so on (in order to take advantage of new luacheck possibilities).

The problem is, when luacheck sees a table in some unknown global or global field, it does not know if its keys are supposed to stay fixed (in which case it can recursively build definitions for the values), or if the table is used as a hash map and new keys can be added (like ngx.ctx table from ngx_lua std).

mpeterv avatar Sep 15 '17 12:09 mpeterv

The problem is, when luacheck sees a table in some unknown global or global field, it does not know if its keys are supposed to stay fixed (in which case it can recursively build definitions for the values), or if the table is used as a hash map and new keys can be added (like ngx.ctx table from ngx_lua std).

When base std's set is auto-defined it's easy to add some overrides manually.

johnd0e avatar Sep 15 '17 15:09 johnd0e

Sometimes source file layout is weird and does not correspond to any package.path. So probably will need something like

Sometimes weird, sometimes no. Can we take into consideration both cases?

local template = [[C:\Apps\Far3\Profile\Macros\modules\?.lua;C:\Apps\Far3\Profile\Macros\modules\?\init.lua]]

modules = {
   ["foo"] = "src/foo/init.lua",
   ["foo.*"] = "src",
   ["luacheck"] = template
}

P.S. Not a big issue though, as I can write own function to search path in template. init.lua]]

modules = {
   ["luacheck"] = find(path_template,"luacheck")
}

johnd0e avatar Sep 15 '17 15:09 johnd0e

It's mentioned here:

Leading plus sign adds new sets to default [set of standard globals] instead of replacing it.

To be precise, not default, but rather current one, as current (or active) set may be defined in .luacheckrc

In other words: if set is redefined in .luacheckrc, then leading plus sign applies not to default _G set, but to one redefined in .luacheckrc.

This is true in both cases: when using --std in commandline and when using as inline option --luacheck: std.

johnd0e avatar Sep 20 '17 07:09 johnd0e

Extending my request from first post:

What if we could define not only stds plain table fields, but also stds functions return values-tables' fields.

Well there are not so many functions that return tables, but anyway..

johnd0e avatar Oct 08 '17 21:10 johnd0e