Skip to content

Commit dbb392e

Browse files
committed
full support for interface
1 parent 8ed72a9 commit dbb392e

File tree

10 files changed

+228
-97
lines changed

10 files changed

+228
-97
lines changed

script/core/diagnostics/missing-parameter.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,24 @@ return function (uri, callback)
2929
message = lang.script('DIAG_MISS_ARGS', funcArgs, callArgs),
3030
}
3131
end)
32+
33+
---@async
34+
guide.eachSourceType(state.ast, 'function', function (source)
35+
await.delay()
36+
if not source.args then
37+
return
38+
end
39+
local funcArgs = vm.countParamsOfSource(source)
40+
if funcArgs == 0 then
41+
return
42+
end
43+
local myArgs = #source.args
44+
if myArgs < funcArgs then
45+
callback {
46+
start = source.args.start,
47+
finish = source.args.finish,
48+
message = lang.script('DIAG_MISS_ARGS', funcArgs, myArgs),
49+
}
50+
end
51+
end)
3252
end

script/core/diagnostics/missing-return-value.lua

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,6 @@ local vm = require 'vm'
44
local lang = require 'language'
55
local await = require 'await'
66

7-
---@param func parser.object
8-
---@return integer
9-
local function getReturnsMin(func)
10-
local min = vm.countReturnsOfFunction(func, true)
11-
if min == 0 then
12-
return 0
13-
end
14-
for _, doc in ipairs(func.bindDocs) do
15-
if doc.type == 'doc.overload' then
16-
local n = vm.countReturnsOfFunction(doc.overload)
17-
if n == 0 then
18-
return 0
19-
end
20-
if n < min then
21-
min = n
22-
end
23-
end
24-
end
25-
return min
26-
end
27-
287
---@async
298
return function (uri, callback)
309
local state = files.getState(uri)
@@ -39,7 +18,7 @@ return function (uri, callback)
3918
if not returns then
4019
return
4120
end
42-
local min = getReturnsMin(source)
21+
local min = vm.countReturnsOfSource(source)
4322
if min == 0 then
4423
return
4524
end

script/core/diagnostics/missing-return.lua

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,6 @@ local function hasReturn(block)
3838
return false
3939
end
4040

41-
---@param func parser.object
42-
---@return integer
43-
local function getReturnsMin(func)
44-
local min = vm.countReturnsOfFunction(func, true)
45-
if min == 0 then
46-
return 0
47-
end
48-
for _, doc in ipairs(func.bindDocs) do
49-
if doc.type == 'doc.overload' then
50-
local n = vm.countReturnsOfFunction(doc.overload)
51-
if n == 0 then
52-
return 0
53-
end
54-
if n < min then
55-
min = n
56-
end
57-
end
58-
end
59-
return min
60-
end
61-
6241
---@async
6342
return function (uri, callback)
6443
local state = files.getState(uri)
@@ -75,7 +54,7 @@ return function (uri, callback)
7554
return
7655
end
7756
await.delay()
78-
if getReturnsMin(source) == 0 then
57+
if vm.countReturnsOfSource(source) == 0 then
7958
return
8059
end
8160
if hasReturn(source) then
@@ -86,8 +65,7 @@ return function (uri, callback)
8665
if lastAction then
8766
pos = lastAction.range or lastAction.finish
8867
else
89-
local row = guide.rowColOf(source.finish)
90-
pos = guide.positionOf(row - 1, 0)
68+
pos = source.keyword[3] or source.finish
9169
end
9270
callback {
9371
start = pos,

script/core/diagnostics/redundant-parameter.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,22 @@ return function (uri, callback)
5252
end
5353
end
5454
end)
55+
56+
---@async
57+
guide.eachSourceType(state.ast, 'function', function (source)
58+
await.delay()
59+
if not source.args then
60+
return
61+
end
62+
local _, funcArgs = vm.countParamsOfSource(source)
63+
local myArgs = #source.args
64+
for i = funcArgs + 1, myArgs do
65+
local arg = source.args[i]
66+
callback {
67+
start = arg.start,
68+
finish = arg.finish,
69+
message = lang.script('DIAG_OVER_MAX_ARGS', funcArgs, myArgs),
70+
}
71+
end
72+
end)
5573
end

