@@ -5,7 +5,8 @@ local vm = require 'vm'
55local await = require ' await'
66
77--- @param defNode vm.node
8- local function expandGenerics (defNode )
8+ --- @param classGenericMap table<string , vm.node> ?
9+ local function expandGenerics (defNode , classGenericMap )
910 --- @type parser.object[]
1011 local generics = {}
1112 for dn in defNode :eachObject () do
@@ -20,27 +21,78 @@ local function expandGenerics(defNode)
2021 end
2122
2223 for _ , generic in ipairs (generics ) do
23- local limits = generic .generic and generic .generic .extends
24- if limits then
25- defNode :merge (vm .compileNode (limits ))
24+ -- First check if this generic is a class generic that can be resolved
25+ local genericName = generic [1 ]
26+ if classGenericMap and genericName and classGenericMap [genericName ] then
27+ defNode :merge (classGenericMap [genericName ])
2628 else
27- local unknownType = vm .declareGlobal (' type' , ' unknown' )
28- defNode :merge (unknownType )
29+ -- Fall back to constraint or unknown
30+ local limits = generic .generic and generic .generic .extends
31+ if limits then
32+ defNode :merge (vm .compileNode (limits ))
33+ else
34+ local unknownType = vm .declareGlobal (' type' , ' unknown' )
35+ defNode :merge (unknownType )
36+ end
37+ end
38+ end
39+ end
40+
41+ --- @param uri uri
42+ --- @param source parser.object
43+ --- @return table<string , vm.node> ?
44+ local function getReceiverGenericMap (uri , source )
45+ local callNode = source .node
46+ if not callNode then
47+ return nil
48+ end
49+ -- Only resolve generics for method calls (obj:method()), not static calls (Class.method())
50+ if callNode .type ~= ' getmethod' then
51+ return nil
52+ end
53+ local receiver = callNode .node
54+ if not receiver then
55+ return nil
56+ end
57+ local receiverNode = vm .compileNode (receiver )
58+ for rn in receiverNode :eachObject () do
59+ if rn .type == ' doc.type.sign' and rn .signs and rn .node and rn .node [1 ] then
60+ local classGlobal = vm .getGlobal (' type' , rn .node [1 ])
61+ if classGlobal then
62+ return vm .getClassGenericMap (uri , classGlobal , rn .signs )
63+ end
2964 end
3065 end
66+ return nil
3167end
3268
3369--- @param funcNode vm.node
3470--- @param i integer
71+ --- @param classGenericMap table<string , vm.node> ?
3572--- @return vm.node ?
36- local function getDefNode (funcNode , i )
73+ local function getDefNode (funcNode , i , classGenericMap )
3774 local defNode = vm .createNode ()
3875 for src in funcNode :eachObject () do
3976 if src .type == ' function'
4077 or src .type == ' doc.type.function' then
4178 local param = src .args and src .args [i ]
4279 if param then
43- defNode :merge (vm .compileNode (param ))
80+ local paramNode = vm .compileNode (param )
81+ -- Check for global type references that match class generic params
82+ if classGenericMap then
83+ local newNode = vm .createNode ()
84+ for pn in paramNode :eachObject () do
85+ if pn .type == ' global' and pn .cate == ' type' and classGenericMap [pn .name ] then
86+ -- Replace the global type reference with the resolved type
87+ newNode :merge (classGenericMap [pn .name ])
88+ else
89+ newNode :merge (pn )
90+ end
91+ end
92+ defNode :merge (newNode )
93+ else
94+ defNode :merge (paramNode )
95+ end
4496 if param [1 ] == ' ...' then
4597 defNode :addOptional ()
4698 end
@@ -51,7 +103,7 @@ local function getDefNode(funcNode, i)
51103 return nil
52104 end
53105
54- expandGenerics (defNode )
106+ expandGenerics (defNode , classGenericMap )
55107
56108 return defNode
57109end
@@ -87,12 +139,14 @@ return function (uri, callback)
87139 end
88140 await .delay ()
89141 local funcNode = vm .compileNode (source .node )
142+ -- Get the class generic map for method calls on generic class instances
143+ local classGenericMap = getReceiverGenericMap (uri , source )
90144 for i , arg in ipairs (source .args ) do
91145 local refNode = vm .compileNode (arg )
92146 if not refNode then
93147 goto CONTINUE
94148 end
95- local defNode = getDefNode (funcNode , i )
149+ local defNode = getDefNode (funcNode , i , classGenericMap )
96150 if not defNode then
97151 goto CONTINUE
98152 end
0 commit comments