diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2018-11-29 16:11:55 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2018-11-29 16:11:55 +0800 |
commit | 01fae72b1a503857a5735f76988ab257f298b256 (patch) | |
tree | a75f616f8261c6b49e709a96ac0e8c7c24a03919 /server | |
parent | 5db32ce42188ec69858c34715a8e4f5778ddc9df (diff) | |
download | lua-language-server-01fae72b1a503857a5735f76988ab257f298b256.zip |
更新
Diffstat (limited to 'server')
-rw-r--r-- | server/src/matcher/definition.lua | 190 | ||||
-rw-r--r-- | server/src/matcher/env.lua | 15 |
2 files changed, 159 insertions, 46 deletions
diff --git a/server/src/matcher/definition.lua b/server/src/matcher/definition.lua index a4c8fd3d..d7fe722e 100644 --- a/server/src/matcher/definition.lua +++ b/server/src/matcher/definition.lua @@ -9,7 +9,11 @@ end function mt:checkName(name) if self:isContainPos(name) then local str = name[1] - self.result = self.env.var[str] or self.env.var._ENV[str] + local var = self.env.var[str] or self.env.var._ENV[str] + self.result = { + type = 'var', + var = var, + } self.stop = true return self.result else @@ -84,17 +88,14 @@ function mt:searchExp(exp) elseif tp == '...' then result = self:checkDots(exp) elseif tp == 'function' then + self:searchFunction(exp) elseif tp == 'table' then end return result end function mt:searchReturn(action) - local exps = action[1] - if not exps then - return nil - end - for _, exp in ipairs(exps) do + for _, exp in ipairs(action) do local result = self:searchExp(exp) if result then return result @@ -103,14 +104,6 @@ function mt:searchReturn(action) return nil end -function mt:checkThenSearchActionsIn(actions) - if self:isContainPos(actions) then - return self:searchActionsIn(actions) - else - return nil - end -end - function mt:markSet(simple) if simple.type == 'name' then local str = simple[1] @@ -143,58 +136,165 @@ function mt:createLocal(str, type, source) } end -function mt:markLocal(simple) - if simple.type == 'name' then - local str = simple[1] +function mt:markLocal(name) + if name.type == 'name' then + local str = name[1] -- 创建一个局部变量 - self:createLocal(str, 'local', simple) - self:checkName(simple) - else - slef:searchSimple(simple) + self:createLocal(str, 'local', name) + self:checkName(name) + elseif name.type == '...' then + self.env.dots = name end end -function mt:markSets(action) - local simples = action[1] - if simples.type == 'list' then - for _, simple in ipairs(simples) do - self:markSet(simple) +function mt:forList(list, callback) + if list.type == 'list' then + for i = 1, #list do + callback(list[i]) end else - self:markSet(simples) + callback(list) end end +function mt:markSets(action) + local keys = action[1] + local values = action[2] + -- 要先计算赋值 + self:forList(values, function (value) + self:searchExp(value) + end) + self:forList(keys, function (key) + self:markSet(key) + end) +end + function mt:markLocals(action) - local simples = action[1] - if simple.type == 'list' then - for _, simple in ipairs(simples) do - self:markLocal(simple) + local keys = action[1] + local values = action[2] + -- 要先计算赋值 + if values then + self:forList(values, function (value) + self:searchExp(value) + end) + end + self:forList(keys, function (key) + self:markLocal(key) + end) +end + +function mt:searchIfs(action) + for _, block in ipairs(action) do + self.env:push() + if block.filter then + self:searchExp(block.filter) end - else - self:markLocal(simples) + self:searchActions(block) + self.env:pop() end end +function mt:searchLoop(action) + self.env:push() + self:markLocal(action.arg) + self:searchExp(action.min) + self:searchExp(action.max) + if action.step then + self:searchExp(action.step) + end + self:searchActions(action) + self.env:pop() +end + +function mt:searchIn(action) + self:forList(action.exp, function (exp) + self:searchExp(exp) + end) + self.env:push() + self:forList(action.arg, function (arg) + self:markLocal(arg) + end) + self:searchActions(action) + self.env:pop() +end + +function mt:searchDo(action) + self.env:push() + self:searchActions(action) + self.env:pop() +end + +function mt:searchWhile(action) + self:searchExp(action.filter) + self.env:push() + self:searchActions(action) + self.env:pop() +end + +function mt:searchRepeat(action) + self.env:push() + self:searchActions(action) + self:searchExp(action.filter) + self.env:pop() +end + +function mt:searchFunction(func) + self.env:push() + if func.name then + self:markSet(func.name) + end + if func.arg then + self:forList(func.arg, function (arg) + self:markLocal(arg) + end) + end + self:searchActions(func) + self.env:pop() +end + +function mt:searchLocalFunction(func) + self:markSet(func.name) + self.env:push() + if func.arg then + self:forList(func.arg, function (arg) + self:markLocal(arg) + end) + end + self:searchActions(func) + self.env:pop() +end + function mt:searchAction(action) local tp = action.type - local result if tp == 'do' then - result = self:checkThenSearchActionsIn(action) + self:searchDo(action) elseif tp == 'break' then elseif tp == 'return' then - result = self:searchReturn(action) + self:searchReturn(action) elseif tp == 'label' then elseif tp == 'goto' then elseif tp == 'set' then self:markSets(action) elseif tp == 'local' then self:markLocals(action) + elseif tp == 'if' then + self:searchIfs(action) + elseif tp == 'loop' then + self:searchLoop(action) + elseif tp == 'in' then + self:searchIn(action) + elseif tp == 'while' then + self:searchWhile(action) + elseif tp == 'repeat' then + self:searchRepeat(action) + elseif tp == 'function' then + self:searchFunction(action) + elseif tp == 'localfunction' then + self:searchLocalFunction(action) end - return result end -function mt:searchActionsIn(actions) +function mt:searchActions(actions) for _, action in ipairs(actions) do self:searchAction(action) if self.stop then @@ -204,18 +304,26 @@ function mt:searchActionsIn(actions) return nil end +local function parseResult(result) + local tp = result.type + if tp == 'var' then + local first = result.var[1] + local source = first.source + return true, source.start, source.finish + end +end + return function (ast, pos) local searcher = setmetatable({ pos = pos, env = env {var = {}, usable = {}, label = {}}, }, mt) searcher.env.var._ENV = {} - searcher:searchActionsIn(ast) + searcher:searchActions(ast) if not searcher.result then return false end - local source = searcher.result[1].source - return true, source.start, source.finish + return parseResult(searcher.result) end diff --git a/server/src/matcher/env.lua b/server/src/matcher/env.lua index 3a7388d1..13787fc0 100644 --- a/server/src/matcher/env.lua +++ b/server/src/matcher/env.lua @@ -1,3 +1,8 @@ +local setmetatable = setmetatable +local pairs = pairs +local type = type +local table_sort = table.sort + return function (root) local env = {root} local is_table = {} @@ -10,11 +15,11 @@ return function (root) root._cut = {} local mt = { _env = env } - function mt:add() - table.insert(env, { _next = env[#env], _cut = {} }) + function mt:push() + env[#env+1] = { _next = env[#env], _cut = {} } end - function mt:remove() - table.remove(env) + function mt:pop() + env[#env] = nil end function mt:cut(key) env[#env]._cut[key] = true @@ -122,7 +127,7 @@ return function (root) break end end - table.sort(keys) + table_sort(keys) local i = 0 return function () i = i + 1 |