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

Convert between LuaLs annotation comments and Luau type annotations #184

Open
itsfrank opened this issue Mar 27, 2024 · 2 comments
Open

Comments

@itsfrank
Copy link

itsfrank commented Mar 27, 2024

Hi, first off, I recognize this is quite the undertaking, so I don't really expect any work to be done until enough people have real use cases for it and someone feels passionate about building it.

But I was curious if it was ever considered to convert between the two different type systems, and wanted to start a conversation / create an issue documenting the topic that others can find in the future.

My current scenario

I want to write a Lua/Luau library that is not coupled Roblox but can be used in Roblox. I would like to make it available in both Lua 5.1 and Luau. In either case, I would love if my users could benefit from the appropriate LSP (lua-ls for Lua, and luau-lsp for Luau).

My plan is to develop the library using tests that are executed by either Luvit or Lune depending on which flavor I choose to develop in (to maximize compatibility, it is probably better to develop in Lua 5.1).

Then, to "release" I would use this wonderful project to convert from whichever dialect I use for development to the other; e.g. convert the Lua 5.1 library to Luau with Roblox-style requires.

However, critically, regardless of which way I convert, the non-development dialect will lose typing information. Say I use LuaLs annotations, my Luau code will have no typing, or if I use Luau, the Lua 5.1 code will have no typing.

Hence, why typing conversion would be very useful in my case.

LuaLs vs Luau type annotations

I suspect users/maintainers of this project are quite familiar with Luau typing, but some may not be familiar with LuaLs.

LuaLs uses doc-comment like type annotation to provide LSP features that are mostly on-par with Luau typing LSP features. The LuaLs annotation have been embraced by large Lua communities like the Neovim plugin community.

LuaLs annotation documentation

For example, this Luau code:

function string_coord(x: number, y: number): string
    return tostring(x) .. "," .. tostring(y)
end

Has equivalent typing information to the following Lua 5.1 code when using LuaLs:

---@param x number
---@param y number
---@return string
function string_coord(x, y)
    return tostring(x) .. "," .. tostring(y)
end

It would be great for the larger Lua ecosystem to have a tool that can generate the annotations of one dialect by parsing the other and darklua seems like the best project for this functionality!

@jeparlefrancais
Copy link
Contributor

Hello 👋 Thanks for taking the time to submit a detailed issue!

This is definitely an interesting feature! I think it fits in darklua because even if it is not quite there yet, it still tries to help the fragmentation of the Lua ecosystem. First thing I built around that was removing some Luau specific statements (like += statements) and types. The next bigger thing I built was supporting path-requires and converting them to Roblox requires, which opened up previously Roblox-focused projects to become more flexible.

So yes I'm definitely open to the idea!

Here are some thoughts I have:

  • does the LuaLS have some other mechanism to load up types? like some kind of type definition file?
  • I think I would suggest developing in Luau and generating LuaLS comments with darklua
    • to maximize compatibility, I would:
      • avoid specific control flow statements that do not exist in the Lua flavors you're supporting (example: the continue statement). Those are trickier to convert
      • push non standard APIs behind interfaces and use a global to branch per Lua target. In the libraries I build for Roblox and Lune, I use a _G.LUA_ENV global to define the target (roblox or lune). I branch stuff when I need the task library (because roblox has it builtin but in lune I have to require it) or something that read json
    • the other way around seems a lot harder because you'd have to rebuild something to parse the LuaLS type syntax in Rust to then build the Luau types. It seems easier to generate the comment token from a Luau type instead

Let me know your thoughts on this 🙂

@itsfrank
Copy link
Author

itsfrank commented Apr 5, 2024

does the LuaLS have some other mechanism to load up types? like some kind of type definition file?

It seems so, the documentation can be found here. I have actually never written one myself before, but it seems like a file that contains annotation comments with the ---@meta annotation at the top.

Just tried it out and it LuaLs can find them with just a simple require (it can also be passed directly to the server, there's a section on that in the doc page linked above)

E.g. with a file coord.lua:

---@meta

--- A point on a 2D plane
---@class Coordinate
---@field x number the horizontal component
---@field y number the vertical component

---@class Coord
Coord = {}

---@return Coordinate
function Coord.make_coord(x, y) end

Here is a screenshot of the hover info for the function in neovim with lua-ls:

image

And here is one of the Coordinate type's hover info:

image

I will need more time to tinker to find the gaps between the way Luau definitions are used and what is possible with LuaLs annotations, but this little test is quite promising.


avoid specific control flow statements that do not exist in the Lua flavors you're supporting

This was actually the reason I thought developing in Lua 5.1 would be good, since both Luau and Luajit (what neovim uses) are supersets of 5.1, using unsupported stuff should not be possible.

But you bring up great points about reimplementing luals parsing syntax in rust, that sounds quite impractical. LuaLs is written entirely in Lua though, it might be possible to extract its annotation parser and run it in a lua interpreter in the rust process? Though I'm not sure how feasible that would be, I tried contributing to LuaLs previously and the repo proved too complex for the time I had on hand.

I think I fully agree that the first version of any sort of Luau/LuaLs type conversion should be from Luau to LuaLs.

Also, I really appreciate the tips on writing multi-flavour modules, that will be super helpful

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

No branches or pull requests

2 participants