Open max397574 opened 1 year ago
Currently, you can achieve this if you create a new class for the cat field:
---@class catClass
---@field name string the name of the cat
---@field age integer the age of the cat
---@class someClass
---@field cat catClass
---@field ...
yes but for my usecase this isn't quite a good way of doing it since the "classes" actually don't have a name they should be inline
since the "classes" actually don't have a name
Mind elaborating a bit on this?
If I understood correctly, you don't want to define the catClass
because it doesn't exist in real Lua code?
yes
Well, why not? That's how many do it. In the end, the annotations are just comments. These affect just your autocomplete suggestions, not code behavior.
I haven't come up with a better syntax yet. For example, in the solution you provided, I can't decide where the comment ends.
(Translated by ChatGPT)
could this perhaps be done when you spread the thing to multiple lines similarly to how it's possibel to add descriptions to enums? @sumneko
Hello, i am also very interested in this feature. In my use case there are many functions that have "named arguments" they just receive a table as first arg and take the values from there. If someone wants to give me pointers where to start i would be glad to help implement this.
I haven't come up with a better syntax yet. For example, in the solution you provided, I can't decide where the comment ends.
(Translated by ChatGPT)
Maybe you could support syntax such as this:
-- Leading whitespace is insignificant and removed/ignored by the LSP.
-- Also if a line ends with `,` or `;`, ignore/remove it from the description as well.
---@field cat {
--- name: string the name of the cat
--- age: integer the age of the cat
---}
---@param cat {
--- name: string the name of the cat,
--- age: integer the age of the cat,
---}
Then just keep a count of balanced braces to find the end.
Or, maybe:
---@field cat {
--- @field name string the name of the cat
--- @field age integer the age of the cat
---}
---@param cat {
--- @field name string the name of the cat
--- @field age integer the age of the cat
---}
Using a @class
would be better. As otherwise with @alias
or literal table structure annotation, it would lead to this issue: https://github.com/LuaLS/lua-language-server/issues/2785#issuecomment-2270556775, where the whole table structure get expanded during hover preview / set type inline hint 😇
I understand the argument here that the cat
just a field with a specific table value, and is not a class
. But in LuaLS class
is just a type container. If the concern is not wanting to pollute the class types list, we may use namespaces in class names, just like what the luv
library did: https://github.com/LuaCATS/luv/blob/3615eb12c94a7cfa7184b8488cf908abb5e94c9c/library/types.lua#L74-L96
---@class uv.fs_stat.result.time
---@field sec integer
---@field nsec integer
---@class uv.fs_stat.result
---
---@field dev integer
---@field mode integer
---@field nlink integer
---@field uid integer
---@field gid integer
---@field rdev integer
---@field ino integer
---@field size integer
---@field blksize integer
---@field blocks integer
---@field flags integer
---@field gen integer
---@field atime uv.fs_stat.result.time
---@field mtime uv.fs_stat.result.time
---@field ctime uv.fs_stat.result.time
---@field birthtime uv.fs_stat.result.time
---@field type string
uv.fs_stat
is a library functionuv.fs_stat.result
is the return value of that functionclass
there are some time
table fields, which is defined as uv.fs_stat.result.time
uv.fs_stat.result
has another date
table with year, month, day
, we may write it as a separate class
---@class uv.fs_stat.result.date
---@field year integer
---@field month integer
---@field day integer
(instead of ---@field date { year: integer, month: integer, day: integer }
under uv.fs_stat.result
)
I totally agree with tomlau10 here. We do the same in MWSE: https://github.com/MWSE/MWSE/blob/master/misc/package/Data%20Files/MWSE/core/meta/lib/tes3.lua#L34 For a function with the following signature, we do the annotations like this:
--- @param params tes3.addArmorSlot.params
function tes3.addArmorSlot(params) end
---Table parameter definitions for `tes3.addArmorSlot`.
--- @class tes3.addArmorSlot.params
--- @field slot number Armor slot number. A number greater than 10 to configure a slot for.
--- @field name string The human-readable name for the armor slot.
--- @field key string? *Optional*. The key placed in the `tes3.armorSlot` table. If no key is provided, the name will be used.
--- @field weight number? *Default*: `0`. A stand-in for the armor base weight value, typically controlled by a GMST (e.g. iHelmWeight).
--- @field scalar number? *Default*: `0.1`. A multiplier with range 0.0-1.0 that controls how much of an item's armor value applies to a character's overall armor rating. For comparison, standard chest armor uses 0.3, helmets, greaves and pauldrons use 0.1, and gauntlets use 0.05.
The current convention is to just come up with a name and create classes (unless you only have 2-3 fields and are sure that you don't need descriptions), but it still might be nice to have a shorthand for certain cases (mainly function args/kwargs where the table type is unique and has a small number of fields that need descriptions). It's effectively an anonymous type, or an extension of a function's type/signature. But it's not a necessary feature and we can do without it for now (since we have the @class
workaround).
Is there a reason something like this wouldn't be a good idea for a small number of fields that are functioning as named arguments?
--- @param opts table ...
--- @param opts.name string ...
--- @param opts.age integer ...
or
--- @param opts table ...
--- @field opts.name string ...
--- @field opts.age integer ...
This would maintain nearly the same annotation conventions without adding a lot of complexity for cases when there are only 2–3 fields.
Classes certainly work, but it feels like it adds a level of visual noise and the cognitive load that may not be necessary. I'd prefer to be able to read through it linearly without bouncing between different annotation blocks
Is there a reason something like this wouldn't be a good idea for a small number of fields
Here maybe the problems (just my guess)
@field
is specifically for @class
, and not all @param
are of table
type. What if you write @field
after a non table type param? should it throw error?
---@param opts integer
---@field opts.name string ???
@field
syntax, it must specify the field name, instead of a table index syntax opts.name
. Because this field is attached to the @class
type above. Otherwise this complicates the things if your @param
name doesn't match with what you write in @field
:
---@param optsA table
---@field optsB.name string ???
opts
is a multi level table?
---@param opts table
---@field opts.a table
---@field opts.b table
---@field opts.a.name integer ???
---@field opts.b.name integer ???
the complexity here seems exponential 😅
I expect something like this or something similar to this to work but it doesn't also when I e.g. split it up onto multiple lines
everything is working fine without the descriptions