1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
local files = require 'files'
local guide = require 'parser.guide'
local vm = require 'vm'
local lang = require 'language'
---@param source parser.object
---@return integer
local function countReturnsOfFunction(source)
local n = 0
local docs = source.bindDocs
if docs then
for _, doc in ipairs(docs) do
if doc.type == 'doc.return' then
for _, rtn in ipairs(doc.returns) do
if rtn.returnIndex and rtn.returnIndex > n then
n = rtn.returnIndex
end
end
end
end
end
local returns = source.returns
if returns then
for _, rtn in ipairs(returns) do
if #rtn > n then
n = #rtn
end
end
end
return n
end
---@param source parser.object
---@return integer
local function countReturnsOfDocFunction(source)
return #source.returns
end
local function countMaxReturns(source)
local hasFounded
local n = 0
for _, def in ipairs(vm.getDefs(source)) do
if def.type == 'function' then
hasFounded = true
local rets = countReturnsOfFunction(def)
if rets > n then
n = rets
end
elseif def.type == 'doc.type.function' then
hasFounded = true
local rets = countReturnsOfDocFunction(def)
if rets > n then
n = rets
end
end
end
if hasFounded then
return n
else
return math.huge
end
end
local function countCallArgs(source)
local result = 0
if not source.args then
return 0
end
local lastArg = source.args[#source.args]
if lastArg.type == 'varargs' then
return math.huge
end
if lastArg.type == 'call' then
result = result + countMaxReturns(lastArg.node) - 1
end
result = result + #source.args
return result
end
---@return integer
local function countFuncArgs(source)
if not source.args or #source.args == 0 then
return 0
end
local count = 0
for i = #source.args, 1, -1 do
local arg = source.args[i]
if arg.type ~= '...'
and not (arg.name and arg.name[1] =='...')
and not vm.compileNode(arg):isNullable() then
return i
end
end
return count
end
local function getFuncArgs(func)
local funcArgs
local defs = vm.getDefs(func)
for _, def in ipairs(defs) do
if def.type == 'function'
or def.type == 'doc.type.function' then
local args = countFuncArgs(def)
if not funcArgs or args < funcArgs then
funcArgs = args
end
end
end
return funcArgs
end
return function (uri, callback)
local state = files.getState(uri)
if not state then
return
end
guide.eachSourceType(state.ast, 'call', function (source)
local callArgs = countCallArgs(source)
local func = source.node
local funcArgs = getFuncArgs(func)
if not funcArgs then
return
end
local delta = callArgs - funcArgs
if delta >= 0 then
return
end
callback {
start = source.start,
finish = source.finish,
message = lang.script('DIAG_MISS_ARGS', funcArgs, callArgs),
}
end)
end
|