Skip to content

Commit c2fb295

Browse files
committed
refactor: simplify generic resolution with helper functions
- Fix double-clone bug in cloneObject for doc.type.function returns - Add containsGenericName() for early-exit generic detection - Add getClassGenericMap() to eliminate code duplication - Refactor resolveGenericField() to use new helpers
1 parent 2bb62ab commit c2fb295

File tree

2 files changed

+86
-46
lines changed

2 files changed

+86
-46
lines changed

script/vm/compiler.lua

Lines changed: 84 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -234,56 +234,107 @@ local function searchLiteralFieldFromTable(source, key, callback)
234234
end
235235
end
236236

237-
---@param uri uri
238-
---@param classGlobal vm.global
239-
---@param field parser.object
240-
---@param signs parser.object[]
241-
---@return parser.object?
242-
local function resolveGenericField(uri, classGlobal, field, signs)
243-
if field.type ~= 'doc.field' then
244-
return nil
237+
---@param obj parser.object
238+
---@return boolean
239+
local function containsGenericName(obj)
240+
if not obj then
241+
return false
245242
end
246-
if not field.extends then
247-
return nil
243+
if obj.type == 'doc.generic.name' then
244+
return true
248245
end
249-
local hasGeneric = false
250-
guide.eachSourceType(field.extends, 'doc.generic.name', function ()
251-
hasGeneric = true
252-
end)
253-
if not hasGeneric then
254-
return nil
246+
if obj.type == 'doc.type' and obj.types then
247+
for _, t in ipairs(obj.types) do
248+
if containsGenericName(t) then
249+
return true
250+
end
251+
end
252+
elseif obj.type == 'doc.type.array' then
253+
return containsGenericName(obj.node)
254+
elseif obj.type == 'doc.type.table' and obj.fields then
255+
for _, field in ipairs(obj.fields) do
256+
if containsGenericName(field.name) or containsGenericName(field.extends) then
257+
return true
258+
end
259+
end
260+
elseif obj.type == 'doc.type.sign' then
261+
if obj.signs then
262+
for _, s in ipairs(obj.signs) do
263+
if containsGenericName(s) then
264+
return true
265+
end
266+
end
267+
end
268+
elseif obj.type == 'doc.type.function' then
269+
for _, arg in ipairs(obj.args or {}) do
270+
if containsGenericName(arg.extends) then
271+
return true
272+
end
273+
end
274+
for _, ret in ipairs(obj.returns or {}) do
275+
if containsGenericName(ret) then
276+
return true
277+
end
278+
end
255279
end
280+
return false
281+
end
282+
283+
---@param uri uri
284+
---@param classGlobal vm.global
285+
---@param signs parser.object[]
286+
---@return table<string, vm.node>?
287+
local function getClassGenericMap(uri, classGlobal, signs)
256288
for _, set in ipairs(classGlobal:getSets(uri)) do
257289
if set.type == 'doc.class' and set.signs then
258290
local resolved = {}
259291
for i, signName in ipairs(set.signs) do
260292
local signType = signs[i]
261293
if signType and signName[1] then
262-
local signNode = vm.compileNode(signType)
263-
resolved[signName[1]] = signNode
294+
resolved[signName[1]] = vm.compileNode(signType)
264295
end
265296
end
266297
if next(resolved) then
267-
local newExtends = vm.cloneObject(field.extends, resolved)
268-
if newExtends then
269-
return {
270-
type = field.type,
271-
start = field.start,
272-
finish = field.finish,
273-
parent = field.parent,
274-
field = field.field,
275-
extends = newExtends,
276-
visible = field.visible,
277-
optional = field.optional,
278-
}
279-
end
298+
return resolved
280299
end
281300
break
282301
end
283302
end
284303
return nil
285304
end
286305

306+
---@param uri uri
307+
---@param classGlobal vm.global
308+
---@param field parser.object
309+
---@param signs parser.object[]
310+
---@return parser.object?
311+
local function resolveGenericField(uri, classGlobal, field, signs)
312+
if field.type ~= 'doc.field' or not field.extends then
313+
return nil
314+
end
315+
if not containsGenericName(field.extends) then
316+
return nil
317+
end
318+
local resolved = getClassGenericMap(uri, classGlobal, signs)
319+
if not resolved then
320+
return nil
321+
end
322+
local newExtends = vm.cloneObject(field.extends, resolved)
323+
if not newExtends then
324+
return nil
325+
end
326+
return {
327+
type = field.type,
328+
start = field.start,
329+
finish = field.finish,
330+
parent = field.parent,
331+
field = field.field,
332+
extends = newExtends,
333+
visible = field.visible,
334+
optional = field.optional,
335+
}
336+
end
337+
287338
local searchFieldSwitch = util.switch()
288339
: case 'table'
289340
: call(function (_suri, source, key, pushResult)
@@ -1673,19 +1724,8 @@ local function bindReturnOfFunction(source, mfunc, index, args)
16731724
if rn.type == 'doc.type.sign' and rn.signs and rn.node and rn.node[1] then
16741725
local classGlobal = vm.getGlobal('type', rn.node[1])
16751726
if classGlobal then
1676-
local genericMap = {}
1677-
for _, set in ipairs(classGlobal:getSets(guide.getUri(source))) do
1678-
if set.type == 'doc.class' and set.signs then
1679-
for i, signName in ipairs(set.signs) do
1680-
if signName[1] and rn.signs[i] then
1681-
genericMap[signName[1]] = vm.compileNode(rn.signs[i])
1682-
end
1683-
end
1684-
break
1685-
end
1686-
end
1687-
1688-
if next(genericMap) and mfunc.bindDocs then
1727+
local genericMap = getClassGenericMap(guide.getUri(source), classGlobal, rn.signs)
1728+
if genericMap and mfunc.bindDocs then
16891729
for _, doc in ipairs(mfunc.bindDocs) do
16901730
if doc.type == 'doc.return' then
16911731
for _, rtn in ipairs(doc.returns) do

script/vm/generic.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ local function cloneObject(source, resolved)
121121
newDocFunc.args[i] = newObj
122122
end
123123
for i, ret in ipairs(source.returns) do
124-
local newObj = cloneObject(ret, resolved)
124+
local newObj = cloneObject(ret, resolved)
125125
newObj.parent = newDocFunc
126126
newObj.optional = ret.optional
127-
newDocFunc.returns[i] = cloneObject(ret, resolved)
127+
newDocFunc.returns[i] = newObj
128128
end
129129
return newDocFunc
130130
end

0 commit comments

Comments
 (0)