diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-01-28 14:59:18 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-01-28 14:59:18 +0800 |
commit | e25be4fc724d0cc56b12c6453426763c750a7dc7 (patch) | |
tree | aed52b65331a72b7999e1e627095c1bcdf0795f8 /server/src | |
parent | 22c78de4cc682ff31cbf16abc3688eba35df62cb (diff) | |
download | lua-language-server-e25be4fc724d0cc56b12c6453426763c750a7dc7.zip |
运行时分析meta方法
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/core/hover_function.lua | 2 | ||||
-rw-r--r-- | server/src/core/hover_name.lua | 4 | ||||
-rw-r--r-- | server/src/core/value.lua | 87 | ||||
-rw-r--r-- | server/src/core/vm.lua | 26 |
4 files changed, 81 insertions, 38 deletions
diff --git a/server/src/core/hover_function.lua b/server/src/core/hover_function.lua index 8c0908d2..68818028 100644 --- a/server/src/core/hover_function.lua +++ b/server/src/core/hover_function.lua @@ -75,7 +75,7 @@ local function buildValueReturns(func) local strs = {} if func.returns then for i, rtn in ipairs(func.returns) do - strs[i] = rtn.type + strs[i] = rtn:getType() end end if #strs == 0 then diff --git a/server/src/core/hover_name.lua b/server/src/core/hover_name.lua index d8afe2fc..affc33f3 100644 --- a/server/src/core/hover_name.lua +++ b/server/src/core/hover_name.lua @@ -1,8 +1,8 @@ return function (result, source) local func = result.value local declarat - if func.type == 'function' then - declarat = func.declarat or source + if func:getType() == 'function' then + declarat = func:getDeclarat() or source else declarat = source end diff --git a/server/src/core/value.lua b/server/src/core/value.lua index 5aa374ad..c0f8848d 100644 --- a/server/src/core/value.lua +++ b/server/src/core/value.lua @@ -42,6 +42,14 @@ function mt:getType() return mType or 'any' end +function mt:setMetaTable(metatable, source) + if not self._meta then + self._meta = {} + end + local uri = source and source.uri or '' + self._meta[uri] = metatable +end + function mt:createField(name, source) local field = { type = 'field', @@ -65,21 +73,42 @@ end function mt:rawGetField(name, source) local uri = source and source.uri or '' - local field - if self._child then - if self._child[uri] then - field = self._child[uri][name] + if not self._child then + return nil + end + if self._child[uri] then + local field = self._child[uri][name] + if field then + return field end - if not field then - for _, childs in pairs(self._child) do - field = childs[name] - if field then - break - end - end + end + for _, childs in pairs(self._child) do + local field = childs[name] + if field then + return field end end - return field + return nil +end + +function mt:_getMeta(name, source) + if not self._meta then + return nil + end + local uri = source and source.uri or '' + if self._meta[uri] then + local meta = self._meta[uri]:rawGetField(name, source) + if meta then + return meta + end + end + for _, indexValue in pairs(self._meta) do + local meta = indexValue:rawGetField(name, source) + if meta then + return meta + end + end + return nil end function mt:getChild() @@ -93,10 +122,21 @@ function mt:setChild(child) self._child = child end -function mt:getField(name, source) +function mt:getField(name, source, stack) local field = self:rawGetField(name, source) if not field then - field = self:createField(name, source) + local indexMeta = self:_getMeta('__index', source) + if not indexMeta then + return nil + end + if not stack then + stack = 0 + end + stack = stack + 1 + if stack > 10 then + return nil + end + return indexMeta.value:getField(name, source, stack) end return field end @@ -116,6 +156,17 @@ function mt:eachField(callback) end end +function mt:getDeclarat() + return self:eachInfo(function (info) + if info.type == 'local' + or info.type == 'set' + or info.type == 'return' + then + return info.source + end + end) +end + function mt:addInfo(tp, source, var) if source and not source.start then error('Miss start: ' .. table.dump(source)) @@ -137,13 +188,17 @@ end function mt:eachInfo(callback) if not self._info then - return + return nil end for _, infos in pairs(self._info) do for i = 1, #infos do - callback(infos[i]) + local res = callback(infos[i]) + if res ~= nil then + return res + end end end + return nil end return function (tp, source, value) diff --git a/server/src/core/vm.lua b/server/src/core/vm.lua index 52c67606..9c7ee732 100644 --- a/server/src/core/vm.lua +++ b/server/src/core/vm.lua @@ -487,17 +487,7 @@ function mt:getFunctionArg(func, i) return func.argValues[i] end -function mt:checkMetaIndex(value, meta) - local index = meta:getField('__index') - if not index then - return - end - local indexValue = self:getValue(index) - -- TODO 支持function - self:mergeChild(value, indexValue) -end - -function mt:callSetMetaTable(func, values) +function mt:callSetMetaTable(func, values, source) if not values[1] then values[1] = self:createValue('any') end @@ -505,10 +495,7 @@ function mt:callSetMetaTable(func, values) values[2] = self:createValue('any') end self:setFunctionReturn(func, 1, values[1]) - - values[1].metatable = values[2] - -- 检查 __index - self:checkMetaIndex(values[1], values[2]) + values[1]:setMetaTable(values[2], source) end function mt:getRequire(strValue, destVM) @@ -653,7 +640,7 @@ function mt:call(func, values, source) end if lib.special then if lib.special == 'setmetatable' then - self:callSetMetaTable(func, values) + self:callSetMetaTable(func, values, source) elseif lib.special == 'require' then self:callRequire(func, values) elseif lib.special == 'loadfile' then @@ -818,7 +805,8 @@ function mt:getName(name, source) return loc end local ENV = self.scope.locals._ENV - local global = self:getValue(ENV):getField(name, source) + local ENVValue = self:getValue(ENV) + local global = ENVValue:getField(name, source) or ENVValue:createField(name, source) global.parent = ENV return global end @@ -947,7 +935,7 @@ function mt:getSimple(simple, mode) elseif tp == 'index' then local child = obj[1] local index = self:getIndex(child) - field = value:getField(index, child) + field = value:getField(index, child) or value:createField(index, child) field.parentValue = value value = self:getValue(field) if mode == 'value' or i < #simple then @@ -965,7 +953,7 @@ function mt:getSimple(simple, mode) parentName = ('%s[?]'):format(parentName) end elseif tp == 'name' then - field = value:getField(obj[1], obj) + field = value:getField(obj[1], obj) or value:createField(obj[1], obj) field.parentValue = value value = self:getValue(field) if mode == 'value' or i < #simple then |