diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2018-12-10 11:56:04 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2018-12-10 11:56:04 +0800 |
commit | 6aa19b14e48d5c81af0cda08362a975392a45565 (patch) | |
tree | 7757fe162dd61d1f08387f9942d7502c3d661d4b /server | |
parent | fdc9a81f6f220a9fab4087a6a4d3eb7c346498e6 (diff) | |
download | lua-language-server-6aa19b14e48d5c81af0cda08362a975392a45565.zip |
根据一些运算符来推导
Diffstat (limited to 'server')
-rw-r--r-- | server/src/matcher/compile.lua | 18 | ||||
-rw-r--r-- | server/src/matcher/type_inference.lua | 111 | ||||
-rw-r--r-- | server/test/type_inference/init.lua | 36 |
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 +]] |