summaryrefslogtreecommitdiff
path: root/server/src/core
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-03-18 16:23:16 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-03-18 16:23:16 +0800
commit357e62b68d67c4218d95f6bee937e6d5e206d752 (patch)
treed53917e3e64b7f252fcb54116c9e5609fe380805 /server/src/core
parentde4cec30d4befc0de4bd264c16c52c1a575cd5d3 (diff)
downloadlua-language-server-357e62b68d67c4218d95f6bee937e6d5e206d752.zip
重构文件符号
Diffstat (limited to 'server/src/core')
-rw-r--r--server/src/core/document_symbol.lua288
-rw-r--r--server/src/core/hover/hover.lua6
-rw-r--r--server/src/core/hover/name.lua69
-rw-r--r--server/src/core/name.lua70
4 files changed, 231 insertions, 202 deletions
diff --git a/server/src/core/document_symbol.lua b/server/src/core/document_symbol.lua
index e22fd4db..ac81277c 100644
--- a/server/src/core/document_symbol.lua
+++ b/server/src/core/document_symbol.lua
@@ -1,5 +1,5 @@
local hoverFunction = require 'core.hover.function'
-local hoverName = require 'core.hover.name'
+local getName = require 'core.name'
local hover = require 'core.hover'
local SymbolKind = {
@@ -31,171 +31,183 @@ local SymbolKind = {
TypeParameter = 26,
}
-local function isFirstSet(source, value)
- if source:action() ~= 'set' then
- return false
+local function buildLocal(vm, source, used, callback)
+ local vars = source[1]
+ local exps = source[2]
+ if vars.type ~= 'list' then
+ vars = {vars}
end
- local firstSrc = value:eachInfo(function (info, src)
- if info.type == 'set' then
- return src
- end
- end)
- if not firstSrc then
- return false
+ if not exps or exps.type ~= 'list' then
+ exps = {exps}
end
- if firstSrc ~= source then
- return false
+ for i, var in ipairs(vars) do
+ local exp = exps[i]
+ local data = {}
+ local loc = var:bindLocal()
+ data.name = loc:getName()
+ data.range = { var.start, var.finish }
+ data.selectionRange = { var.start, var.finish }
+ if exp then
+ local hvr = hover(var)
+ if exp.type == 'function' then
+ data.kind = SymbolKind.Function
+ else
+ data.kind = SymbolKind.Variable
+ end
+ data.detail = hvr.label:gsub('[\r\n]', '')
+ data.valueRange = { exp.start, exp.finish }
+ used[exp] = true
+ else
+ data.kind = SymbolKind.Variable
+ data.detail = ''
+ data.valueRange = { var.start, var.finish }
+ end
+ callback(data)
end
- return true
end
-local function buildLocal(vm, source, callback)
- local loc = source:bindLocal()
- local value = loc:getInitValue()
- local hvr = hover(source)
- if not hvr then
- return
+local function buildSet(vm, source, used, callback)
+ local vars = source[1]
+ local exps = source[2]
+ if vars.type ~= 'list' then
+ vars = {vars}
end
- local kind
- if value:getType() == 'function' then
- kind = SymbolKind.Function
- elseif source:get 'table index' then
- kind = SymbolKind.Class
- else
- kind = SymbolKind.Variable
- end
- local valueSource = value:getSource()
- if not valueSource or valueSource.start == 0 or value.uri ~= vm.uri then
- valueSource = source
- end
- local name = hvr.name
- if name == '' then
- name = tostring(source[1] or '')
- end
- -- 由于范围不允许交叉,为了支持 local x, y, z = 1, 2, 3 的形式
- -- 范围只能限定在变量上
- -- 而 local function xx() 的形式范围会包含整个 function
- if source.start > valueSource.start and source.finish < valueSource.finish then
- callback {
- name = name,
- detail = hvr.label:gsub('[\r\n]', ''),
- kind = kind,
- range = { valueSource.start, valueSource.finish },
- selectionRange = { source.start, source.finish },
- valueRange = { valueSource.start, valueSource.finish },
- }
- else
- callback {
- name = name,
- detail = hvr.label:gsub('[\r\n]', ''),
- kind = kind,
- range = { source.start, source.finish },
- selectionRange = { source.start, source.finish },
- valueRange = { valueSource.start, valueSource.finish },
- }
+ if not exps or exps.type ~= 'list' then
+ exps = {exps}
+ end
+ for i, var in ipairs(vars) do
+ if var:bindLocal() then
+ goto CONTINUE
+ end
+ local exp = exps[i]
+ local data = {}
+ data.name = getName(var)
+ data.range = { var.start, var.finish }
+ data.selectionRange = { var.start, var.finish }
+ if exp then
+ local hvr = hover(var)
+ if not hvr then
+ goto CONTINUE
+ end
+ if exp.type == 'function' then
+ data.kind = SymbolKind.Function
+ else
+ data.kind = SymbolKind.Property
+ end
+ data.detail = hvr.label:gsub('[\r\n]', '')
+ data.valueRange = { exp.start, exp.finish }
+ used[exp] = true
+ else
+ data.kind = SymbolKind.Property
+ data.detail = ''
+ data.valueRange = { var.start, var.finish }
+ end
+ callback(data)
+ :: CONTINUE ::
end
end
-local function buildSet(vm, source, callback)
- if source:bindLocal() then
- return
- end
- local value = source:bindValue()
- local hvr = hover(source)
- if not hvr then
- return
- end
- local kind
- if value:getFunction() then
- local func = value:getFunction()
- if func:getObject() then
- kind = SymbolKind.Field
+local function buildPair(vm, source, used, callback)
+ local var = source[1]
+ local exp = source[2]
+ local data = {}
+ data.name = getName(var)
+ data.range = { var.start, var.finish }
+ data.selectionRange = { var.start, var.finish }
+ if exp then
+ local hvr = hover(var)
+ if not hvr then
+ return
+ end
+ if exp.type == 'function' then
+ data.kind = SymbolKind.Function
else
- kind = SymbolKind.Function
+ data.kind = SymbolKind.Class
end
- elseif source:get 'table index' then
- kind = SymbolKind.Class
+ data.detail = hvr.label:gsub('[\r\n]', '')
+ data.valueRange = { exp.start, exp.finish }
+ used[exp] = true
else
- kind = SymbolKind.Property
- end
- local valueSource = value:getSource()
- if not valueSource or valueSource.start == 0 or value.uri ~= vm.uri then
- valueSource = source
- end
- local name = hvr.name
- if name == '' then
- name = tostring(source[1] or '')
- end
- -- 由于范围不允许交叉,为了支持 x, y, z = 1, 2, 3 的形式
- -- 范围只能限定在变量上
- -- 而 function xx() 的形式范围会包含整个 function
- if source.start > valueSource.start and source.finish < valueSource.finish then
- callback {
- name = name,
- -- 前端不支持多行
- detail = hvr.label:gsub('[\r\n]', ''),
- kind = kind,
- range = { valueSource.start, valueSource.finish },
- selectionRange = { source.start, source.finish },
- valueRange = { valueSource.start, valueSource.finish },
- }
- elseif isFirstSet(source, value) then
- callback {
- name = name,
- -- 前端不支持多行
- detail = hvr.label:gsub('[\r\n]', ''),
- kind = kind,
- range = { source.start, source.finish },
- selectionRange = { source.start, source.finish },
- valueRange = { valueSource.start, valueSource.finish },
- }
- else
- callback {
- name = name,
- -- 前端不支持多行
- detail = hvr.label:gsub('[\r\n]', ''),
- kind = kind,
- range = { source.start, source.finish },
- selectionRange = { source.start, source.finish },
- valueRange = { source.start, source.finish },
- }
+ data.kind = SymbolKind.Class
+ data.detail = ''
+ data.valueRange = { var.start, var.finish }
end
+ callback(data)
end
-local function buildReturn(vm, source, callback)
+local function buildLocalFunction(vm, source, used, callback)
local value = source:bindFunction()
if not value then
return
end
- local hvr = hoverFunction('', value:getFunction())
+ local name = getName(source.name)
+ local hvr = hoverFunction(name, value:getFunction())
if not hvr then
return
end
local kind = SymbolKind.Function
callback {
- name = '',
- -- 前端不支持多行
+ name = name,
detail = hvr.label:gsub('[\r\n]', ''),
kind = kind,
range = { source.start, source.finish },
- selectionRange = { source.start, source.start },
+ selectionRange = { source.name.start, source.name.finish },
valueRange = { source.start, source.finish },
}
end
-local function buildSource(vm, source, callback)
- if source:action() == 'local' then
- buildLocal(vm, source, callback)
+
+local function buildFunction(vm, source, used, callback)
+ if used[source] then
return
end
- if source:action() == 'set' then
- buildSet(vm, source, callback)
+ local value = source:bindFunction()
+ if not value then
return
end
- if source.type == 'return' then
- for _, src in ipairs(source) do
- buildReturn(vm, src, callback)
- end
+ local name = getName(source.name)
+ local func = value:getFunction()
+ local hvr = hoverFunction(name, func, func:getObject())
+ if not hvr then
+ return
+ end
+ local data = {}
+ data.name = name
+ data.detail = hvr.label:gsub('[\r\n]', '')
+ data.range = { source.start, source.finish }
+ data.valueRange = { source.start, source.finish }
+ if source.name then
+ data.selectionRange = { source.name.start, source.name.finish }
+ else
+ data.selectionRange = { source.start, source.start }
+ end
+ if func:getObject() then
+ data.kind = SymbolKind.Field
+ else
+ data.kind = SymbolKind.Function
+ end
+ callback(data)
+end
+
+local function buildSource(vm, source, used, callback)
+ if source.type == 'local' then
+ buildLocal(vm, source, used, callback)
+ return
+ end
+ if source.type == 'set' then
+ buildSet(vm, source, used, callback)
+ return
+ end
+ if source.type == 'pair' then
+ buildPair(vm, source, used, callback)
+ return
+ end
+ if source.type == 'localfunction' then
+ buildLocalFunction(vm, source, used, callback)
+ return
+ end
+ if source.type == 'function' then
+ buildFunction(vm, source, used, callback)
return
end
end
@@ -212,13 +224,10 @@ local function packChild(symbols, finish, kind)
end
symbols[#symbols] = nil
symbol.children = packChild(symbols, symbol.valueRange[2], symbol.kind)
- if symbol.kind == SymbolKind.Class and kind == SymbolKind.Function then
- else
- if not t then
- t = {}
- end
- t[#t+1] = symbol
+ if not t then
+ t = {}
end
+ t[#t+1] = symbol
end
return t
end
@@ -226,7 +235,7 @@ end
local function packSymbols(symbols)
-- 按照start位置反向排序
table.sort(symbols, function (a, b)
- return a.valueRange[1] > b.valueRange[1]
+ return a.range[1] > b.range[1]
end)
-- 处理嵌套
return packChild(symbols, math.maxinteger, SymbolKind.Function)
@@ -234,9 +243,10 @@ end
return function (vm)
local symbols = {}
+ local used = {}
for _, source in ipairs(vm.sources) do
- buildSource(vm, source, function (data)
+ buildSource(vm, source, used, function (data)
symbols[#symbols+1] = data
end)
end
diff --git a/server/src/core/hover/hover.lua b/server/src/core/hover/hover.lua
index c7aba17e..f09bfce4 100644
--- a/server/src/core/hover/hover.lua
+++ b/server/src/core/hover/hover.lua
@@ -220,5 +220,11 @@ return function (source, lsp, select)
if source.type == 'name' and source:bindValue() then
return hoverAsValue(source, lsp, select)
end
+ if source.type == 'simple' then
+ source = source[#source]
+ if source.type == 'name' and source:bindValue() then
+ return hoverAsValue(source, lsp, select)
+ end
+ end
return nil
end
diff --git a/server/src/core/hover/name.lua b/server/src/core/hover/name.lua
index 52bcfef4..e5880884 100644
--- a/server/src/core/hover/name.lua
+++ b/server/src/core/hover/name.lua
@@ -1,4 +1,9 @@
+local getName = require 'core.name'
+
return function (source)
+ if not source then
+ return ''
+ end
local value = source:bindValue()
if not value then
return ''
@@ -22,67 +27,5 @@ return function (source)
return name or ''
end
- local key
- 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] = '.'
- else
- chars[i] = '*' .. obj.type
- 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])
- elseif declarat.type == 'number' or declarat.type == 'boolean' then
- key = tostring(declarat[1])
- elseif declarat.type == 'simple' then
- local chars = {}
- for i, obj in ipairs(declarat) 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] = '.'
- else
- chars[i] = '*' .. obj.type
- 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 = ''
- end
- return key
+ return getName(declarat, source)
end
diff --git a/server/src/core/name.lua b/server/src/core/name.lua
new file mode 100644
index 00000000..54947974
--- /dev/null
+++ b/server/src/core/name.lua
@@ -0,0 +1,70 @@
+return function (source, caller)
+ if not source then
+ return ''
+ end
+ local key
+ if source:get 'simple' then
+ local simple = source: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] = '.'
+ else
+ chars[i] = '*' .. obj.type
+ end
+ if obj == source then
+ break
+ end
+ end
+ key = table.concat(chars)
+ elseif source.type == 'name' then
+ key = source[1]
+ elseif source.type == 'string' then
+ key = ('%q'):format(source[1])
+ elseif source.type == 'number' or source.type == 'boolean' then
+ key = tostring(source[1])
+ elseif source.type == 'simple' then
+ local chars = {}
+ for i, obj in ipairs(source) 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] = '.'
+ else
+ chars[i] = '*' .. obj.type
+ end
+ end
+ -- 这里有个特殊处理
+ -- function mt:func() 以 mt.func 的形式调用时
+ -- hover 显示为 mt.func(self)
+ if caller then
+ if chars[#chars-1] == ':' then
+ if not caller:get 'object' then
+ chars[#chars-1] = '.'
+ end
+ elseif chars[#chars-1] == '.' then
+ if caller:get 'object' then
+ chars[#chars-1] = ':'
+ end
+ end
+ end
+ key = table.concat(chars)
+ else
+ key = ''
+ end
+ return key
+end