Skip to content

Breaking changes in 3.X #980

Open
Open

Description

@sumneko

Introduce

I'm working on the 3.X version, the purpose is to add a more complete type system, and use this to implement features such as type checking.
In previous versions I tried to keep the type system compatible with EmmyLua, but I will make some breaking changes after version 3.X, so the type system may not be suitable to continue to be called EmmyLua in the future, but I haven't thought about it yet, I will call it LuaDoc for now.

Breaking changes

Always trace local set

local x
x = 1
x = true
print(x) --> x is `integer|boolean`
---@type string
local x
x = 1
x = true
print(x) --> x is `string`
local x = 'str'
x = 1
x = true
print(x) --> x is `string`

Dose not trace field inject

local x = {}
local y = x
y.field = 1

print(x.field) --> undefined field `field`

use ---@class instead

---@class MyClass
local x = {}
---@class MyClass
local y = x
y.field = 1

print(x.field) --> `x.field` is `1`

Finding definition does not recurse

local t = {}
t.x = 1
t.y = t.x

print(t.y) --> t.y is `1`

Find definition of t.y will not find out t.x

---@class C
local mt = {}

---@type C
local o

Find definition of o will not find out mt

Type unknown

local t = {}
print(t.x) --> t.x is `unknown` instead of `any`

Types can be used in doc-table keys

---@type { [number]: string }
local t

print(t[1]) --> t[1] is `string`
print(t.x) --> t.x is `unknown`

boolean type true and false

You can use ---@type { [string]: true } now.

class and alias support generic inheritance

---@class table<K, V>: { [K]: V } --> this is builtin

---@alias mark<K> { [K]: true } 

table<integer, string> can not convert to string[]

Default value of unrary and binary

---@type unknown
local x

local y = - x --> y is `number` instead of `unknown`

unknown can form union types with other types

function f()
    if x then
        return y
    else
        return nil
    end
end

local n = f() --> n is `unknown|nil`

Integer type

---@type 1|2|3|4|5
local v

doc-enum must be a string

---@param x 'aaa'|'bbb'
function f(x)
    print(x) --> x is `"aaa"` or `"bbb"`
end

This means you can no longer use ---@param x '1024'|'true'|'function () end' to represent a specific number, boolean or function. Use ---@param x 1024|true|fun() instead.
For compatibility, I will continue to recognize '"xxx"' as the string xxx instead of "xxx".

integer is a class in Lua 5.1 and Lua 5.2

---@type integer
local v

print(v) --> v is `integer` instead of `number`

Although Lua 5.1 and Lua 5.2 runtimes do not have integer, many API parameters require a number that can be converted to an integer, so adding integer to the type system can help you handle this part.

Not supported for now

search metatable in this case

setmetatable(object, { __index = {
    default = 1
} })
print(object.default) --> undefined field `default`

This turns the reference into a definition, and checking the reference in order to search for a definition is too expensive.

Please use ---@class or use this:

object = setmetatable(object, { __index = {
    default = 1
} })
print(object.default) --> this is OK

Maybe can be resolved by indexing setmetable

