summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/core/hover_function.lua2
-rw-r--r--server/src/core/hover_name.lua4
-rw-r--r--server/src/core/value.lua87
-rw-r--r--server/src/core/vm.lua26
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