LuaLS/lua-language-server

Relative paths do not work with `workspace.library` and `diagnostics.libraryFiles` & `.gitmodules`-related issue

Opened this issue ยท 6 comments

How are you using the lua-language-server?

NeoVim

Which OS are you using?

Linux

What is the issue affecting?

Type Checking, Diagnostics/Syntax Checking, Libraries

Expected Behaviour

workspace.library and diagnostics.libraryFiles work together even if workspace.library is a relative path on-disk. All that is needed is the path specified.

If I clone busted / luassert into my repository and point relative paths to those directories, lua-language-server should treat these directories as third-party and will ignore any issues they may have during diagnostics / type-checking.

Original context: jeffzi/llscheck#7

Actual Behaviour

workspace.library and diagnostics.libraryFiles seem to only omit diagnostics if it is given an absolute path. Relative paths are still read into the workspace but lua-language-server still reports issues on them anyway. Effectively diagnostics.libraryFiles is ignored.

Reproduction steps

Jean-Francois nicely provided a minimum reproduction of the issue.

Reproduction Summary

The README.md from the above repository has concise reproduction steps but to further simplify...

  • If you run lua-language-server --check . --logpath logs, it says that there are errors.
  • There is a .luarc.json in the repository
    • If you change the "workspace.library": ["annotations"] to "workspace.library": ["$PWD/annotations"]
  • If you run lua-language-server --check . --logpath logs again, it succeeds

To conclude, the relative path was not respected but the $PWD-prefixed path is.

Experiments with .gitmodules

I noticed that if you empty out the .gitmodules file or delete it completely, neither relative paths or absolute paths work. lua-language-server will treat any issues within busted / luassert as if they are errors in my project even though they're meant to be third-party.

Additional Notes

It would be very nice if lua-language-server removed the dependency on .gitmodules. A relative path to workspace.library and diagnostics.libraryFiles: "Disable" in my opinion should be all you need to provide for lua-language-server to know not to report diagnostics from there.

Additionally if we could allow relative paths so as to not need to add $PWD that would be nice.

Log File

{
    "file:///home/selecaoone/repositories/luals-example/./annotations/luassert/library/luassert/mock.lua": [
        {
            "code": "cast-local-type",
            "message": "This variable is defined as type `luassert.mock`. Cannot convert its type to `function`.\n- `function` cannot match `luassert.mock`\n- Type `function` cannot match `table`\n- Type `function` cannot match `luassert.mock`",
            "range": {
                "end": {
                    "character": 13,
                    "line": 15
                },
                "start": {
                    "character": 9,
                    "line": 15
                }
            },
            "severity": 2,
            "source": "Lua Diagnostics."
        }
    ],
    "file:///home/selecaoone/repositories/luals-example/./annotations/luassert/library/luassert/stub.lua": [
        {
            "code": "cast-local-type",
            "message": "This variable is defined as type `luassert.stub`. Cannot convert its type to `function`.\n- `function` cannot match `luassert.stub`\n- Type `function` cannot match `table`\n- Type `function` cannot match `luassert.stub`",
            "range": {
                "end": {
                    "character": 13,
                    "line": 12
                },
                "start": {
                    "character": 9,
                    "line": 12
                }
            },
            "severity": 2,
            "source": "Lua Diagnostics."
        }
    ]
}

A relative path to workspace.library and diagnostics.libraryFiles: "False" ...

I believe you have set this diagnostics.libraryFiles config incorrectly. ๐Ÿ˜•

outdated original comment

From the wiki: https://luals.github.io/wiki/settings/#diagnosticslibraryfiles, the options are:

  • "Enable" - Always diagnose library files
  • "Opened" - Only diagnose library files when they are open
  • "Disable" - Never diagnose library files

=> so instead of "False", you should use "Disable"


I have been using this config in my team's project for a while, and it is working as expected ๐Ÿค”
Here is the sample of my config:

{
    "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",

    // runtime setting
    "runtime.version": "Lua 5.4",
    "runtime.pathStrict": true,
    "runtime.path": [
        "lualib/?.lua"
    ],
    "workspace.library": [
        "meta/",
        "skynet/lualib/"
    ],

    // completely ignore files not belonging to workspace
    "diagnostics.ignoredFiles": "Disable",
    "diagnostics.libraryFiles": "Disable",
    "workspace.ignoreSubmodules": true,
    "workspace.ignoreDir": [
        ".luacheckrc",
        "config"
    ],
    ...
}