script/core/diagnostics/redundant-return-value.lua

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,6 @@ local vm = require 'vm'
44
local lang = require 'language'
55
local await = require 'await'
66

7-
---@param func parser.object
8-
---@return number
9-
local function getReturnsMax(func)
10-
local _, max = vm.countReturnsOfFunction(func, true)
11-
if max == math.huge then
12-
return max
13-
end
14-
for _, doc in ipairs(func.bindDocs) do
15-
if doc.type == 'doc.overload' then
16-
local _, n = vm.countReturnsOfFunction(doc.overload)
17-
if n == math.huge then
18-
return n
19-
end
20-
if n > max then
21-
max = n
22-
end
23-
end
24-
end
25-
return max
26-
end
27-
287
---@async
298
return function (uri, callback)
309
local state = files.getState(uri)
@@ -39,7 +18,7 @@ return function (uri, callback)
3918
return
4019
end
4120
await.delay()
42-
local max = getReturnsMax(source)
21+
local _, max = vm.countReturnsOfSource(source)
4322
for _, ret in ipairs(returns) do
4423
local rmin, rmax = vm.countList(ret)
4524
if rmin > max then

script/core/diagnostics/return-type-mismatch.lua

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,28 @@ local util = require 'utility'
88
---@param func parser.object
99
---@return vm.node[]?
1010
local function getDocReturns(func)
11-
if not func.bindDocs then
12-
return nil
13-
end
1411
---@type table<integer, vm.node>
1512
local returns = util.defaultTable(function ()
1613
return vm.createNode()
1714
end)
18-
for _, doc in ipairs(func.bindDocs) do
19-
if doc.type == 'doc.return' then
20-
for _, ret in ipairs(doc.returns) do
21-
returns[ret.returnIndex]:merge(vm.compileNode(ret))
15+
if func.bindDocs then
16+
for _, doc in ipairs(func.bindDocs) do
17+
if doc.type == 'doc.return' then
18+
for _, ret in ipairs(doc.returns) do
19+
returns[ret.returnIndex]:merge(vm.compileNode(ret))
20+
end
21+
end
22+
if doc.type == 'doc.overload' then
23+
for i, ret in ipairs(doc.overload.returns) do
24+
returns[i]:merge(vm.compileNode(ret))
25+
end
2226
end
2327
end
24-
if doc.type == 'doc.overload' then
25-
for i, ret in ipairs(doc.overload.returns) do
28+
end
29+
for nd in vm.compileNode(func):eachObject() do
30+
if nd.type == 'doc.type.function' then
31+
---@cast nd parser.object
32+
for i, ret in ipairs(nd.returns) do
2633
returns[i]:merge(vm.compileNode(ret))
2734
end
2835
end

script/parser/compile.lua

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,16 +2289,15 @@ local function parseFunction(isLocal, isAction)
22892289
end
22902290
end
22912291
if hasLeftParen then
2292+
params = params or {}
22922293
local parenLeft = getPosition(Tokens[Index], 'left')
22932294
Index = Index + 2
22942295
params = parseParams(params)
2295-
if params then
2296-
params.type = 'funcargs'
2297-
params.start = parenLeft
2298-
params.finish = lastRightPosition()
2299-
params.parent = func
2300-
func.args = params
2301-
end
2296+
params.type = 'funcargs'
2297+
params.start = parenLeft
2298+
params.finish = lastRightPosition()
2299+
params.parent = func
2300+
func.args = params
23022301
skipSpace(true)
23032302
if Tokens[Index + 1] == ')' then
23042303
local parenRight = getPosition(Tokens[Index], 'right')

script/vm/function.lua

Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,54 @@ function vm.countParamsOfFunction(func)
6363
return min, max, def
6464
end
6565

