summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-04-22 03:18:35 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-04-22 03:18:35 +0800
commit7881d1a3d91b59d2dd8c28a72453e0e6c44a902f (patch)
tree6c2466f3676d813ac9db469815f4af9834d1711a /script
parentb85ff57a116fb252a0da35e525264e0940af88c7 (diff)
downloadlua-language-server-7881d1a3d91b59d2dd8c28a72453e0e6c44a902f.zip
new diagnostic `missing-parameter`
Diffstat (limited to 'script')
-rw-r--r--script/core/diagnostics/missing-parameter.lua84
-rw-r--r--script/core/diagnostics/redundant-parameter.lua43
-rw-r--r--script/proto/define.lua2
-rw-r--r--script/vm/node.lua16
4 files changed, 110 insertions, 35 deletions
diff --git a/script/core/diagnostics/missing-parameter.lua b/script/core/diagnostics/missing-parameter.lua
new file mode 100644
index 00000000..34cbdab6
--- /dev/null
+++ b/script/core/diagnostics/missing-parameter.lua
@@ -0,0 +1,84 @@
+local files = require 'files'
+local guide = require 'parser.guide'
+local vm = require 'vm'
+local lang = require 'language'
+
+local function countCallArgs(source)
+ local result = 0
+ if not source.args then
+ return 0
+ 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 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)
+ if callArgs == 0 then
+ return
+ end
+
+ 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,
+ }
+ for i = #source.args - delta + 1, #source.args do
+ local arg = source.args[i]
+ if arg then
+ callback {
+ start = arg.start,
+ finish = arg.finish,
+ message = lang.script('DIAG_MISS_ARGS', funcArgs, callArgs)
+ }
+ end
+ end
+ end)
+end
diff --git a/script/core/diagnostics/redundant-parameter.lua b/script/core/diagnostics/redundant-parameter.lua
index 564e0810..2f921f3a 100644
--- a/script/core/diagnostics/redundant-parameter.lua
+++ b/script/core/diagnostics/redundant-parameter.lua
@@ -2,7 +2,6 @@ local files = require 'files'
local guide = require 'parser.guide'
local vm = require 'vm'
local lang = require 'language'
-local define = require 'proto.define'
local function countCallArgs(source)
local result = 0
@@ -14,64 +13,38 @@ local function countCallArgs(source)
end
local function countFuncArgs(source)
- local result = 0
if not source.args or #source.args == 0 then
- return result
+ return 0
end
if source.args[#source.args].type == '...' then
return math.maxinteger
+ else
+ return #source.args
end
- result = result + #source.args
- return result
-end
-
-local function countOverLoadArgs(source, doc)
- local result = 0
- local func = doc.overload
- if not func.args or #func.args == 0 then
- return result
- end
- if func.args[#func.args].type == '...' then
- return math.maxinteger
- end
- result = result + #func.args
- return result
end
local function getFuncArgs(func)
local funcArgs
local defs = vm.getDefs(func)
for _, def in ipairs(defs) do
- if def.value then
- def = def.value
- end
- if def.type == 'function' then
+ 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
- if def.bindDocs then
- for _, doc in ipairs(def.bindDocs) do
- if doc.type == 'doc.overload' then
- args = countOverLoadArgs(def, doc)
- if not funcArgs or args > funcArgs then
- funcArgs = args
- end
- end
- end
- end
end
end
return funcArgs
end
return function (uri, callback)
- local ast = files.getState(uri)
- if not ast then
+ local state = files.getState(uri)
+ if not state then
return
end
- guide.eachSourceType(ast.ast, 'call', function (source)
+ guide.eachSourceType(state.ast, 'call', function (source)
local callArgs = countCallArgs(source)
if callArgs == 0 then
return
diff --git a/script/proto/define.lua b/script/proto/define.lua
index 389cdf88..9da67039 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -29,6 +29,7 @@ m.DiagnosticDefaultSeverity = {
['newline-call'] = 'Information',
['newfield-call'] = 'Warning',
['redundant-parameter'] = 'Warning',
+ ['missing-parameter'] = 'Warning',
['redundant-return'] = 'Warning',
['ambiguity-1'] = 'Warning',
['lowercase-global'] = 'Information',
@@ -88,6 +89,7 @@ m.DiagnosticDefaultNeededFileStatus = {
['newline-call'] = 'Any',
['newfield-call'] = 'Any',
['redundant-parameter'] = 'Opened',
+ ['missing-parameter'] = 'Opened',
['redundant-return'] = 'Opened',
['ambiguity-1'] = 'Any',
['lowercase-global'] = 'Any',
diff --git a/script/vm/node.lua b/script/vm/node.lua
index 87fcc0c5..92604c3c 100644
--- a/script/vm/node.lua
+++ b/script/vm/node.lua
@@ -7,6 +7,7 @@ local ws = require 'workspace.workspace'
vm.nodeCache = {}
---@class vm.node
+---@field [integer] vm.object
local mt = {}
mt.__index = mt
mt.type = 'vm.node'
@@ -85,6 +86,7 @@ function mt:isFalsy()
end
for _, c in ipairs(self) do
if c.type == 'nil'
+ or (c.type == 'global' and c.cate == 'type' and c.name == 'nil')
or (c.type == 'boolean' and c[1] == false)
or (c.type == 'doc.type.boolean' and c[1] == false) then
return true
@@ -93,6 +95,20 @@ function mt:isFalsy()
return false
end
+---@return boolean
+function mt:isNullable()
+ if self.optional then
+ return true
+ end
+ for _, c in ipairs(self) do
+ if c.type == 'nil'
+ or (c.type == 'global' and c.cate == 'type' and c.name == 'nil') then
+ return true
+ end
+ end
+ return false
+end
+
---@return vm.node
function mt:copyTruly()
local newNode = vm.createNode()