Per-Path Settings has weird behavior inside global configuration file.
So, I have come upon this interesting behavior where some of my settings were being ignored. Initially I thought it was because i wrote the globs wrong, then thinking the VSCode extension i used was doing weird things. After getting my debugging hat on, I found an interesting behavior.
My goal was that more or less simple, instead of having to create dozens of .luacheckrc for various projects all resolving around the same thing. I would use the global config file, set up a custom set of globals, and uses files[] to add the set to those folders.
My file was at F:\LuaMods\VTMods\Ammo.lua
My config was set like this: files["VTMods"] = {
VSCode would never apply my custom std, but calling it from the terminal worked. I later realized its because my terminal was set to F:\LuaMods, while editor plugins would call it from F:\LuaMods\VTMods, trying the terminal from that folder also failed.
If I had a .luacheckrc file in F:\LuaMods, then it would work in both folders, and VSCode would display it properly. So I decided to dig around and try to find why everything would fail.
I added a few prints to the luacheck's lua files and found this interaction: In the local file, i would get these results when using terminal from the VTMods folder: abs_conf_dir = "F:\LuaMods" rel_conf_dir = ".." overrides.globs[1] = "F:\LuaMods\VTMods
When using the global file on the other hand: abs_conf_dir = "F:\LuaMods\VTMods" rel_conf_dir = nil overrides.globs[1] = "F:\LuaMods\VTMods\VTMods"
Result: Override not found in file path. Configs not applied.
It would also cause the command line call to give you different results depending on where you called the function, despite using the same arguments.
That seems to go against the concept of per-path settings inside a global configuration file if it's always going to be relative to the current directory. It's true that I could use ../VTMods to go up a folder and then look for the directory I want, but then subfolders becomes hell on earth.
Yes, it's not very well defined what per-path overrides do in global config because it's not clear relatively to which directory they should be interpreted. With local config location of config itself defines how it should be interpreted, but with global config it's difficult to figure out project root.
Current behaviour is definitely misleading, global config should just ignore relative globs and use only absolute globs and globs like (**/foo.lua) that don't change behaviour based on directory they are applied from.
I think that global config should be left as a way to apply some general rules (like default std) when checking single files outside a project. Inside a project there should be a local config.
However, there does need to be a way to share configuration between projects. For example, config could have a new include_configs property that includes other configs into current config context given a path:
include_configs = {"F:\\my_base_config.luacheckrc"}
-- Some configuration specific to this project goes here,
-- taking priority over included configs on conflict
I understand it may be slightly unorthodox, and I remember trying absolute paths, but I used F:/LuaMods/VTMods/, instead of using escaped backslashes F:\
But I looked deeper into it today: Absolute paths also failed. It worked in the command line but failed in the editor.
So, adding some more debug in Luacheck, I found this behavior in globbing.match()
"Glob's base ["F:"] does not match Path's base ["f:"], no match found."
Yes, luacheck should probably convert all paths to lowercase when normalizing them before matching globs (on Windows). I think it already normalizes slashes.
With paths normalized and absolute paths, it completely fixes issues i've had so far. The main thing that threw me off track is that it never occurred to me until much, much later in troubleshooting that file[
When checking a file
, luacheck will override options from the main config with entries from files[ ] if matches
I assumed it compared glob to the absolute path of the file directly. That's my bad I guess.
The idea of include_configs sounds interesting. In the context of game modding for example, we could have an auto-generated file containing all of that environment's globals (and even share it!) without interfering with a project's own configuration.
Not your bad, it should have been documented