66+
---@param source parser.object
67+
---@return integer min
68+
---@return number max
69+
---@return integer def
70+
function vm.countParamsOfSource(source)
71+
local min = 0
72+
local max = 0
73+
local def = 0
74+
local overloads = {}
75+
if source.bindDocs then
76+
for _, doc in ipairs(source.bindDocs) do
77+
if doc.type == 'doc.overload' then
78+
overloads[doc.overload] = true
79+
end
80+
end
81+
end
82+
local hasDocFunction
83+
for nd in vm.compileNode(source):eachObject() do
84+
if nd.type == 'doc.type.function' and not overloads[nd] then
85+
hasDocFunction = true
86+
---@cast nd parser.object
87+
local dmin, dmax, ddef = vm.countParamsOfFunction(nd)
88+
if dmin > min then
89+
min = dmin
90+
end
91+
if dmax > max then
92+
max = dmax
93+
end
94+
if ddef > def then
95+
def = ddef
96+
end
97+
end
98+
end
99+
if not hasDocFunction then
100+
local dmin, dmax, ddef = vm.countParamsOfFunction(source)
101+
if dmin > min then
102+
min = dmin
103+
end
104+
if dmax > max then
105+
max = dmax
106+
end
107+
if ddef > def then
108+
def = ddef
109+
end
110+
end
111+
return min, max, def
112+
end
113+
66114
---@param node vm.node
67115
---@return integer min
68116
---@return number max
@@ -136,12 +184,12 @@ function vm.countReturnsOfFunction(func, onlyDoc, mark)
136184
end
137185
if not onlyDoc and not hasDocReturn and func.returns then
138186
for _, ret in ipairs(func.returns) do
139-
local rmin, rmax, ddef = vm.countList(ret, mark)
140-
if not min or rmin < min then
141-
min = rmin
187+
local dmin, dmax, ddef = vm.countList(ret, mark)
188+
if not min or dmin < min then
189+
min = dmin
142190
end
143-
if not max or rmax > max then
144-
max = rmax
191+
if not max or dmax > max then
192+
max = dmax
145193
end
146194
if not def or ddef > def then
147195
def = ddef
@@ -156,6 +204,62 @@ function vm.countReturnsOfFunction(func, onlyDoc, mark)
156204
error('not a function')
157205
end
158206

207+
---@param source parser.object
208+
---@return integer min
209+
---@return number max
210+
---@return integer def
211+
function vm.countReturnsOfSource(source)
212+
local overloads = {}
213+
local hasDocFunction
214+
local min, max, def
215+
if source.bindDocs then
216+
for _, doc in ipairs(source.bindDocs) do
217+
if doc.type == 'doc.overload' then
218+
overloads[doc.overload] = true
219+
local dmin, dmax, ddef = vm.countReturnsOfFunction(doc.overload)
220+
if not min or dmin < min then
221+
min = dmin
222+
end
223+
if not max or dmax > max then
224+
max = dmax
225+
end
226+
if not def or ddef > def then
227+
def = ddef
228+
end
229+
end
230+
end
231+
end
232+
for nd in vm.compileNode(source):eachObject() do
233+
if nd.type == 'doc.type.function' and not overloads[nd] then
234+
---@cast nd parser.object
235+
hasDocFunction = true
236+
local dmin, dmax, ddef = vm.countReturnsOfFunction(nd)
237+
if not min or dmin < min then
238+
min = dmin
239+
end
240+
if not max or dmax > max then
241+
max = dmax
242+
end
243+
if not def or ddef > def then
244+
def = ddef
245+
end
246+
end
247+
end
248+
if not hasDocFunction then
249+
local dmin, dmax, ddef = vm.countReturnsOfFunction(source, true)
250+
if not min or dmin < min then
251+
min = dmin
252+
end
253+
if not max or dmax > max then
254+
max = dmax
255+
end
256+
if not def or ddef > def then
257+
def = ddef
258+
end
259+
end
260+
return min, max, def
261+
end
262+
159263
---@param func parser.object
160264
---@param mark? table
161265
---@return integer min
@@ -254,7 +358,7 @@ function vm.isVarargFunctionWithOverloads(func)
254358
if not func.args then
255359
return false
256360
end
257-
if func.args[1].type ~= '...' then
361+
if not func.args[1] or func.args[1].type ~= '...' then
258362
return false
259363
end
260364
if not func.bindDocs then

test.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ local function testAll()
5656
test 'references'
5757
test 'hover'
5858
test 'completion'
59-
test 'crossfile'
6059
test 'diagnostics'
60+
test 'crossfile'
6161
test 'highlight'
6262
test 'rename'
6363
test 'signature'

0 commit comments

Comments
 (0)