diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-10-11 11:16:22 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-10-11 11:16:22 +0800 |
commit | a54939cb662f8730a011cababf37b634e6344300 (patch) | |
tree | 318e1434fa9a99863e7bb19f2ba1d33a313e86bd /server-beta/src/core | |
parent | 976e63df5340def77c363935f383da315ee5b5ab (diff) | |
download | lua-language-server-a54939cb662f8730a011cababf37b634e6344300.zip |
支持反找__index
Diffstat (limited to 'server-beta/src/core')
-rw-r--r-- | server-beta/src/core/engineer.lua | 92 | ||||
-rw-r--r-- | server-beta/src/core/field.lua | 38 | ||||
-rw-r--r-- | server-beta/src/core/local.lua | 41 |
3 files changed, 144 insertions, 27 deletions
diff --git a/server-beta/src/core/engineer.lua b/server-beta/src/core/engineer.lua index b41412aa..675bd803 100644 --- a/server-beta/src/core/engineer.lua +++ b/server-beta/src/core/engineer.lua @@ -1,6 +1,7 @@ local guide = require 'parser.guide' local require = require local tableUnpack = table.unpack +local error = error local setmetatable = setmetatable @@ -66,6 +67,13 @@ function mt:eachSpecial(callback) end function mt:eachField(source, key, callback) + local cache = self.cache.field[source] + if cache and cache[key] then + for i = 1, #cache[key] do + callback(tableUnpack(cache[key][i])) + end + return + end local tp = source.type local d = mt[tp] if not d then @@ -75,17 +83,36 @@ function mt:eachField(source, key, callback) if not f then return end + if self.step >= 100 then + error('Stack overflow!') + return + end + self.step = self.step + 1 local mark = {} + if not cache then + cache = {} + self.cache.field[source] = cache + end + cache[key] = {} f(self, source, key, function (src, ...) if mark[src] then return end mark[src] = true + cache[key][#cache[key]+1] = { src, ... } callback(src, ...) end) + self.step = self.step - 1 end function mt:eachRef(source, callback) + local cache = self.cache.ref[source] + if cache then + for i = 1, #cache do + callback(tableUnpack(cache[i])) + end + return + end local tp = source.type local d = mt[tp] if not d then @@ -95,17 +122,33 @@ function mt:eachRef(source, callback) if not f then return end + if self.step >= 100 then + error('Stack overflow!') + return + end + self.step = self.step + 1 + cache = {} + self.cache.ref[source] = cache local mark = {} f(self, source, function (src, ...) if mark[src] then return end mark[src] = true + cache[#cache+1] = {src, ...} callback(src, ...) end) + self.step = self.step - 1 end function mt:eachDef(source, callback) + local cache = self.cache.def[source] + if cache then + for i = 1, #cache do + callback(tableUnpack(cache[i])) + end + return + end local tp = source.type local d = mt[tp] if not d then @@ -115,17 +158,33 @@ function mt:eachDef(source, callback) if not f then return end + if self.step >= 100 then + error('Stack overflow!') + return + end + self.step = self.step + 1 + cache = {} + self.cache.def[source] = cache local mark = {} f(self, source, function (src, ...) if mark[src] then return end mark[src] = true + cache[#cache+1] = {src, ...} callback(src, ...) end) + self.step = self.step - 1 end function mt:eachValue(source, callback) + local cache = self.cache.value[source] + if cache then + for i = 1, #cache do + callback(tableUnpack(cache[i])) + end + return + end local tp = source.type local d = mt[tp] if not d then @@ -135,14 +194,23 @@ function mt:eachValue(source, callback) if not f then return end + if self.step >= 100 then + error('Stack overflow!') + return + end + self.step = self.step + 1 + cache = {} + self.cache.value[source] = cache local mark = {} f(self, source, function (src, ...) if mark[src] then return end mark[src] = true + cache[#cache+1] = {src, ...} callback(src, ...) end) + self.step = self.step - 1 end function mt:childDef(source, callback) @@ -184,11 +252,33 @@ function mt:callArgOf(source) return tableUnpack(args) end +function mt:callReturnOf(source) + if not source or source.type ~= 'call' then + return + end + local parent = source.parent + local extParent = source.extParent + if extParent then + local returns = {parent.parent} + for i = 1, #extParent do + returns[i+1] = extParent[i].parent + end + return tableUnpack(returns) + elseif parent then + return parent.parent + end +end + return function (ast) local self = setmetatable({ step = 0, ast = ast.ast, - cache = {}, + cache = { + def = {}, + ref = {}, + field = {}, + value = {}, + }, }, mt) return self end diff --git a/server-beta/src/core/field.lua b/server-beta/src/core/field.lua index 95c9954f..997b38e3 100644 --- a/server-beta/src/core/field.lua +++ b/server-beta/src/core/field.lua @@ -3,23 +3,33 @@ local guide = require 'parser.guide' local m = {} function m:def(source, callback) - local node = source.parent.node - local key = guide.getKeyName(source) - self:eachField(node, key, function (src, mode) - if mode == 'set' then - callback(src, mode) - end - end) + local parent = source.parent + if parent.type == 'setfield' or parent.type == 'getfield' then + local node = parent.node + local key = guide.getKeyName(source) + self:eachField(node, key, function (src, mode) + if mode == 'set' then + callback(src, mode) + end + end) + elseif parent.type == 'tablefield' then + self:eachDef(parent.value, callback) + end end function m:ref(source, callback) - local node = source.parent.node - local key = guide.getKeyName(source) - self:eachField(node, key, function (src, mode) - if mode == 'set' or mode == 'get' then - callback(src, mode) - end - end) + local parent = source.parent + if parent.type == 'setfield' or parent.type == 'getfield' then + local node = parent.node + local key = guide.getKeyName(source) + self:eachField(node, key, function (src, mode) + if mode == 'set' or mode == 'get' then + callback(src, mode) + end + end) + elseif parent.type == 'tablefield' then + self:eachDef(parent.value, callback) + end end function m:value(source, callback) diff --git a/server-beta/src/core/local.lua b/server-beta/src/core/local.lua index 575a9360..adbb9138 100644 --- a/server-beta/src/core/local.lua +++ b/server-beta/src/core/local.lua @@ -42,6 +42,7 @@ end function m:field(source, key, callback) local used = {} + used[source] = true local refs = source.ref if refs then for i = 1, #refs do @@ -78,28 +79,44 @@ function m:field(source, key, callback) end end) self:eachSpecial(function (name, src) + local call = src.parent if name == 'rawset' then - local t, k = self:callArgOf(src.parent) + local t, k = self:callArgOf(call) if used[t] and guide.getKeyName(k) == key then - callback(src.parent, 'set') + callback(call, 'set') end elseif name == 'rawget' then - local t, k, v = self:callArgOf(src.parent) + local t, k, v = self:callArgOf(call) if used[t] and guide.getKeyName(k) == key then - callback(src.parent, 'get') + callback(call, 'get') self:eachField(v, key, callback) end elseif name == 'setmetatable' then - local t, mt = self:callArgOf(src.parent) - if used[t] then - self:eachField(mt, 's|__index', function (src, mode) - if mode == 'set' then - self:eachValue(src, function (src) - self:eachField(src, key, callback) + local t, mt = self:callArgOf(call) + self:eachField(mt, 's|__index', function (src, mode) + if mode == 'set' then + -- t.field -> mt.__index.field + if used[t] then + self:eachValue(src, function (mtvalue) + self:eachField(mtvalue, key, callback) end) end - end) - end + -- mt.__index.field -> t.field + self:eachDef(src, function (src) + if used[src] then + self:eachValue(t, function (mtvalue) + self:eachField(mtvalue, key, callback) + end) + local obj = self:callReturnOf(call) + if obj then + self:eachValue(obj, function (mtvalue) + self:eachField(mtvalue, key, callback) + end) + end + end + end) + end + end) end end) end |