Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow plugins to resolve require paths #2590

Merged
merged 1 commit into from
Apr 16, 2024
Merged

Allow plugins to resolve require paths #2590

merged 1 commit into from
Apr 16, 2024

Conversation

zziger
Copy link
Contributor

@zziger zziger commented Mar 30, 2024

This PR allows plugins to manually resolve require('...') file paths. It adds ResolveRequire plugin method, that accepts workspace URI and require name, and can return resolved paths to Lua files.

This feature would be helpful for environments that implement custom require name resolution, as it provides max flexibility and can be added with an addon.

Example usage

---@param uri string
---@param name string
---@return nil|string[]
function ResolveRequire(uri, name)
  if name:byte(1) ~= 0x40 --[['@']] then
      return nil
  end

  return { "file:///path/to/mods/" .. name:sub(2) .. "/main.lua" }
end

@Frityet
Copy link
Contributor

Frityet commented Apr 3, 2024

This would be really useful 👍 Could this possibly a coroutine function? I created a require loader that lets me download files from online

local pprint = require("https://raw.githubusercontent.com/jagt/pprint.lua/master/pprint.lua")

and I would like to make it yield while its downloading so it doesnt slow down the language server

@zziger
Copy link
Contributor Author

zziger commented Apr 4, 2024

This would be really useful 👍 Could this possibly a coroutine function? I created a require loader that lets me download files from online

local pprint = require("https://raw.githubusercontent.com/jagt/pprint.lua/master/pprint.lua")

and I would like to make it yield while its downloading so it doesnt slow down the language server

@Frityet
I feel like it would be more beneficial when implemented by the plugin itself. As the function gets called by the language server pretty frequently, you could start and cache a coroutine on first call, and then return empty array or the result depending on whether coroutine finished it's execution. That way you have more control over pending coroutines you have, rather than if that was implemented in the API itself caching e.g. by require name.

@zziger
Copy link
Contributor Author

zziger commented Apr 4, 2024

Here's a very hacky workaround to use this feature before PR gets merged:

There is a possibility to monkey patch the API from plugin, put this code somewhere in the plugin Lua file, and then define the ResolveRequire function as described in the PR

local scope = require('workspace.scope')
local rpath = require('workspace.require-path')
local plugin = require('plugin')

local scp = scope.getScope(scope.folders[1].uri)
rpath.getVisiblePath(scp.uri, 'fallback')
local mgr = scp:get('requireManager')
local mt = getmetatable(mgr)
local old_fn = mt.searchUrisByRequireName
function mt:searchUrisByRequireName(name)
    local pluginSuccess, pluginResults = plugin.dispatch('ResolveRequire', self.scp.uri, name)
    if pluginSuccess and pluginResults ~= nil then
        return pluginResults
    end
    return old_fn(self, name)
end

Even though this works, I do not recommend using hacky tricks like that in a production environment, since this will easily break with any LuaLS update

@Frityet
Copy link
Contributor

Frityet commented Apr 4, 2024

This would be really useful 👍 Could this possibly a coroutine function? I created a require loader that lets me download files from online

local pprint = require("https://raw.githubusercontent.com/jagt/pprint.lua/master/pprint.lua")

and I would like to make it yield while its downloading so it doesnt slow down the language server

@Frityet

I feel like it would be more beneficial when implemented by the plugin itself. As the function gets called by the language server pretty frequently, you could start and cache a coroutine on first call, and then return empty array or the result depending on whether coroutine finished it's execution. That way you have more control over pending coroutines you have, rather than if that was implemented in the API itself caching e.g. by require name.

Yeah, I am planning on caching it, but on the first GET it could be quite slow, especially if many different modules have url requires

@sumneko
Copy link
Collaborator

sumneko commented Apr 16, 2024

Great, thank you!

@sumneko sumneko merged commit bfe6618 into LuaLS:master Apr 16, 2024
5 of 10 checks passed
@C3pa
Copy link
Contributor

C3pa commented Apr 16, 2024

We've been getting very nice PRs lately. Sumneko, would you consider if we'd add some instructions for contributors to describe the feature they are working on in the changelog? It would be a shame if these things went under users' radar.

@sumneko
Copy link
Collaborator

sumneko commented Apr 17, 2024

We've been getting very nice PRs lately. Sumneko, would you consider if we'd add some instructions for contributors to describe the feature they are working on in the changelog? It would be a shame if these things went under users' radar.

Sure!

@sumneko
Copy link
Collaborator

sumneko commented Apr 22, 2024

if we'd add some instructions

I thought you were coming to write…

@C3pa
Copy link
Contributor

C3pa commented Apr 22, 2024

Oh, sorry, I can write something this weekend. Should I add a Contributing paragraph to the project's readme file (https://github.com/LuaLS/lua-language-server/blob/master/README.md) or add a new contributing article on the project's wiki (https://luals.github.io/wiki/)?

@sumneko
Copy link
Collaborator

sumneko commented Apr 22, 2024

Should I add a Contributing paragraph to the project's readme file (https://github.com/LuaLS/lua-language-server/blob/master/README.md) or add a new contributing article on the project's wiki (https://luals.github.io/wiki/)?

You are free to decide.

@carsakiller
Copy link
Collaborator

@C3pa, I can help if you'd like 🙂

The wiki's development guide page definitely needs an overhaul, but I'm not sure what it should contain exactly. Adding a whole new page to cover all the different ways (not just developing) to contribute would be great, too.

@C3pa
Copy link
Contributor

C3pa commented Apr 22, 2024

I think the wiki would be the best place for this. IMHO, the contributing article could have three sections:

  1. Contributing code (I haven't made this kind of contribution to the project, so I am not eligible to write this section):
    • dependencies & setting up the development environment
    • build process
    • code style, naming conventions
  2. Contributing LuaCATS annotations with a link to: https://github.com/LuaLS/LLS-Addons
  3. Contributing translations

I welcome any help or suggestions, especially in the code contributions section. I am going to open a draft PR during the weekend at the wiki repo, and we can discuss the details there.

Edit: I've now seen the wiki has quite a bit of what I mentioned.

@carsakiller
Copy link
Collaborator

Great!

I also have not contributed code. I have built from source, edited some files, and messed around a bit, but I definitely don't have a good understanding of Sumneko's workflow, or what the best one would be. Code style is something I didn't even think of. I'm not sure whether there really is a code style enforced, or even preferred.

I think it is mainly the developing page that needs some attention, and then maybe we want a section on the wiki homepage that points to all the different articles on how one can contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants