diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-03-05 16:21:08 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-03-05 16:21:08 +0800 |
commit | a9507cd6a329d2be66035ca2019ded070fc7ad33 (patch) | |
tree | 7e3738add820d09763ed57dba6551c69cb01b197 /server/src | |
parent | 908738e65b6af347f051d7b4439d4820efa60605 (diff) | |
download | lua-language-server-a9507cd6a329d2be66035ca2019ded070fc7ad33.zip |
hover支持class
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/core/diagnostics.lua | 6 | ||||
-rw-r--r-- | server/src/core/find_lib.lua | 16 | ||||
-rw-r--r-- | server/src/core/hover.lua | 133 | ||||
-rw-r--r-- | server/src/core/hover_function.lua | 8 | ||||
-rw-r--r-- | server/src/core/hover_name.lua | 34 | ||||
-rw-r--r-- | server/src/vm/function.lua | 6 | ||||
-rw-r--r-- | server/src/vm/local.lua | 4 | ||||
-rw-r--r-- | server/src/vm/source.lua | 4 | ||||
-rw-r--r-- | server/src/vm/vm.lua | 16 |
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 |