LuaLS / lua-language-server

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

Multiple return values for fields #2357

Open ChloeDawn opened 12 months ago

ChloeDawn commented 12 months ago

How are you using the lua-language-server?

Visual Studio Code Extension (sumneko.lua)

Which OS are you using?

Windows

What is the issue affecting?

Annotations

Expected Behaviour

The ability to define multiple return values for a field annotation.

Actual Behaviour

Any non-identifier symbol following a type is treated as a comment or a break.

Reproduction steps

  1. Create a field with a comma separated return type.
  2. See that anything following the comma is treated as a comment.

Additional Notes

---@class Color
---@field [string] Color,string
Color = {}

,string is highlighted as a comment.

---@class Color
---@field [string] Color, string
Color = {}

, is highlighted as a symbol, string is highlighted as a comment.


An example of fields with multiple return types are the named color lookups in the Tabletop Simulator API: https://api.tabletopsimulator.com/color/#colorblue

local color, name = Color.Blue
print(color) -- Color: Blue { r = 0.118, g = 0.53, b = 1, a = 1 }
print(name) -- Blue

local color, name = Color.Red
print(color) -- Color: Red { r = 0.856, g = 0.1, b = 0.094, a = 1 }
print(name) -- Red

Log File

No response

ChloeDawn commented 12 months ago

It would be great to see multiple type support for aliases too, as then we could represent event APIs such as ComputerCraft's event polling system with strong typing.

https://tweaked.cc/event/mouse_up.html

---@alias mouse_up string, number, number, number

--Possibly with naming support too for documention purposes?
--e.g. @alias mouse_up string event, number button, number x, number y

---@generic E
---@param event `E`
---@return E
function os.pullEvent(event) end
while true do
  local event, button, x, y = os.pullEvent("mouse_up")
  print(("The mouse button %s was released at %d, %d"):format(button, x, y))
end

This suggestion seems to encounter the problem documented in https://github.com/LuaLS/lua-language-server/issues/2355

carsakiller commented 12 months ago

Hello 👋

You can specify multiple types for a @field using a union, like so:

---@class Color
---@field color Color|string
local color = {}

or if you want it to work for all keys:

---@class Color
---@field [string] Color|string
local color = {}

It also works for @alias:

---@alias eventName "mouse_down"|"mouse_up"|number

---@param eventName eventName
local function fire(eventName) end

fire("mouse_down")

Note however that the language server does not yet have the capability to narrow the type given more context: https://github.com/LuaLS/lua-language-server/issues/1456. This is exactly what is preventing me from documenting all the events for the CC:Tweaked addon.

checkraisefold commented 11 months ago

It would be great to see multiple type support for aliases too, as then we could represent event APIs such as ComputerCraft's event polling system with strong typing.

https://tweaked.cc/event/mouse_up.html

---@alias mouse_up string, number, number, number

--Possibly with naming support too for documention purposes?
--e.g. @alias mouse_up string event, number button, number x, number y

---@generic E
---@param event `E`
---@return E
function os.pullEvent(event) end
while true do
  local event, button, x, y = os.pullEvent("mouse_up")
  print(("The mouse button %s was released at %d, %d"):format(button, x, y))
end

This suggestion seems to encounter the problem documented in #2355

Trying to make a hooking system with differing callbacks for a set of hooks was actually what lead me to discover #2355; I was attempting to have a bunch of aliases for the hook types, capture them with a generic parameter, and use them in the next parameter (which didn't work).

The main issue there is that generic capture parameters only seem to work for @return and not in other, successive parameters, so I don't think these issues are related in cause, only by what the target use-case is.