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

`inject-field` error (`exact`) is not working as expected? #2710

Closed Rathoz closed 3 months ago

Rathoz commented 3 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?

Type Checking

Expected Behaviour

Based on the wiki https://luals.github.io/wiki/annotations/#class I would expect that inject-field error only show up if exact is provided the class annotation

Actual Behaviour

Classes without exact gets inject-field error

Reproduction steps

---@class Foo
---@field a string
local Foo = {}

---@return Foo
function Foo.new()
    return {a = 'abc'} -- Pretend this make a proper new object or smt
end

local function doSomething()
    local foo = Foo.new()
    foo.bar = 'baz' --- Fields cannot be injected into the reference of `Foo` for `bar`. To do so, use `---@class` for `foo`. Lua Diagnostics.(inject-field)
end

Additional Notes

No response

Log File

No response

tomlau10 commented 3 months ago

I would expect that inject-field error only show up if exact is provided the class annotation

Nope. This is the normal behavior. Basically You can declare class fields in 2 ways:


---@return Foo function Foo.new() -- method2: you are adding a new() function field to the class Foo return {a = 'abc'} -- Pretend this make a proper new object or smt end

- On the other hand, `---@class (exact)` means that you can only use **method 1** (`---@field`) to declare fields/function/methods of a class. That is if you write `---@class (exact) Foo`, your `function Foo.new` will already throw this `inject-field` warning.

---
A few ways to tackle this warning:
- declare the `bar` field in `---@class Foo`
- Add `---@class` for `foo` (as stated by the warning)
```lua
local function doSomething()
    ---@class Foo
    local foo = Foo.new()
    ...
end

The last one is probably not a good idea, because in this case, LuaLS actually DOES NOT KNOW that Foo class has the field bar, and you can't do those goto defintion thing for this field.

Rathoz commented 3 months ago

Then the docs probably needs to be updated as they state

Marking the class as (exact) means fields cannot be injected after the definition.

With the example used as

---@class (exact) Point
---@field x number
---@field y number
local Point = {}
Point.x = 1 -- OK
Point.y = 2 -- OK
Point.z = 3 -- Warning
tomlau10 commented 3 months ago

I think the example that you quoted from wiki is perfectly fine? It strictly follows the rule "fields cannot be injected after the definition"


In my own opinion, there is indeed a difference between a class and an instance.

Rathoz commented 3 months ago

Alright, fair.

I still think the documentation should be clarified