diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-04-22 03:18:35 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-04-22 03:18:35 +0800 |
commit | 7881d1a3d91b59d2dd8c28a72453e0e6c44a902f (patch) | |
tree | 6c2466f3676d813ac9db469815f4af9834d1711a /script | |
parent | b85ff57a116fb252a0da35e525264e0940af88c7 (diff) | |
download | lua-language-server-7881d1a3d91b59d2dd8c28a72453e0e6c44a902f.zip |
new diagnostic `missing-parameter`
Diffstat (limited to 'script')
-rw-r--r-- | script/core/diagnostics/missing-parameter.lua | 84 | ||||
-rw-r--r-- | script/core/diagnostics/redundant-parameter.lua | 43 | ||||
-rw-r--r-- | script/proto/define.lua | 2 | ||||
-rw-r--r-- | script/vm/node.lua | 16 |
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() |