summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-03-05 16:21:08 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-03-05 16:21:08 +0800
commita9507cd6a329d2be66035ca2019ded070fc7ad33 (patch)
tree7e3738add820d09763ed57dba6551c69cb01b197 /server/src
parent908738e65b6af347f051d7b4439d4820efa60605 (diff)
downloadlua-language-server-a9507cd6a329d2be66035ca2019ded070fc7ad33.zip
hover支持class
Diffstat (limited to 'server/src')
-rw-r--r--server/src/core/diagnostics.lua6
-rw-r--r--server/src/core/find_lib.lua16
-rw-r--r--server/src/core/hover.lua133
-rw-r--r--server/src/core/hover_function.lua8
-rw-r--r--server/src/core/hover_name.lua34
-rw-r--r--server/src/vm/function.lua6
-rw-r--r--server/src/vm/local.lua4
-rw-r--r--server/src/vm/source.lua4
-rw-r--r--server/src/vm/vm.lua16
9 files changed, 137 insertions, 90 deletions
diff --git a/server/src/core/diagnostics.lua b/server/src/core/diagnostics.lua
index a08cace4..eb4ca403 100644
--- a/server/src/core/diagnostics.lua
+++ b/server/src/core/diagnostics.lua
@@ -24,7 +24,7 @@ function mt:searchUnusedLocals(callback)
if source:action() ~= 'local' then
return
end
- if loc:getFlag 'hide' then
+ if loc:get 'hide' then
return
end
local used = loc:eachInfo(function (info)
@@ -40,7 +40,7 @@ end
function mt:searchUndefinedGlobal(callback)
self.vm:eachSource(function (source)
- if not source:getFlag 'global' then
+ if not source:get 'global' then
return
end
local value = source:bindValue()
@@ -156,7 +156,7 @@ function mt:searchRedefinition(callback)
return
end
used[shadow] = true
- if loc:getFlag 'hide' then
+ if loc:get 'hide' then
return
end
local name = loc:getName()
diff --git a/server/src/core/find_lib.lua b/server/src/core/find_lib.lua
index 11174b2a..60a2a75e 100644
--- a/server/src/core/find_lib.lua
+++ b/server/src/core/find_lib.lua
@@ -20,32 +20,32 @@ local function findLib(source)
return nil
end
if lib.parent then
- if source:getFlag 'object' then
+ if source:get 'object' then
-- *string:sub
local fullKey = ('*%s:%s'):format(getParentName(lib, true), lib.name)
- return lib, fullKey, true
+ return lib, fullKey
else
- local parentValue = source:getFlag 'parent'
+ local parentValue = source:get 'parent'
if parentValue and parentValue:getType() == 'string' then
-- *string.sub
local fullKey = ('*%s.%s'):format(getParentName(lib, false), lib.name)
- return lib, fullKey, false
+ return lib, fullKey
else
-- string.sub
local fullKey = ('%s.%s'):format(getParentName(lib, false), lib.name)
- return lib, fullKey, false
+ return lib, fullKey
end
end
else
local name = lib.nick or lib.name
- return lib, name, false
+ return lib, name
end
end
return function (source)
if source:bindValue() then
- local lib, fullKey, oo = findLib(source)
- return lib, fullKey, oo
+ local lib, fullKey = findLib(source)
+ return lib, fullKey
end
return nil
end
diff --git a/server/src/core/hover.lua b/server/src/core/hover.lua
index 06e95379..a18ba00b 100644
--- a/server/src/core/hover.lua
+++ b/server/src/core/hover.lua
@@ -209,42 +209,54 @@ local function getFunctionHoverAsLib(name, lib, oo, select)
}
end
-local function findClass(result)
- -- 查找meta表的 __name 字段
- local name = result.value:getMeta('__name', result.source)
- -- 值必须是字符串
- if name and name.value and type(name.value:getValue()) == 'string' then
- return name.value:getValue()
+local function findClass(value)
+ -- 检查对象元表
+ local metaValue = value:getMetaTable()
+ if not metaValue then
+ return nil
end
- -- 查找meta表 __index 里的字段
- local index = result.value:getMeta('__index', result.source)
- if index and index.value then
- return index.value:eachField(function (key, field)
- -- 键值类型必须均为字符串
- if type(key) ~= 'string' then
- goto CONTINUE
- end
- if not field.value or type(field.value:getValue()) ~= 'string' then
- goto CONTINUE
- end
- local lKey = key:lower()
- if lKey == 'type' or lKey == 'name' or lKey == 'class' then
- -- 必须只有过一次赋值
- local hasSet = false
- for _, info in ipairs(field) do
- if info.type == 'set' then
- if hasSet then
- goto CONTINUE
- end
+ -- 检查元表中的 __name
+ local metaName = metaValue:rawGet('__name')
+ if metaName and type(metaName:getLiteral()) == 'string' then
+ return metaName:getLiteral()
+ end
+ -- 检查元表的 __index
+ local indexValue = metaValue:rawGet('__index')
+ if not indexValue then
+ return nil
+ end
+ -- 查找index方法中的以下字段: type name class
+ -- 允许多重继承
+ return indexValue:eachChild(function (k, v)
+ -- 键值类型必须均为字符串
+ if type(k) ~= 'string' then
+ return
+ end
+ if type(v:getLiteral()) ~= 'string' then
+ return
+ end
+ local lKey = k:lower()
+ if lKey == 'type'
+ or lKey == 'name'
+ or lKey == 'class'
+ then
+ -- 必须只有过一次赋值
+ local hasSet = false
+ local ok = v:eachInfo(function (info)
+ if info.type == 'set' then
+ if hasSet then
+ return false
+ else
hasSet = true
end
end
- return field.value:getValue()
+ end)
+ if ok == false then
+ return false
end
- ::CONTINUE::
- end)
- end
- return nil
+ return v:getLiteral()
+ end
+ end)
end
local function unpackTable(result)
@@ -291,46 +303,53 @@ local function unpackTable(result)
return table.concat(lines, '\r\n')
end
-local function getValueHover(name, valueType, result, lib)
+local function getValueHover(source, name, value, lib)
+ local valueType = value:getType()
+
if not lib then
- local class = findClass(result)
+ local class = findClass(value)
if class then
valueType = class
end
end
- if type(valueType) == 'table' then
- valueType = valueType[1]
- end
-
if not OriginTypes[valueType] then
valueType = '*' .. valueType
end
- local value
local tip
+ local literal
if lib then
- value = lib.code or (lib.value and ('%q'):format(lib.value))
- tip = lib.description
+ --value = lib.code or (lib.value and ('%q'):format(lib.value))
+ --tip = lib.description
else
- value = result.value:getValue() and ('%q'):format(result.value:getValue())
+ literal = value:getLiteral() and ('%q'):format(value:getLiteral())
end
- local tp = result.type
- if tp == 'field' then
- if result.GLOBAL then
+ local tp
+ if source:bindLocal() then
+ tp = 'local'
+ elseif source:get 'global' then
+ tp = 'global'
+ elseif source:get 'simple' then
+ local simple = source:get 'simple'
+ if simple[1]:get 'global' then
tp = 'global'
+ else
+ tp = 'field'
end
+ else
+ tp = 'field'
end
local text
if valueType == 'table' then
- text = ('%s %s: %s'):format(tp, name, unpackTable(result))
+ text = ('%s %s: %s'):format(tp, name, unpackTable(value))
else
- if value == nil then
+ if literal == nil then
text = ('%s %s: %s'):format(tp, name, valueType)
else
- text = ('%s %s: %s = %s'):format(tp, name, valueType, value)
+ text = ('%s %s: %s = %s'):format(tp, name, valueType, literal)
end
end
return {
@@ -353,7 +372,7 @@ local function getStringHover(result, lsp)
end
local function hoverAsValue(source, lsp, select)
- local lib, fullkey, isObject = findLib(source)
+ local lib, fullkey = findLib(source)
local value = source:bindValue()
local name = fullkey or buildValueName(source)
@@ -361,9 +380,10 @@ local function hoverAsValue(source, lsp, select)
if value:getType() == 'function' then
if lib then
else
- hover = getFunctionHover(name, value:getFunction(), source:getFlag 'object', select)
+ hover = getFunctionHover(name, value:getFunction(), source:get 'object', select)
end
else
+ hover = getValueHover(source, name, value, lib)
end
if not hover then
@@ -374,20 +394,7 @@ local function hoverAsValue(source, lsp, select)
end
local function hoverAsVar(result, source, lsp, select)
- if not result.value then
- return
- end
-
- if result.key == '' then
- return
- end
-
-
- if result.type ~= 'local' and result.type ~= 'field' then
- return
- end
-
- local lib, fullKey, oo = findLib(result)
+ local lib, fullKey = findLib(result)
local valueType = lib and lib.type
if valueType then
if type(valueType) == 'table' then
diff --git a/server/src/core/hover_function.lua b/server/src/core/hover_function.lua
index 0eef37df..1b313f55 100644
--- a/server/src/core/hover_function.lua
+++ b/server/src/core/hover_function.lua
@@ -1,4 +1,7 @@
local function buildValueArgs(func, object, select)
+ if not func then
+ return '', nil
+ end
local names = {}
local values = {}
if func:getObject() then
@@ -72,7 +75,10 @@ local function buildValueArgs(func, object, select)
end
local function buildValueReturns(func)
- if not func.hasReturn then
+ if not func then
+ return '\n -> any'
+ end
+ if not func:get 'hasReturn' then
return ''
end
local strs = {}
diff --git a/server/src/core/hover_name.lua b/server/src/core/hover_name.lua
index 3c0c9564..485ce69a 100644
--- a/server/src/core/hover_name.lua
+++ b/server/src/core/hover_name.lua
@@ -12,7 +12,27 @@ return function (source)
end
local key
- if declarat.type == 'name' then
+ if declarat:get 'simple' then
+ local simple = declarat:get 'simple'
+ local chars = {}
+ for i, obj in ipairs(simple) do
+ if obj.type == 'name' then
+ chars[i] = obj[1]
+ elseif obj.type == 'index' then
+ chars[i] = '[?]'
+ elseif obj.type == 'call' then
+ chars[i] = '(?)'
+ elseif obj.type == ':' then
+ chars[i] = ':'
+ elseif obj.type == '.' then
+ chars[i] = '.'
+ end
+ if obj == declarat then
+ break
+ end
+ end
+ key = table.concat(chars)
+ elseif declarat.type == 'name' then
key = declarat[1]
elseif declarat.type == 'string' then
key = ('%q'):format(declarat[1])
@@ -33,6 +53,18 @@ return function (source)
chars[i] = '.'
end
end
+ -- 这里有个特殊处理
+ -- function mt:func() 以 mt.func 的形式调用时
+ -- hover 显示为 mt.func(self)
+ if chars[#chars-1] == ':' then
+ if not source:get 'object' then
+ chars[#chars-1] = '.'
+ end
+ elseif chars[#chars-1] == '.' then
+ if source:get 'object' then
+ chars[#chars-1] = ':'
+ end
+ end
key = table.concat(chars)
else
key = ''
diff --git a/server/src/vm/function.lua b/server/src/vm/function.lua
index 976f8ab2..8cebdf8f 100644
--- a/server/src/vm/function.lua
+++ b/server/src/vm/function.lua
@@ -80,7 +80,7 @@ function mt:loadLabel(name)
end
function mt:setReturn(index, value)
- self.hasReturn = true
+ self:set('hasReturn', true)
if not self.returns then
self.returns = createMulti()
end
@@ -216,14 +216,14 @@ function mt:createArgs()
end
end
-function mt:setFlag(name, v)
+function mt:set(name, v)
if not self._flag then
self._flag = {}
end
self._flag[name] = v
end
-function mt:getFlag(name)
+function mt:get(name)
if not self._flag then
return nil
end
diff --git a/server/src/vm/local.lua b/server/src/vm/local.lua
index 6062d28e..570f453d 100644
--- a/server/src/vm/local.lua
+++ b/server/src/vm/local.lua
@@ -38,14 +38,14 @@ function mt:eachInfo(callback)
end
end
-function mt:setFlag(name, v)
+function mt:set(name, v)
if not self._flag then
self._flag = {}
end
self._flag[name] = v
end
-function mt:getFlag(name)
+function mt:get(name)
if not self._flag then
return nil
end
diff --git a/server/src/vm/source.lua b/server/src/vm/source.lua
index 5dcdac66..98102bf7 100644
--- a/server/src/vm/source.lua
+++ b/server/src/vm/source.lua
@@ -62,14 +62,14 @@ function mt:getUri()
return self._uri
end
-function mt:setFlag(name, v)
+function mt:set(name, v)
if not self._flag then
self._flag = {}
end
self._flag[name] = v
end
-function mt:getFlag(name)
+function mt:get(name)
if not self._flag then
return nil
end
diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua
index 3ab10630..c147439a 100644
--- a/server/src/vm/vm.lua
+++ b/server/src/vm/vm.lua
@@ -313,8 +313,8 @@ function mt:call(value, values, source)
self:callLibrary(func, values, source, lib)
else
if func.source then
- if not source:getFlag 'called' then
- source:setFlag('called', true)
+ if not source:get 'called' then
+ source:set('called', true)
func:setArgs(values)
self:runFunction(func)
end
@@ -348,7 +348,7 @@ function mt:getName(name, source)
if global then
return global
end
- source:setFlag('global', true)
+ source:set('global', true)
local ENV = self:loadLocal('_ENV')
local ENVValue = ENV:getValue()
global = ENVValue:getChild(name) or ENVValue:setChild(name, createValue('any', source))
@@ -368,7 +368,7 @@ function mt:setName(name, source, value)
if global then
return global
end
- source:setFlag('global', true)
+ source:set('global', true)
source:bindValue(global, 'set')
local ENV = self:loadLocal('_ENV')
local ENVValue = ENV:getValue()
@@ -448,6 +448,7 @@ function mt:getSimple(simple, max)
for i = 2, max do
local source = simple[i]
self:instantSource(source)
+ source:set('simple', simple)
value = self:getFirstInMulti(value) or createValue('nil')
if source.type == 'call' then
@@ -465,8 +466,8 @@ function mt:getSimple(simple, max)
value = value:getChild(index) or value:setChild(index, createValue('any', source))
source:bindValue(value, 'get')
elseif source.type == 'name' then
- source:setFlag('parent', value)
- source:setFlag('object', object)
+ source:set('parent', value)
+ source:set('object', object)
value = value:getChild(source[1]) or value:setChild(source[1], createValue('any', source))
source:bindValue(value, 'get')
elseif source.type == ':' then
@@ -725,6 +726,7 @@ function mt:setOne(var, value)
local parent = self:getSimple(var, -2)
local key = var[#var]
self:instantSource(key)
+ key:set('simple', var)
if key.type == 'index' then
local index = self:getIndex(key[1])
parent:setChild(index, value)
@@ -1073,7 +1075,7 @@ function mt:createEnvironment(ast)
local global = buildGlobal(self.lsp)
-- 隐藏的上值`_ENV`
local env = self:createLocal('_ENV', nil, global)
- env:setFlag('hide', true)
+ env:set('hide', true)
self.env = env
end