seaofvoices / darklua

A command line tool that transforms Lua code
https://darklua.com/
MIT License
67 stars 8 forks source link

Convert between LuaLs annotation comments and Luau type annotations #184

Open itsfrank opened 3 months ago

itsfrank commented 3 months ago

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 commented 3 months ago

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:

Let me know your thoughts on this 🙂

itsfrank commented 3 months ago

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