summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <luoxingyue@cn.net.ntes>2021-09-27 15:43:38 +0800
committerunknown <luoxingyue@cn.net.ntes>2021-09-27 15:43:38 +0800
commitd330c9020e299e9bddbadb12e3712679029febe6 (patch)
tree2ee1f8650420ba8b137b686b431f19ec2a2a4b02
parent426e5d48378fb1679c13fc8923967507d2750871 (diff)
downloadlua-language-server-d330c9020e299e9bddbadb12e3712679029febe6.zip
improve
-rw-r--r--script/core/diagnostics/type-check.lua197
-rw-r--r--script/proto/define.lua2
2 files changed, 126 insertions, 73 deletions
diff --git a/script/core/diagnostics/type-check.lua b/script/core/diagnostics/type-check.lua
index 010764ba..f021b1e5 100644
--- a/script/core/diagnostics/type-check.lua
+++ b/script/core/diagnostics/type-check.lua
@@ -1,20 +1,25 @@
local files = require 'files'
local guide = require 'parser.guide'
local vm = require 'vm'
+local infer = require 'core.infer'
+local await = require 'await'
+-- local function hasTypeDoc(obj)
+-- if obj.type == 'getlocal'
+-- and obj.node
+-- and obj.node.type == 'local'
+-- and obj.node.bindDocs
+-- and obj.node.bindDocs[1]
+-- and (obj.node.bindDocs[1].type == 'doc.type'
+-- or obj.node.bindDocs[1].type == 'doc.param') then
+-- return true
+-- end
+-- return false
+-- end
+local function hasInferType(obj)
-local function hasTypeDoc(obj)
- if obj.type == 'getlocal'
- and obj.node
- and obj.node.type == 'local'
- and obj.node.bindDocs
- and obj.node.bindDocs[1]
- and obj.node.bindDocs[1].type == 'doc.type' then
- return true
- end
- return false
end
local function inTypes(param, args)
- for _, v in ipairs(args.type) do
+ for _, v in ipairs(args) do
if param[1] == v[1] then
return true
end
@@ -26,6 +31,7 @@ return function (uri, callback)
if not ast then
return
end
+ await.delay()
guide.eachSourceType(ast.ast, 'call', function (source)
if not source.args then
return
@@ -36,97 +42,144 @@ return function (uri, callback)
---检查字面值类型的参数调用
if guide.isLiteral(arg) then
callArgsType[#callArgsType+1] = {
- type = {
- [1] = {
- [1] = arg.type,
- ['type'] = arg.type,
- }
+ [1] = {
+ [1] = arg.type,
+ ['type'] = arg.type,
},
start = arg.start,
finish = arg.finish,
}
- ---检查传入参数有完整信息的情况
- elseif hasTypeDoc(arg) then
- callArgsType[#callArgsType+1] = {
- type = arg.node.bindDocs[1].types,
- start = arg.start,
- finish = arg.finish,
- }
+ -- ---检查传入参数有完整信息的情况
+ -- elseif hasInferType(arg) then
+ -- callArgsType[#callArgsType+1] = {
+ -- type = arg.node.bindDocs[1].types,
+ -- start = arg.start,
+ -- finish = arg.finish,
+ -- }
else
- return
+ local infers = infer.searchInfers(arg)
+ if infers['_G'] or infer['_ENV'] then
+ infers['_G'] = nil
+ infers['_ENV'] = nil
+ infers['table'] = true
+ end
+ local types = {}
+ for k in pairs(infers) do
+ if k then
+ types[#types+1] = {
+ [1] = k,
+ type = k
+ }
+ end
+ end
+ if #types < 1 then
+ return
+ end
+ types.start = arg.start
+ types.finish = arg.finish
+ callArgsType[#callArgsType+1] = types
end
end
local func = source.node
local defs = vm.getDefs(func)
- local funcArgsType = {}
+ local funcArgsType
+ local mark = {}
+ local paramType = {}
---只检查有emmy注释定义的函数
- ---获取函数定义的参数信息时,遇到一个定义就停止获取
for _, def in ipairs(defs) do
+ funcArgsType = {}
if def.value then
def = def.value
end
- if def.type == 'function' then
+ if mark[def] then
+ goto CONTINUE
+ end
+ mark[def] = true
+ if def.type == 'function'
+ or def.type == 'doc.type.function' then
if def.args then
for _, arg in ipairs(def.args) do
+ local types
if arg.docParam and arg.docParam.extends then
- ---如果是很复杂的type,比如泛型什么的,先不检查
- if not arg.docParam.extends.types[1][1]
- or arg.docParam.extends.types[1].typeGeneric then
- return
- end
- funcArgsType[#funcArgsType+1] = arg.docParam.extends.types
+ types = arg.docParam.extends.types
+ ---变长参数不检查
+ elseif arg.name and arg.name[1] == '...' then
+ return
+ elseif arg.type == 'doc.type.arg' then
+ types = arg.extends.types
else
- funcArgsType = {}
+ goto CONTINUE
+ end
+
+ ---如果是很复杂的type,比如泛型什么的,先不检查
+ if not types[1]
+ or not types[1][1]
+ or types[1].typeGeneric then
+ goto CONTINUE
end
+ funcArgsType[#funcArgsType+1] = types
end
end
- break
+ else
+ goto CONTINUE
end
- end
- if #funcArgsType == 0 then
- return
- end
- local message = ''
- ---先遍历实参
- for i, arg in ipairs(callArgsType) do
- if not funcArgsType[i] then
- ---由另一个检查来处理
- -- message = 'too many call args'
- -- callback{
- -- start = arg.start,
- -- finish = arg.finish,
- -- message = message
- -- }
- return
+ if #funcArgsType == 0 then
+ goto CONTINUE
end
- local flag = ''
- ---遍历形参
- for _, tp in ipairs(funcArgsType[i]) do
- ---如果形参的类型在实参里面
- if inTypes(tp, arg)
- or tp[1] == 'any'
- or arg.type == 'any' then
- flag = ''
- break
- else
- flag = flag ..' ' .. tp[1]
+ paramType[#paramType+1] = funcArgsType
+ ::CONTINUE::
+ end
+ ---先遍历实参
+ for i, arg in ipairs(callArgsType) do
+ local flag = ''
+ local messages = {}
+ ---遍历形参
+ for _, par in ipairs(paramType) do
+ if not par[i] then
+ ---实参过多,由另一个检查来处理,此处跳过
+ goto CONTINUE
+ end
+ for _, param in ipairs(par[i]) do
+ ---如果形参的类型在实参里面
+ if inTypes(param, arg)
+ or param[1] == 'any'
+ or arg.type == 'any' then
+ flag = ''
+ goto HIT
+ else
+ flag = flag ..' ' .. param[1]
+ end
+ end
+ if flag ~= '' then
+ local argm = '[ '
+ for _, v in ipairs(arg) do
+ argm = argm .. v[1]..' '
+ end
+ argm = argm .. ']'
+ local message = 'Argument of type in '..argm..' is not assignable to parameter of type in ['..flag..' ]'
+ messages[#messages+1] = message
+ end
+ ::CONTINUE::
end
- end
- if flag ~= '' then
- local argm = '[ '
- for _, v in ipairs(arg.type) do
- argm = argm .. v[1]..' '
+ ---都不匹配
+ local norepeat = {}
+ for _, m in ipairs(messages) do
+ if not norepeat[m] then
+ norepeat[m] = true
+ norepeat[#norepeat+1] = m
+ end
+ end
+ if #norepeat == 0 then
+ return
end
- argm = argm .. ']'
- message = 'Argument of type in '..argm..' is not assignable to parameter of type in ['..flag..' ]'
callback{
start = arg.start,
finish = arg.finish,
- message = message
+ message = table.concat(norepeat, '\n')
}
- return
+ ::HIT::
end
- end
+ ---所有参数都匹配了
end)
end
diff --git a/script/proto/define.lua b/script/proto/define.lua
index fe7d171b..58eafe2a 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -17,7 +17,7 @@ m.DiagnosticSeverity = {
--- 诊断类型与默认等级
---@type table<string, DiagnosticDefaultSeverity>
m.DiagnosticDefaultSeverity = {
- ['type-check'] = "Hint",
+ ['type-check'] = "Warning",
['unused-local'] = 'Hint',
['unused-function'] = 'Hint',
['undefined-global'] = 'Warning',