summaryrefslogtreecommitdiff
path: root/script/core/document_symbol.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-11-23 00:05:30 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-11-23 00:05:30 +0800
commit6da2b175e20ed3c03b0dfcfc9046de1e0e5d4444 (patch)
treefdc22d78150fd1c5edc46732c8b151ccfefb519f /script/core/document_symbol.lua
parentd0ff66c9abe9d6abbca12fd811e0c3cb69c1033a (diff)
downloadlua-language-server-6da2b175e20ed3c03b0dfcfc9046de1e0e5d4444.zip
正路目录
Diffstat (limited to 'script/core/document_symbol.lua')
-rw-r--r--script/core/document_symbol.lua260
1 files changed, 260 insertions, 0 deletions
diff --git a/script/core/document_symbol.lua b/script/core/document_symbol.lua
new file mode 100644
index 00000000..48e01332
--- /dev/null
+++ b/script/core/document_symbol.lua
@@ -0,0 +1,260 @@
+local hoverFunction = require 'core.hover.function'
+local getName = require 'core.name'
+local hover = require 'core.hover'
+
+local SymbolKind = {
+ File = 1,
+ Module = 2,
+ Namespace = 3,
+ Package = 4,
+ Class = 5,
+ Method = 6,
+ Property = 7,
+ Field = 8,
+ Constructor = 9,
+ Enum = 10,
+ Interface = 11,
+ Function = 12,
+ Variable = 13,
+ Constant = 14,
+ String = 15,
+ Number = 16,
+ Boolean = 17,
+ Array = 18,
+ Object = 19,
+ Key = 20,
+ Null = 21,
+ EnumMember = 22,
+ Struct = 23,
+ Event = 24,
+ Operator = 25,
+ TypeParameter = 26,
+}
+
+local function buildLocal(vm, source, used, callback)
+ local vars = source[1]
+ local exps = source[2]
+ if vars.type ~= 'list' then
+ vars = {vars}
+ end
+ if not exps or exps.type ~= 'list' then
+ exps = {exps}
+ end
+ 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
+end
+
+local function buildSet(vm, source, used, callback)
+ local vars = source[1]
+ local exps = source[2]
+ if vars.type ~= 'list' then
+ vars = {vars}
+ end
+ 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 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
+ data.kind = SymbolKind.Class
+ end
+ data.detail = hvr.label:gsub('[\r\n]', '')
+ data.valueRange = { exp.start, exp.finish }
+ used[exp] = true
+ else
+ data.kind = SymbolKind.Class
+ data.detail = ''
+ data.valueRange = { var.start, var.finish }
+ end
+ callback(data)
+end
+
+local function buildLocalFunction(vm, source, used, callback)
+ local value = source:bindFunction()
+ if not value then
+ return
+ end
+ local name = getName(source.name)
+ local hvr = hoverFunction(name, value:getFunction())
+ if not hvr then
+ return
+ end
+ local kind = SymbolKind.Function
+ callback {
+ name = name,
+ detail = hvr.label:gsub('[\r\n]', ''),
+ kind = kind,
+ range = { source.start, source.finish },
+ selectionRange = { source.name.start, source.name.finish },
+ valueRange = { source.start, source.finish },
+ }
+end
+
+
+local function buildFunction(vm, source, used, callback)
+ if used[source] then
+ return
+ end
+ local value = source:bindFunction()
+ if not value then
+ return
+ end
+ local name = getName(source.name)
+ local func = value:getFunction()
+ if not func then
+ return
+ end
+ 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
+
+local function packChild(symbols, finish, kind)
+ local t
+ while true do
+ local symbol = symbols[#symbols]
+ if not symbol then
+ break
+ end
+ if symbol.valueRange[1] > finish then
+ break
+ end
+ symbols[#symbols] = nil
+ symbol.children = packChild(symbols, symbol.valueRange[2], symbol.kind)
+ if not t then
+ t = {}
+ end
+ t[#t+1] = symbol
+ end
+ return t
+end
+
+local function packSymbols(symbols)
+ -- 按照start位置反向排序
+ table.sort(symbols, function (a, b)
+ return a.range[1] > b.range[1]
+ end)
+ -- 处理嵌套
+ return packChild(symbols, math.maxinteger, SymbolKind.Function)
+end
+
+return function (vm)
+ local symbols = {}
+ local used = {}
+
+ vm:eachSource(function (source)
+ buildSource(vm, source, used, function (data)
+ symbols[#symbols+1] = data
+ end)
+ end)
+
+ local packedSymbols = packSymbols(symbols)
+
+ return packedSymbols
+end