summaryrefslogtreecommitdiff
path: root/server/src/core
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/core
parent908738e65b6af347f051d7b4439d4820efa60605 (diff)
downloadlua-language-server-a9507cd6a329d2be66035ca2019ded070fc7ad33.zip
hover支持class
Diffstat (limited to 'server/src/core')
-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
5 files changed, 121 insertions, 76 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 = ''