LuaLS / lua-language-server

A language server that offers Lua language support - programmed in Lua
https://luals.github.io
MIT License
3.24k stars 305 forks source link

3rd-party libraries annotation is not automatically loaded #940

Closed MikuAuahDark closed 2 years ago

MikuAuahDark commented 2 years ago

Describe the bug On opening new directory (project) in VSCode, 3rd-party library annotation is not automatically loaded. In this case, it's LOVE library.

Any code (always main.lua in my case) that has local love = require("love") doesn't load the LOVE annotation at first, but if the require("love") is retyped, the annotation is back. This is bit annoying to do everytime when opening my projects.

To Reproduce Reproducing this seems require a slightly larger workspace (and sadly mines are private), but thankfully my own livesim2 project can be used to reproduce this. You just need to tell VSCode to open the project to reproduce (but ensure the project is detected as LOVE project first). I've attached the log for this project.

Unfortunately, an empty project consist of main.lua that only contain local love = require("love") (which has been detected as LOVE project) doesn't seem get affected by this issue. I also have attached the log for this empty project too in case you need to compare the logs between.

Expected behavior LOVE library annotation should be loaded automatically on load, like the empty project described above.

Screenshots gambar

Environment (please complete the following information):

Additional context I slightly have no idea when this start to happend, as it seems it happends overnight to me.

I also have ${3rd}/love2d/library in my Lua.workspace.library workspace setting for both projects, so this can be ruled out.

Provide logs "livesim2" project log empty project log

lua-rocks commented 2 years ago

LOVE API is bigger than default limit. Try to add "Lua.workspace.preloadFileSize": 1000, to your config.

I downloaded your project but can't reproduce this.

screenshot

MikuAuahDark commented 2 years ago

My Lua.workspace.preloadFileSize is set to 65536, so that one also can be ruled out.

Also you must use the local love = require("love") line to reproduce it instead of pulling love from global namespace (I see in your screenshot that you comment out that line).

lua-rocks commented 2 years ago

Wait! I thought you were using this line to avoid the error. Otherwise it is not surprising because there is no library named love in your project.

You need to explicitly specify the type:

---@type love
local love = require("love")
lua-rocks commented 2 years ago

Your issue is not with the Sumneko server, but with the VSCode client. In Sublime Text, for example, the client is designed differently and it looks for required package API everywhere, although I personally think that VSCode behaves more correctly and more predictable.

screenshot

MikuAuahDark commented 2 years ago

If you didn't touch any of that require("love") line and keep it as-is and the annotation doesn't load, then you're affected by the issue. Now try to retype the require("love") part of that line and you'll see annotation suddenly comes back.

lua-rocks commented 2 years ago

Yes, you're right, it is strange behavior. But, as I said, it is observed only in vscode and only if you don't explicitly specify ---@type love. I think in this case, it is better to always specify the type, just to avoid scanning the entire project in search of a library that is not in it.

You could definitely call this a bug if your project contained files with the full love-api descriptions and the client didn't recognize them, but since the api is located outside your project, it's not surprising.

flrgh commented 2 years ago

Interesting. This seems to be the exact same behavior I described in #932. As to whether its an LSP client problem or a lua-language-server quirk, I'm sympathetic to both views (mostly because I don't feel I have sufficient understanding of either one :upside_down_face:).

As a user of lua-language-server and a common LSP client (neovim), here is what I would naturally expect to happen:

  1. Open file.lua in my editor
  2. Editor starts lua-language-server a. I've explicitly added /path/to/external/lib to Lua.workspace.library and /path/to/external/lib/?.lua to Lua.runtime.path
  3. file.lua contains the line local mod = require "my_module"
  4. Call textDocument/hover for mod.
  5. lua-language-server understands enough about lua to parse out that mod is equal to require "my_module" and that require means it needs to search for a module called my_module
  6. lua-language-server searches Lua.workspace.library and/or Lua.runtime.path, eventually locating /path/to/external/lib/my_module.lua
  7. lua-language-server returns the appropriate typedefs/enhancements from /path/to/external/lib/my_module.lua a. If /path/to/external/lib is in Lua.workspace.library, ideally this file was preloaded and can be returned from memory/cache b. If /path/to/external/lib/?.lua is in Lua.runtime.path, the file is read and parsed, and the results are probably cached

This seems like a logical and reasonable expectation to me, but it's possible I'm missing something.

Re: @lua-rocks comment:

I think in this case, it is better to always specify the type, just to avoid scanning the entire project in search of a library that is not in it.

I agree, but I do not own all codebases that I work on, and some of them do not use/allow EmmyLua style annotations.

lua-rocks commented 2 years ago

@flrgh

I do not own all codebases that I work on, and some of them do not use/allow EmmyLua style annotations.

In such cases I keep this code in a directory which is added to exceptions so that neither luacheck nor lsp tries to scan them. I require these libraries in a separate directory and I write the annotations there:

/git/ is ignored and inspect placed there as submodule:

"Lua.workspace.ignoreDir": [".**", "git"]

require inspect from /lib/:

---@class lib.any.inspect-options:table
---@field depth integer? sets the maximum depth that will be printed out
---@field newline string? add custom newline each level of a table
---@field indent string? add an indent each level of a table
---@field process fun(...): any? additional handler

---Returns any lua variable in human-readable format.
---@alias lib.any.inspect fun(variable:any, options: lib.any.inspect-options): string

---@type lib.any.inspect
local inspect = require("git.inspect.inspect")
return inspect

https://github.com/lua-rocks/love-template/tree/main/git https://github.com/lua-rocks/love-template/tree/main/lib/debug/inspect

sumneko commented 2 years ago

Sorry for the late reply, I just finished the Chinese New Year holiday. Thank you very much for providing a reproducible project, I tried to fix it, please help to test if this version fixes your problem: https://github.com/sumneko/lua-language-server/actions/runs/1811303949

MikuAuahDark commented 2 years ago

I tried it and now everything works as intended, thanks.