summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2018-12-10 11:56:04 +0800
committer最萌小汐 <sumneko@hotmail.com>2018-12-10 11:56:04 +0800
commit6aa19b14e48d5c81af0cda08362a975392a45565 (patch)
tree7757fe162dd61d1f08387f9942d7502c3d661d4b /server
parentfdc9a81f6f220a9fab4087a6a4d3eb7c346498e6 (diff)
downloadlua-language-server-6aa19b14e48d5c81af0cda08362a975392a45565.zip
根据一些运算符来推导
Diffstat (limited to 'server')
-rw-r--r--server/src/matcher/compile.lua18
-rw-r--r--server/src/matcher/type_inference.lua111
-rw-r--r--server/test/type_inference/init.lua36
3 files changed, 153 insertions, 12 deletions
diff --git a/server/src/matcher/compile.lua b/server/src/matcher/compile.lua
index de9f914b..53da49e0 100644
--- a/server/src/matcher/compile.lua
+++ b/server/src/matcher/compile.lua
@@ -242,12 +242,20 @@ function mt:searchSimple(simple)
end
function mt:searchBinary(exp)
- self:searchExp(exp[1])
- self:searchExp(exp[2])
+ return {
+ type = 'binary',
+ op = exp.op,
+ [1] = self:searchExp(exp[1]),
+ [2] = self:searchExp(exp[2]),
+ }
end
function mt:searchUnary(exp)
- self:searchExp(exp[1])
+ return {
+ type = 'unary',
+ op = exp.op,
+ [1] = self:searchExp(exp[1]),
+ }
end
function mt:searchTable(exp)
@@ -309,9 +317,9 @@ function mt:searchExp(exp)
elseif tp == 'simple' then
return self:searchSimple(exp)
elseif tp == 'binary' then
- self:searchBinary(exp)
+ return self:searchBinary(exp)
elseif tp == 'unary' then
- self:searchUnary(exp)
+ return self:searchUnary(exp)
elseif tp == '...' then
self:checkDots(exp)
elseif tp == 'function' then
diff --git a/server/src/matcher/type_inference.lua b/server/src/matcher/type_inference.lua
index e689c482..19205413 100644
--- a/server/src/matcher/type_inference.lua
+++ b/server/src/matcher/type_inference.lua
@@ -1,6 +1,77 @@
local mt = {}
mt.__index = mt
+function mt:setType(obj, type)
+ if not obj then
+ return
+ end
+ if not obj.group then
+ obj.group = {
+ type = type,
+ }
+ end
+ obj.valuetype = type
+end
+
+function mt:getType(obj)
+ if not obj then
+ return nil
+ end
+ if obj.valuetype then
+ return obj.valuetype
+ end
+ if obj.group then
+ return obj.group.type
+ end
+ return nil
+end
+
+function mt:getUnaryType(obj)
+ if obj.op == 'not' then
+ return 'boolean'
+ elseif obj.op == '#' then
+ return 'integer'
+ elseif obj.op == '-' then
+ return 'number'
+ elseif obj.op == '~' then
+ return 'integer'
+ end
+ return nil
+end
+
+function mt:getBinaryType(obj)
+ if obj.op == 'or'
+ or obj.op == 'and'
+ or obj.op == '<='
+ or obj.op == '>='
+ or obj.op == '<'
+ or obj.op == '>'
+ or obj.op == '~='
+ or obj.op == '=='
+ then
+ return 'boolean'
+ elseif obj.op == '|'
+ or obj.op == '~'
+ or obj.op == '&'
+ or obj.op == '<<'
+ or obj.op == '>>'
+ or obj.op == '//'
+ then
+ return 'integer'
+ elseif obj.op == '..' then
+ return 'string'
+ elseif obj.op == '+'
+ or obj.op == '-'
+ or obj.op == '*'
+ or obj.op == '/'
+ or obj.op == '^'
+ or obj.op == '%'
+ then
+ return 'number'
+ end
+ return nil
+end
+
function mt:searchGroup(group)
if not group then
return
@@ -14,6 +85,22 @@ function mt:searchGroup(group)
return
end
end
+ for obj in pairs(group) do
+ -- TODO 搜索metatable
+ if obj.type == 'unary' then
+ local type = self:getUnaryType(obj)
+ if type then
+ group.type = type
+ return
+ end
+ elseif obj.type == 'binary' then
+ local type = self:getBinaryType(obj)
+ if type then
+ group.type = type
+ return
+ end
+ end
+ end
group.type = false
end
@@ -24,16 +111,13 @@ function mt:searchVar(var)
if self.lock[var] then
return
end
- if not var.group and next(var.childs) then
- var.valuetype = 'table'
- var.group = {
- type = 'table',
- }
- return
- end
self.lock[var] = true
self:searchGroup(var.group)
self.lock[var] = nil
+ if not self:getType(var) and next(var.childs) then
+ self:setType(var, 'table')
+ return
+ end
end
function mt:searchVars(vars)
@@ -42,9 +126,22 @@ function mt:searchVars(vars)
end
end
+function mt:searchCall(call)
+ if not self:getType(call.func) then
+ self:setType(call.func, 'function')
+ end
+end
+
+function mt:searchCalls(calls)
+ for _, call in ipairs(calls) do
+ self:searchCall(call)
+ end
+end
+
return function (results)
local session = setmetatable({
lock = {},
}, mt)
session:searchVars(results.vars)
+ session:searchCalls(results.calls)
end
diff --git a/server/test/type_inference/init.lua b/server/test/type_inference/init.lua
index c4446a51..4097eb2f 100644
--- a/server/test/type_inference/init.lua
+++ b/server/test/type_inference/init.lua
@@ -70,6 +70,42 @@ local <?t?>
t = {}
]]
+TEST 'function' [[
+<?x?>()
+]]
+
TEST 'table' [[
<?t?>.x = 1
]]
+
+TEST 'boolean' [[
+<?x?> = not y
+]]
+
+TEST 'integer' [[
+<?x?> = #y
+]]
+
+TEST 'number' [[
+<?x?> = - y
+]]
+
+TEST 'integer' [[
+<?x?> = ~ y
+]]
+
+TEST 'boolean' [[
+<?x?> = a and b
+]]
+
+TEST 'integer' [[
+<?x?> = a << b
+]]
+
+TEST 'string' [[
+<?x?> = a .. b
+]]
+
+TEST 'number' [[
+<?x?> = a + b
+]]