summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2020-09-27 17:51:13 +0800
committer最萌小汐 <sumneko@hotmail.com>2020-09-27 17:51:13 +0800
commitafc09241d9075d73cb76661a02613a6e114df686 (patch)
treea71006af6318a9c445185c6495fe4e8d67d085fa
parent6c34663ba8d3392136f0c0cedb0c402810e442da (diff)
downloadlua-language-server-afc09241d9075d73cb76661a02613a6e114df686.zip
工作区符号
-rw-r--r--.vscode/launch.json2
-rw-r--r--script-beta/core/document-symbol.lua196
-rw-r--r--script-beta/core/hover/return.lua6
-rw-r--r--script-beta/core/symbol.lua199
-rw-r--r--script-beta/core/workspace-symbol.lua29
-rw-r--r--script-beta/provider/provider.lua35
6 files changed, 266 insertions, 201 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 5095cfb2..838f6b24 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -48,7 +48,7 @@
"type": "lua",
"request": "attach",
"stopOnEntry": true,
- "address": "127.0.0.1:11414",
+ "address": "127.0.0.1:11413",
"outputCapture": [
]
},
diff --git a/script-beta/core/document-symbol.lua b/script-beta/core/document-symbol.lua
index dabb8a25..efa54f57 100644
--- a/script-beta/core/document-symbol.lua
+++ b/script-beta/core/document-symbol.lua
@@ -1,187 +1,5 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local skind = require 'define.SymbolKind'
-local lname = require 'core.hover.name'
-local util = require 'utility'
-local await = require 'await'
-
-local function buildFunctionParams(func)
- if not func.args then
- return ''
- end
- local params = {}
- for i, arg in ipairs(func.args) do
- if arg.type == '...' then
- params[i] = '...'
- else
- params[i] = arg[1] or ''
- end
- end
- return table.concat(params, ', ')
-end
-
-local function buildFunction(source, symbols)
- local name = lname(source)
- local func = source.value
- if source.type == 'tablefield'
- or source.type == 'setfield' then
- source = source.field
- end
- local range, kind
- if func.start > source.finish then
- -- a = function()
- range = { source.start, func.finish }
- else
- -- function f()
- range = { func.start, func.finish }
- end
- if source.type == 'setmethod' then
- kind = skind.Field
- else
- kind = skind.Function
- end
- symbols[#symbols+1] = {
- name = name,
- detail = ('function (%s)'):format(buildFunctionParams(func)),
- kind = kind,
- range = range,
- selectionRange = { source.start, source.finish },
- valueRange = { func.start, func.finish },
- }
-end
-
-local function buildTable(tbl)
- local buf = {}
- for i = 1, 3 do
- local field = tbl[i]
- if not field then
- break
- end
- if field.type == 'tablefield' then
- buf[i] = ('%s'):format(field.field[1])
- end
- end
- return table.concat(buf, ', ')
-end
-
-local function buildValue(source, symbols)
- local name = lname(source)
- local range, sRange, valueRange, kind
- local details = {}
- if source.type == 'local' then
- if source.parent.type == 'funcargs' then
- details[1] = 'param'
- range = { source.start, source.finish }
- sRange = { source.start, source.finish }
- kind = skind.Constant
- else
- details[1] = 'local'
- range = { source.start, source.finish }
- sRange = { source.start, source.finish }
- kind = skind.Variable
- end
- elseif source.type == 'setlocal' then
- details[1] = 'setlocal'
- range = { source.start, source.finish }
- sRange = { source.start, source.finish }
- kind = skind.Variable
- elseif source.type == 'setglobal' then
- details[1] = 'global'
- range = { source.start, source.finish }
- sRange = { source.start, source.finish }
- kind = skind.Class
- elseif source.type == 'tablefield' then
- details[1] = 'field'
- range = { source.field.start, source.field.finish }
- sRange = { source.field.start, source.field.finish }
- kind = skind.Property
- else
- details[1] = 'field'
- range = { source.field.start, source.field.finish }
- sRange = { source.field.start, source.field.finish }
- kind = skind.Field
- end
- if source.value then
- local literal = source.value[1]
- if source.value.type == 'boolean' then
- details[2] = ' boolean'
- if literal ~= nil then
- details[3] = ' = '
- details[4] = util.viewLiteral(source.value[1])
- end
- elseif source.value.type == 'string' then
- details[2] = ' string'
- if literal ~= nil then
- details[3] = ' = '
- details[4] = util.viewLiteral(source.value[1])
- end
- elseif source.value.type == 'number' then
- details[2] = ' number'
- if literal ~= nil then
- details[3] = ' = '
- details[4] = util.viewLiteral(source.value[1])
- end
- elseif source.value.type == 'table' then
- details[2] = ' {'
- details[3] = buildTable(source.value)
- details[4] = '}'
- valueRange = { source.value.start, source.value.finish }
- elseif source.value.type == 'select' then
- if source.value.vararg and source.value.vararg.type == 'call' then
- valueRange = { source.value.start, source.value.finish }
- end
- end
- range = { range[1], source.value.finish }
- end
- symbols[#symbols+1] = {
- name = name,
- detail = table.concat(details),
- kind = kind,
- range = range,
- selectionRange = sRange,
- valueRange = valueRange,
- }
-end
-
-local function buildSet(source, used, symbols)
- local value = source.value
- if value and value.type == 'function' then
- used[value] = true
- buildFunction(source, symbols)
- else
- buildValue(source, symbols)
- end
-end
-
-local function buildAnonymousFunction(source, used, symbols)
- if used[source] then
- return
- end
- used[source] = true
- symbols[#symbols+1] = {
- name = '',
- detail = 'function ()',
- kind = skind.Function,
- range = { source.start, source.finish },
- selectionRange = { source.start, source.start },
- valueRange = { source.start, source.finish },
- }
-end
-
-local function buildSource(source, used, symbols)
- if source.type == 'local'
- or source.type == 'setlocal'
- or source.type == 'setglobal'
- or source.type == 'setfield'
- or source.type == 'setmethod'
- or source.type == 'tablefield' then
- await.delay()
- buildSet(source, used, symbols)
- elseif source.type == 'function' then
- await.delay()
- buildAnonymousFunction(source, used, symbols)
- end
-end
+local await = require 'await'
+local symbol = require 'core.symbol'
local function packChild(ranges, symbols)
await.delay()
@@ -244,17 +62,11 @@ local function packSymbols(symbols)
end
return function (uri)
- local ast = files.getAst(uri)
- if not ast then
+ local symbols = symbol(uri)
+ if not symbols then
return nil
end
- local symbols = {}
- local used = {}
- guide.eachSource(ast.ast, function (source)
- buildSource(source, used, symbols)
- end)
-
local packedSymbols = packSymbols(symbols)
return packedSymbols
diff --git a/script-beta/core/hover/return.lua b/script-beta/core/hover/return.lua
index 3e340b5b..0fd11c57 100644
--- a/script-beta/core/hover/return.lua
+++ b/script-beta/core/hover/return.lua
@@ -68,8 +68,10 @@ local function asFunction(source)
for n = 1, #rtn do
local values = vm.getInfers(rtn[n])
for _, value in ipairs(values) do
- for tp in value.type:gmatch '[^|]+' do
- types[#types+1] = tp
+ if value.type then
+ for tp in value.type:gmatch '[^|]+' do
+ types[#types+1] = tp
+ end
end
end
end
diff --git a/script-beta/core/symbol.lua b/script-beta/core/symbol.lua
new file mode 100644
index 00000000..eeed234d
--- /dev/null
+++ b/script-beta/core/symbol.lua
@@ -0,0 +1,199 @@
+local files = require 'files'
+local guide = require 'parser.guide'
+local skind = require 'define.SymbolKind'
+local lname = require 'core.hover.name'
+local util = require 'utility'
+local await = require 'await'
+
+local function buildFunctionParams(func)
+ if not func.args then
+ return ''
+ end
+ local params = {}
+ for i, arg in ipairs(func.args) do
+ if arg.type == '...' then
+ params[i] = '...'
+ else
+ params[i] = arg[1] or ''
+ end
+ end
+ return table.concat(params, ', ')
+end
+
+local function buildFunction(source, symbols)
+ local name = lname(source)
+ local func = source.value
+ if source.type == 'tablefield'
+ or source.type == 'setfield' then
+ source = source.field
+ end
+ local range, kind
+ if func.start > source.finish then
+ -- a = function()
+ range = { source.start, func.finish }
+ else
+ -- function f()
+ range = { func.start, func.finish }
+ end
+ if source.type == 'setmethod' then
+ kind = skind.Field
+ else
+ kind = skind.Function
+ end
+ symbols[#symbols+1] = {
+ name = name,
+ detail = ('function (%s)'):format(buildFunctionParams(func)),
+ kind = kind,
+ range = range,
+ selectionRange = { source.start, source.finish },
+ valueRange = { func.start, func.finish },
+ }
+end
+
+local function buildTable(tbl)
+ local buf = {}
+ for i = 1, 3 do
+ local field = tbl[i]
+ if not field then
+ break
+ end
+ if field.type == 'tablefield' then
+ buf[i] = ('%s'):format(field.field[1])
+ end
+ end
+ return table.concat(buf, ', ')
+end
+
+local function buildValue(source, symbols)
+ local name = lname(source)
+ local range, sRange, valueRange, kind
+ local details = {}
+ if source.type == 'local' then
+ if source.parent.type == 'funcargs' then
+ details[1] = 'param'
+ range = { source.start, source.finish }
+ sRange = { source.start, source.finish }
+ kind = skind.Constant
+ else
+ details[1] = 'local'
+ range = { source.start, source.finish }
+ sRange = { source.start, source.finish }
+ kind = skind.Variable
+ end
+ elseif source.type == 'setlocal' then
+ details[1] = 'setlocal'
+ range = { source.start, source.finish }
+ sRange = { source.start, source.finish }
+ kind = skind.Variable
+ elseif source.type == 'setglobal' then
+ details[1] = 'global'
+ range = { source.start, source.finish }
+ sRange = { source.start, source.finish }
+ kind = skind.Class
+ elseif source.type == 'tablefield' then
+ details[1] = 'field'
+ range = { source.field.start, source.field.finish }
+ sRange = { source.field.start, source.field.finish }
+ kind = skind.Property
+ else
+ details[1] = 'field'
+ range = { source.field.start, source.field.finish }
+ sRange = { source.field.start, source.field.finish }
+ kind = skind.Field
+ end
+ if source.value then
+ local literal = source.value[1]
+ if source.value.type == 'boolean' then
+ details[2] = ' boolean'
+ if literal ~= nil then
+ details[3] = ' = '
+ details[4] = util.viewLiteral(source.value[1])
+ end
+ elseif source.value.type == 'string' then
+ details[2] = ' string'
+ if literal ~= nil then
+ details[3] = ' = '
+ details[4] = util.viewLiteral(source.value[1])
+ end
+ elseif source.value.type == 'number' then
+ details[2] = ' number'
+ if literal ~= nil then
+ details[3] = ' = '
+ details[4] = util.viewLiteral(source.value[1])
+ end
+ elseif source.value.type == 'table' then
+ details[2] = ' {'
+ details[3] = buildTable(source.value)
+ details[4] = '}'
+ valueRange = { source.value.start, source.value.finish }
+ elseif source.value.type == 'select' then
+ if source.value.vararg and source.value.vararg.type == 'call' then
+ valueRange = { source.value.start, source.value.finish }
+ end
+ end
+ range = { range[1], source.value.finish }
+ end
+ symbols[#symbols+1] = {
+ name = name,
+ detail = table.concat(details),
+ kind = kind,
+ range = range,
+ selectionRange = sRange,
+ valueRange = valueRange,
+ }
+end
+
+local function buildSet(source, used, symbols)
+ local value = source.value
+ if value and value.type == 'function' then
+ used[value] = true
+ buildFunction(source, symbols)
+ else
+ buildValue(source, symbols)
+ end
+end
+
+local function buildAnonymousFunction(source, used, symbols)
+ if used[source] then
+ return
+ end
+ used[source] = true
+ symbols[#symbols+1] = {
+ name = '',
+ detail = 'function ()',
+ kind = skind.Function,
+ range = { source.start, source.finish },
+ selectionRange = { source.start, source.start },
+ valueRange = { source.start, source.finish },
+ }
+end
+
+local function buildSource(source, used, symbols)
+ if source.type == 'local'
+ or source.type == 'setlocal'
+ or source.type == 'setglobal'
+ or source.type == 'setfield'
+ or source.type == 'setmethod'
+ or source.type == 'tablefield' then
+ await.delay()
+ buildSet(source, used, symbols)
+ elseif source.type == 'function' then
+ await.delay()
+ buildAnonymousFunction(source, used, symbols)
+ end
+end
+
+return function (uri)
+ local ast = files.getAst(uri)
+ if not ast then
+ return nil
+ end
+
+ local symbols = {}
+ local used = {}
+ guide.eachSource(ast.ast, function (source)
+ buildSource(source, used, symbols)
+ end)
+
+ return symbols
+end
diff --git a/script-beta/core/workspace-symbol.lua b/script-beta/core/workspace-symbol.lua
index a2d1d8dd..6b2c309e 100644
--- a/script-beta/core/workspace-symbol.lua
+++ b/script-beta/core/workspace-symbol.lua
@@ -1,7 +1,28 @@
-local files = require 'files'
-local define = require 'proto.define'
-local skind = require 'define.symbolkind'
+local files = require 'files'
+local symbol = require 'core.symbol'
+local guide = require 'parser.guide'
+local matchKey = require 'core.matchkey'
+
+local function searchFile(uri, key, results)
+ local symbols = symbol(uri)
+ if not symbols then
+ return
+ end
+
+ for _, res in ipairs(symbols) do
+ if res.name ~= '' and matchKey(key, res.name) then
+ res.uri = uri
+ results[#results+1] = res
+ end
+ end
+end
return function (key)
-
+ local results = {}
+
+ for uri in files.eachFile() do
+ searchFile(files.getOriginUri(uri), key, results)
+ end
+
+ return results
end
diff --git a/script-beta/provider/provider.lua b/script-beta/provider/provider.lua
index 7c61db14..68c498c6 100644
--- a/script-beta/provider/provider.lua
+++ b/script-beta/provider/provider.lua
@@ -511,6 +511,7 @@ proto.on('textDocument/documentSymbol', function (params)
if symbol.name == '' then
symbol.name = lang.script.SYMBOL_ANONYMOUS
end
+ symbol.valueRange = nil
if symbol.children then
for _, child in ipairs(symbol.children) do
convert(child)
@@ -549,6 +550,36 @@ proto.on('workspace/executeCommand', function (params)
end
end)
-proto.on('workspaceSymbolProvider', function (params)
-
+proto.on('workspace/symbol', function (params)
+ local core = require 'core.workspace-symbol'
+
+ await.close('workspace/symbol')
+ await.setID('workspace/symbol')
+
+ local symbols = core(params.query)
+ if not symbols or #symbols == 0 then
+ return nil
+ end
+
+ local function convert(symbol)
+ symbol.location = define.location(
+ symbol.uri,
+ define.range(
+ files.getLines(symbol.uri),
+ files.getText(symbol.uri),
+ symbol.range[1],
+ symbol.range[2]
+ )
+ )
+ symbol.uri = nil
+ symbol.detail = nil
+ symbol.selectionRange = nil
+ symbol.valueRange = nil
+ end
+
+ for _, symbol in ipairs(symbols) do
+ convert(symbol)
+ end
+
+ return symbols
end)