Activity

  1. pinned this issue on Mar 10, 2022
  2. XeroOl commented on Mar 29, 2022

    @XeroOl

    I think LuaDoc name is taken by https://keplerproject.github.io/luadoc/

  3. sumneko commented on Mar 30, 2022

    @sumneko
    CollaboratorAuthor

    I think LuaDoc name is taken by https://keplerproject.github.io/luadoc/

    Maybe I can continue to call it Emmylua, since the original author is not active, then I can grab it 🙃.

  4. sumneko commented on Apr 8, 2022

    @sumneko
    CollaboratorAuthor

    I have merged a 3.0 branch to Master, if you find a major problem, you can return to the label 2.6.8

  5. faimin commented on Apr 10, 2022

    @faimin

    The CPU usage of the latest plugin version (v3.0.0) in VSCode is full.

    新版本插件(v3.0.0)在VSCode 中CPU爆满

    ENV: 
    MacOS 12.3.1
    VSCode  1.66.1
    Lua 5.4
    
  6. Silent-zzz commented on Apr 10, 2022

    @Silent-zzz

    多个文件声明类的方法该怎么写呢

  7. Silent-zzz commented on Apr 10, 2022

    @Silent-zzz

    例如
    image

  8. sumneko commented on Apr 10, 2022

    @sumneko
    CollaboratorAuthor

    The CPU usage of the latest plugin version (v3.0.0) in VSCode is full.

    新版本插件(v3.0.0)在VSCode 中CPU爆满

    ENV: 
    MacOS 12.3.1
    VSCode  1.66.1
    Lua 5.4
    

    请单独开个issue并提供日志

  9. sumneko commented on Apr 10, 2022

    @sumneko
    CollaboratorAuthor

    多个文件声明类的方法该怎么写呢

    你可以多次使用 ---@class unit

  10. firas-assaad commented on Apr 10, 2022

    @firas-assaad
    Contributor

    Thanks for the great server/extension!

    With the latest version of the VS Code extension (3.0.0) I get a lot of undefined field errors in classes. e.g.

    image

    I actually use middleclass for classes, but that used to work fine in previous versions. Is this the same unsupported case as "find definition in methods"?

    As I use classes heavily, this is raising a lot of warnings. Is there a workaround or do you recommend that I revert to a previous 2.X version?

  11. sumneko commented on Apr 10, 2022

    @sumneko
    CollaboratorAuthor

    Thanks for the great server/extension!

    With the latest version of the VS Code extension (3.0.0) I get a lot of undefined field errors in classes. e.g.

    image

    I actually use middleclass for classes, but that used to work fine in previous versions. Is this the same unsupported case as "find definition in methods"?

    As I use classes heavily, this is raising a lot of warnings. Is there a workaround or do you recommend that I revert to a previous 2.X version?

    You can choose:

    1. Use ---@field field boolean under ---@class x
    2. Revert to 2.X
    3. Waiting for supporting this case, maybe next week
  12. added a commit that references this issue on Apr 16, 2022
  13. sumneko commented on Apr 17, 2022

    @sumneko
    CollaboratorAuthor
    function mt:init()
        self.xxx = 1
    end

    Supported finding definition of self.xxx in version 3.1.0

  14. Arxareon commented on May 24, 2022

    @Arxareon

    I think this issue we found all links to here: #1158

    I'd very much like to have the old functionality from 2.6.8 back. There are fringe cases in WoW addon development (addon namespace tables as an example) where field references being pulled through tables and subtables are very much needed. I tried adding @class and @field definitions to rectify the issue, but I wasn't able to fix annotations and types in all cases. Also, I wouldn't like adding more unnecessary lines to the already long files just to have annotations working between all files of a project.

    See the above mentioned issue and further quoted issue from Ketho's WoW API extension repo (also mentioned within the above mentioned issue).

    Thank you for working on this! :)
    If you need details on how we use it specifically for WoW or have tips for us to change our workflow, I'd be happy to get back to you on that.

  15. SalavatR commented on Oct 31, 2022

    @SalavatR
    Contributor

    Thanks for the great server/extension!
    With the latest version of the VS Code extension (3.0.0) I get a lot of undefined field errors in classes. e.g.
    image
    I actually use middleclass for classes, but that used to work fine in previous versions. Is this the same unsupported case as "find definition in methods"?
    As I use classes heavily, this is raising a lot of warnings. Is there a workaround or do you recommend that I revert to a previous 2.X version?

    You can choose:

    1. Use ---@field field boolean under ---@class x
    2. Revert to 2.X
    3. Waiting for supporting this case, maybe next week

    Hello!
    is any update for this issue?

    
    ---@class my_window
    
    ---@param self my_window
    local function lcf1(self)
       local a = self.variable ----- Undefined field `variable`.Lua Diagnostics.(undefined-field)
    end
    
    ---@param self my_window
    function init(self)
       self.variable = true
       lcf1(self)
    end
    

    in some cases we have more about 100 variables in self, and it is not comfortable to declare all as ---@field

  16. Arxareon commented on Nov 1, 2022

    @Arxareon

    @SalavatR
    I've reverted to using version 2.6.8 until this gets resolved without needing to use excessive documentation for references to be recognized. It works fine for me even though I wish I had some of the new features available as well (like the recognition of aliases - but I can always collapse them manually now) - so unless you need something new, I suggest reverting the extension back to 2.6.8 for the time being (not sure if sumneko is planning to revert any of these changes in one way or another, so it might be indefinitely).

  17. sumneko commented on Nov 2, 2022

    @sumneko
    CollaboratorAuthor

    in some cases we have more about 100 variables in self, and it is not comfortable to declare all as ---@field

    You can use

    ---@param self my_window
    function init(self)
        ---@class my_window
        self = self
        self.variable = true
        lcf1(self)
    end

    This is to prevent fields from being declared unexpectedly.

  18. SalavatR commented on Nov 2, 2022

    @SalavatR
    Contributor

    in some cases we have more about 100 variables in self, and it is not comfortable to declare all as ---@field

    You can use

    ---@param self my_window
    function init(self)
        ---@class my_window
        self = self
        self.variable = true
        lcf1(self)
    end

    This is to prevent fields from being declared unexpectedly.

    Thanks!
    What about performance of this?
    And will LLS analize all of usings of param?

  19. sumneko commented on Nov 2, 2022

    @sumneko
    CollaboratorAuthor

    @SalavatR LLS only analize fields in ---@class, this is both strict and performance oriented.

  20. Iyadriel commented on Nov 14, 2022

    @Iyadriel

    @SalavatR I've reverted to using version 2.6.8 until this gets resolved without needing to use excessive documentation for references to be recognized. It works fine for me even though I wish I had some of the new features available as well (like the recognition of aliases - but I can always collapse them manually now) - so unless you need something new, I suggest reverting the extension back to 2.6.8 for the time being (not sure if sumneko is planning to revert any of these changes in one way or another, so it might be indefinitely).

    I was able to make references across namespaces work in the latest version by simply using the following syntax in every file:

    ---@class ns
    local ns = select(2, ...)

    Does this work for you?

    Edit -- Never mind, this only seems to work for a depth of one level.

  21. bandaloo commented on Jan 28, 2023

    @bandaloo

    @SalavatR I've reverted to using version 2.6.8 until this gets resolved without needing to use excessive documentation for references to be recognized. It works fine for me even though I wish I had some of the new features available as well (like the recognition of aliases - but I can always collapse them manually now) - so unless you need something new, I suggest reverting the extension back to 2.6.8 for the time being (not sure if sumneko is planning to revert any of these changes in one way or another, so it might be indefinitely).

    I was able to make references across namespaces work in the latest version by simply using the following syntax in every file:

    ---@class ns
    local ns = select(2, ...)

    Does this work for you?

    Edit -- Never mind, this only seems to work for a depth of one level.

    it would be really nice to have a @namespace instead of having to use @class for simple modules. it is a little funky to mark a table as @class when you're not interested in using it as a type or instantiating it, and it makes no reference to self. if you don't use @class, it's easy to make a typo and access a field that doesn't exist; it will be treated as unknown. @class does the job though! it's just slightly more feature-rich than what i want most of the time.

  22. gynt commented on Apr 7, 2025

    @gynt

    Will this break compatibility with sphinx-lua? https://github.com/boolangery/sphinx-lua

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    planPlanning from the devs

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions