-
Suppose I want to write a vector class, which has a few functions defined, but I also want to swizzle the components. ---@class Vector
---@field x number
---@field y number
---@field z number
local Vector = {}
function Vector:normed() return --[[normed vector]] end
function Vector:__index(k)
if Vector[k] then return Vector[k] end
-- create new vector based on swizzle k
end Such that the following code works: ---@type Vector
local vec
local a = vec.yxz
local b = vec:norm() + a:norm() Swizzling means I can create a new vector from a new arrangment of the vector components using the key given to ---@class Vector : { [string]: Vector }
local Vector Which does work, but it also adds the fallback for functions (i.e. Does anyone know a workaround for this issue? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Firstly you can use ---@class Vector
---@field x number
---@field y number
---@field z number
---@field [string] Vector
local Vector = {}
The current workaround is add those methods to ---@class Vector
---@field x number
---@field y number
---@field z number
---@field normed fun(self: self): Vector
---@field [string] Vector
local Vector = {}
|
Beta Was this translation helpful? Give feedback.
-
A fix for only adding fallback type when field type not foundI debugged quite a while, and finally found a fix for this 🤔
However I am not sure if there are any side effects, at least it pasts all existing defined test in the project 😕 demo---@class Vector
---@field x number
---@field y number
---@field z number
---@field [string] Vector
---@operator add(Vector): Vector
local Vector = {}
function Vector:normed() return Vector end
function Vector:__index(k)
if Vector[k] then return Vector[k] end
-- create new vector based on swizzle k
end
---@type Vector
local vec
local a = vec.yxz
local b = vec:normed() + a:normed() The patch
basically just move the whole logic to the bottom From d893ffdbf9a8ca75d2fe61c61203908002f8807b Mon Sep 17 00:00:00 2001
From: Tom Lau <[email protected]>
Date: Sat, 5 Jul 2025 20:31:16 +0800
Subject: [PATCH] fix: fallback type of `@field` should not apply when field
type is found
---
script/vm/compiler.lua | 91 ++++++++++++++++++++++++------------------
1 file changed, 53 insertions(+), 38 deletions(-)
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 986e85e2..ec9c8bb7 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -434,44 +434,6 @@ function vm.getClassFields(suri, object, key, pushResult)
pushResult(field, true)
goto CONTINUE
end
- if hasFounded[key] then
- goto CONTINUE
- end
- local keyType = type(key)
- if keyType == 'table' then
- -- ---@field [integer] boolean -> class[integer]
- local fieldNode = vm.compileNode(field.field)
- if vm.isSubType(suri, key.name, fieldNode) then
- local nkey = '|' .. key.name
- if not searchedFields[nkey] then
- pushResult(field, true)
- hasFounded[nkey] = true
- end
- end
- else
- local keyObject
- if keyType == 'number' then
- if math.tointeger(key) then
- keyObject = { type = 'integer', [1] = key }
- else
- keyObject = { type = 'number', [1] = key }
- end
- elseif keyType == 'boolean'
- or keyType == 'string' then
- keyObject = { type = keyType, [1] = key }
- end
- if keyObject and field.field.type ~= 'doc.field.name' then
- -- ---@field [integer] boolean -> class[1]
- local fieldNode = vm.compileNode(field.field)
- if vm.isSubType(suri, keyObject, fieldNode) then
- local nkey = '|' .. keyType
- if not searchedFields[nkey] then
- pushResult(field, true)
- hasFounded[nkey] = true
- end
- end
- end
- end
::CONTINUE::
end
end
@@ -547,6 +509,59 @@ function vm.getClassFields(suri, object, key, pushResult)
end
copyToSearched()
+ -- search for fallback types in @field, eg: ---@field [integer] boolean
+ -- only when type for this field key is not found
+ if key ~= vm.ANY and key ~= vm.ANYDOC and not searchedFields[key] then
+ for _, set in ipairs(sets) do
+ if set.type == 'doc.class' then
+ for _, field in ipairs(set.fields) do
+ local fieldKey = guide.getKeyName(field)
+ if fieldKey then
+ -- already processed above
+ goto CONTINUE
+ end
+ local keyType = type(key)
+ if keyType == 'table' then
+ -- ---@field [integer] boolean -> class[integer]
+ local fieldNode = vm.compileNode(field.field)
+ if vm.isSubType(suri, key.name, fieldNode) then
+ local nkey = '|' .. key.name
+ if not searchedFields[nkey] then
+ pushResult(field, true)
+ hasFounded[nkey] = true
+ end
+ end
+ else
+ local keyObject
+ if keyType == 'number' then
+ if math.tointeger(key) then
+ keyObject = { type = 'integer', [1] = key }
+ else
+ keyObject = { type = 'number', [1] = key }
+ end
+ elseif keyType == 'boolean'
+ or keyType == 'string' then
+ keyObject = { type = keyType, [1] = key }
+ end
+ if keyObject and field.field.type ~= 'doc.field.name' then
+ -- ---@field [integer] boolean -> class[1]
+ local fieldNode = vm.compileNode(field.field)
+ if vm.isSubType(suri, keyObject, fieldNode) then
+ local nkey = '|' .. keyType
+ if not searchedFields[nkey] then
+ pushResult(field, true)
+ hasFounded[nkey] = true
+ end
+ end
+ end
+ end
+ ::CONTINUE::
+ end
+ end
+ end
+ copyToSearched()
+ end
+
for _, set in ipairs(sets) do
if set.type == 'doc.class' then
-- look into extends(if field not found)
--
2.47.1.windows.2
|
Beta Was this translation helpful? Give feedback.
A fix for only adding fallback type when field type not found
I debugged quite a while, and finally found a fix for this 🤔
@field
types info, before looking intosetfield/setmethod
of the class variable@field [T1] T2
, we can then first check if a field type is already foundHowever I am not sure if there are any side effects, at least it pasts all existing defined test in the project 😕
demo