edit: from the original context that you provided, seems you have already set it correctly with Disable ๐Ÿค”

My bad I typoed that one part. As you mentioned I use Disable, not False. My actual (Neovim plugin) configuration looks like this

{
    "diagnostics.globals": [
        "vim"
    ],
    "diagnostics.libraryFiles": "Disable",
    "runtime.version": "LuaJIT",
    "workspace.checkThirdParty": "Disable",
    "workspace.library": ["$PWD/.dependencies"]
}

It's working as long as I include a (non-empty) .gitmodules. I edited the original post to be less confusing

Yeah, I followed the reproduction steps and confirmed it as well. ๐Ÿ‘


I just did a quick debugging and found something strange:

  • first I full searched where will read the diagnostics.libraryFiles, it's here:
    local function isValid(uri)
    if not config.get(uri, 'Lua.diagnostics.enable') then
    return false
    end
    if not ws.isReady(uri) then
    return false
    end
    if files.isLibrary(uri, true) then
    local status = config.get(uri, 'Lua.diagnostics.libraryFiles')

    This logic seems to be if the current uri is inside library path => check settings to see if it should be ignored
  • However for the file annotations/luassert/library/luassert/mock.lua, this if branch is not executing ?!
    => implies that files.isLibrary(uri, true) for this path is returning false
  • then I looked into files.isLibrary and check which line is returning false, it's this line:
    function m.isLibrary(uri, excludeFolder)
    if excludeFolder then
    for _, scp in ipairs(scope.folders) do
    if scp:isChildUri(uri) then
    return false
  • by adding some debug print, I get the following
click to expand logs
$ ~/.vscode/extensions/sumneko.lua-3.11.1-darwin-x64/server/bin/lua-language-server --check=.
Initializing ...file:///Users/tomlau10/projects/luals-example/./annotations/busted/library/busted.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/busted/library/busted.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
>>>================= 1/9file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/array.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/array.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/match.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/match.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/mock.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/mock.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/spy.d.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/spy.d.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/spy.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/spy.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/stub.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./annotations/luassert/library/luassert/stub.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./spec/test.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	[C]: in function 'xpcall'
	script/provider/diagnostic.lua:695: in upvalue 'callback'
	script/files.lua:992: in function <script/files.lua:991>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
file:///Users/tomlau10/projects/luals-example/./spec/test.lua
stack traceback:
	script/files.lua:157: in function 'files.isLibrary'
	script/provider/diagnostic.lua:252: in upvalue 'isValid'
	script/provider/diagnostic.lua:282: in function 'provider.diagnostic.doDiagnostic'
	script/cli/check_worker.lua:107: in upvalue 'callback'
	script/lclient.lua:129: in function <script/lclient.lua:128>
false due to:	{scope|folder|file:///Users/tomlau10/projects/luals-example/.}
Diagnosis complete, 2 problems found, see /Users/tomlau10/.vscode/extensions/sumneko.lua-3.11.1-darwin-x64/server/log/check.json

So the scp in question is the project root ?! ๐Ÿ˜ณ
Seems like when a library file path is under the project root, the files.isLibrary(uri, true) will always return false ??
(Because one of the scope.folders is the project root, the isChildUri will always return true for that case?)
But taking a step back, I have absolutely no idea what's the excludeFolder flag is doing in this logic at the moment. ๐Ÿ˜•

The details are a bit lost on me but if I can help test it please let me know. I tried making the change to lua-language-server but the setup on how to get started and quickly iterate on a solution weren't immediately apparent to me. Which is what prompted making this GitHub issue

but the setup on how to get started and quickly iterate on a solution weren't immediately apparent to me.

The main logic of luals reside on the script/ folder of this repo, I come up with the following way to quickly test some changes:

  1. clone this luals repo to local
  2. use a terminal and cd to ~/.vscode/extensions/sumneko.lua-{version}/server/
  3. mv script script.bak (for backup)
  4. and then make a symlink script -> {the cloned repo}/script
  5. now whenever I have made some changes in the cloned repo, I can reload vscode to see the new effect ๐Ÿ‘€ This bypass the need to locally build the luals binary before testing

I just used some raw debugging method, adding print() here and there ๐Ÿ˜‚
And then I can see the result on the Output tab of vscode. But I don't know if neovim has similar output tab or not ๐Ÿค” .

Hi @SweetSea-ButImNotSweet, I believe the ${addons} not working is another issue, please track it here:

And a fix seems to be on the way ๐Ÿ˜„