summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2018-12-19 13:25:16 +0800
committer最萌小汐 <sumneko@hotmail.com>2018-12-19 13:25:16 +0800
commit3400b54cca23a5440502897fd848dd01684d021b (patch)
tree33e61542f25ee2132b628ad2abb06e788fca5151
parent21f5a489430b04caee6cdc4b62f34bc3ca884181 (diff)
downloadlua-language-server-3400b54cca23a5440502897fd848dd01684d021b.zip
找局部变量
-rw-r--r--server/src/matcher/completion.lua121
-rw-r--r--server/src/matcher/diagnostics.lua6
-rw-r--r--server/src/matcher/vm.lua43
-rw-r--r--server/src/method/textDocument/completion.lua50
-rw-r--r--server/src/service.lua4
-rw-r--r--server/test/completion/init.lua72
6 files changed, 228 insertions, 68 deletions
diff --git a/server/src/matcher/completion.lua b/server/src/matcher/completion.lua
index 66b993a4..910173f0 100644
--- a/server/src/matcher/completion.lua
+++ b/server/src/matcher/completion.lua
@@ -1,8 +1,129 @@
local findResult = require 'matcher.find_result'
+local CompletionItemKind = {
+ Text = 1,
+ Method = 2,
+ Function = 3,
+ Constructor = 4,
+ Field = 5,
+ Variable = 6,
+ Class = 7,
+ Interface = 8,
+ Module = 9,
+ Property = 10,
+ Unit = 11,
+ Value = 12,
+ Enum = 13,
+ Keyword = 14,
+ Snippet = 15,
+ Color = 16,
+ File = 17,
+ Reference = 18,
+ Folder = 19,
+ EnumMember = 20,
+ Constant = 21,
+ Struct = 22,
+ Event = 23,
+ Operator = 24,
+ TypeParameter = 25,
+}
+
+local function matchKey(me, other)
+ if me == other then
+ return false
+ end
+ if #me > #other then
+ return false
+ end
+ local lMe = me:lower()
+ local lOther = other:lower()
+ if lMe:sub(1, 1) ~= lOther:sub(1, 1) then
+ return false
+ end
+ if lMe == lOther:sub(1, #lMe) then
+ return true
+ end
+ local used = {
+ [1] = true,
+ }
+ local cur = 2
+ local lookup
+ local researched
+ for i = 2, #lMe do
+ local c = lMe:sub(i, i)
+ -- 1. 看当前字符是否匹配
+ if c == lOther:sub(cur, cur) then
+ used[cur] = true
+ goto NEXT
+ end
+ -- 2. 看前一个字符是否匹配
+ if not used[cur-1] then
+ if c == lOther:sub(cur-1, cur-1) then
+ used[cur-1] = true
+ goto NEXT
+ end
+ end
+ -- 3. 向后找这个字
+ lookup = lOther:find(c, cur+1, true)
+ if lookup then
+ cur = lookup
+ used[cur] = true
+ goto NEXT
+ end
+
+ -- 4. 重新搜索整个字符串,但是只允许1次,否则失败.如果找不到也失败
+ if researched then
+ return false
+ else
+ researched = true
+ for j = 2, cur - 2 do
+ if c == lOther:sub(j, j) then
+ used[j] = true
+ goto NEXT
+ end
+ end
+ return false
+ end
+ -- 5. 找到下一个可用的字,如果超出长度则失败
+ ::NEXT::
+ repeat
+ cur = cur + 1
+ until not used[cur]
+ if cur > #lOther then
+ return false
+ end
+ end
+ return true
+end
+
+local function searchLocals(vm, pos, name, callback)
+ for _, loc in ipairs(vm.results.locals) do
+ if loc.source.start == 0 then
+ goto CONTINUE
+ end
+ if loc.source.start <= pos and loc.close >= pos then
+ if matchKey(name, loc.key) then
+ callback(loc.key)
+ end
+ end
+ ::CONTINUE::
+ end
+end
+
return function (vm, pos)
local result = findResult(vm, pos)
if not result then
return nil
end
+ local list = {}
+ local source = result.source
+ if source.type == 'name' then
+ searchLocals(vm, pos, result.key, function (label)
+ list[#list+1] = {
+ label = label,
+ kind = CompletionItemKind.Variable,
+ }
+ end)
+ end
+ return list
end
diff --git a/server/src/matcher/diagnostics.lua b/server/src/matcher/diagnostics.lua
index 7a190354..f22ce7cb 100644
--- a/server/src/matcher/diagnostics.lua
+++ b/server/src/matcher/diagnostics.lua
@@ -150,7 +150,11 @@ local function searchRedundantParameters(results, callback)
local passed = #call.args
for i = max + 1, passed do
local source = call.args[i]
- callback(source.start, source.finish, max, passed)
+ if source.start then
+ callback(source.start, source.finish, max, passed)
+ else
+ log.error('No start: ', table.dump(source))
+ end
end
::NEXT_CALL::
end
diff --git a/server/src/matcher/vm.lua b/server/src/matcher/vm.lua
index e1da6a81..83c29555 100644
--- a/server/src/matcher/vm.lua
+++ b/server/src/matcher/vm.lua
@@ -11,10 +11,12 @@ function mt:createLocal(key, source, value)
type = 'local',
key = key,
source = source or DefaultSource,
+ close = self.scope.block.finish,
}
local shadow = self.scope.locals[key]
if shadow then
+ shadow.close = source and (source.start-1)
local group
if shadow.shadow then
group = shadow.shadow
@@ -34,6 +36,18 @@ function mt:createLocal(key, source, value)
return loc
end
+function mt:scopePush(block)
+ if not block.start then
+ error('Scope push without start!')
+ end
+ self.scope:push()
+ self.scope.block = block
+end
+
+function mt:scopePop()
+ self.scope:pop()
+end
+
function mt:addInfo(obj, type, source)
if source and not source.start then
error('Miss start: ' .. table.dump(source))
@@ -255,7 +269,7 @@ function mt:buildFunction(exp, object)
func.built = true
- self.scope:push()
+ self:scopePush(exp)
self.chunk:push()
self.chunk:cut 'dots'
self.chunk:cut 'labels'
@@ -291,7 +305,7 @@ function mt:buildFunction(exp, object)
self.results.funcs[#self.results.funcs+1] = func
self.chunk:pop()
- self.scope:pop()
+ self:scopePop()
return func
end
@@ -889,9 +903,9 @@ function mt:getExp(exp)
end
function mt:doDo(action)
- self.scope:push()
+ self:scopePush(action)
self:doActions(action)
- self.scope:pop()
+ self:scopePop()
end
function mt:doReturn(action)
@@ -961,9 +975,9 @@ function mt:doIf(action)
self:getExp(block.filter)
end
- self.scope:push()
+ self:scopePush(block)
self:doActions(block)
- self.scope:pop()
+ self:scopePop()
end
end
@@ -975,16 +989,16 @@ function mt:doLoop(action)
self:getExp(action.step)
end
- self.scope:push()
+ self:scopePush(action)
self:createLocal(action.arg[1], action.arg, min)
self:doActions(action)
- self.scope:pop()
+ self:scopePop()
end
function mt:doIn(action)
local args = self:unpackList(action.exp)
- self.scope:push()
+ self:scopePush(action)
local func = table.remove(args, 1) or self:createValue('any')
local values = self:call(func, args)
self:forList(action.arg, function (arg)
@@ -994,23 +1008,23 @@ function mt:doIn(action)
self:doActions(action)
- self.scope:pop()
+ self:scopePop()
end
function mt:doWhile(action)
self:getExp(action.filter)
- self.scope:push()
+ self:scopePush(action)
self:doActions(action)
- self.scope:pop()
+ self:scopePop()
end
function mt:doRepeat(action)
- self.scope:push()
+ self:scopePush(action)
self:doActions(action)
self:getExp(action.filter)
- self.scope:pop()
+ self:scopePop()
end
function mt:doFunction(action)
@@ -1081,6 +1095,7 @@ function mt:doActions(actions)
end
function mt:createEnvironment()
+ self.scope.block = { start = 0, finish = math.maxinteger }
-- 整个文件是一个函数
self.chunk.func = self:buildFunction()
self.results.main = self.chunk.func
diff --git a/server/src/method/textDocument/completion.lua b/server/src/method/textDocument/completion.lua
index 9b040f17..2e03882e 100644
--- a/server/src/method/textDocument/completion.lua
+++ b/server/src/method/textDocument/completion.lua
@@ -1,29 +1,29 @@
local CompletionItemKind = {
- Text = 1,
- Method = 2,
- Function = 3,
- Constructor = 4,
- Field = 5,
- Variable = 6,
- Class = 7,
- Interface = 8,
- Module = 9,
- Property = 10,
- Unit = 11,
- Value = 12,
- Enum = 13,
- Keyword = 14,
- Snippet = 15,
- Color = 16,
- File = 17,
- Reference = 18,
- Folder = 19,
- EnumMember = 20,
- Constant = 21,
- Struct = 22,
- Event = 23,
- Operator = 24,
- TypeParameter = 25,
+ Text = 1,
+ Method = 2,
+ Function = 3,
+ Constructor = 4,
+ Field = 5,
+ Variable = 6,
+ Class = 7,
+ Interface = 8,
+ Module = 9,
+ Property = 10,
+ Unit = 11,
+ Value = 12,
+ Enum = 13,
+ Keyword = 14,
+ Snippet = 15,
+ Color = 16,
+ File = 17,
+ Reference = 18,
+ Folder = 19,
+ EnumMember = 20,
+ Constant = 21,
+ Struct = 22,
+ Event = 23,
+ Operator = 24,
+ TypeParameter = 25,
}
return function (lsp, params)
diff --git a/server/src/service.lua b/server/src/service.lua
index 62131446..f7c81317 100644
--- a/server/src/service.lua
+++ b/server/src/service.lua
@@ -41,8 +41,10 @@ function mt:_callMethod(name, params)
if suc then
return res
else
+ local suc, res = pcall(table.dump, params)
+ local dump = suc and res or 'Cyclic table'
log.debug(('Task [%s] failed, params: %s'):format(
- name, table.dump(params)
+ name, dump
))
return nil, {
code = ErrorCodes.InternalError,
diff --git a/server/test/completion/init.lua b/server/test/completion/init.lua
index 684a8fe7..da633a86 100644
--- a/server/test/completion/init.lua
+++ b/server/test/completion/init.lua
@@ -2,31 +2,31 @@ local matcher = require 'matcher'
local parser = require 'parser'
local CompletionItemKind = {
- Text = 1,
- Method = 2,
- Function = 3,
- Constructor = 4,
- Field = 5,
- Variable = 6,
- Class = 7,
- Interface = 8,
- Module = 9,
- Property = 10,
- Unit = 11,
- Value = 12,
- Enum = 13,
- Keyword = 14,
- Snippet = 15,
- Color = 16,
- File = 17,
- Reference = 18,
- Folder = 19,
- EnumMember = 20,
- Constant = 21,
- Struct = 22,
- Event = 23,
- Operator = 24,
- TypeParameter = 25,
+ Text = 1,
+ Method = 2,
+ Function = 3,
+ Constructor = 4,
+ Field = 5,
+ Variable = 6,
+ Class = 7,
+ Interface = 8,
+ Module = 9,
+ Property = 10,
+ Unit = 11,
+ Value = 12,
+ Enum = 13,
+ Keyword = 14,
+ Snippet = 15,
+ Color = 16,
+ File = 17,
+ Reference = 18,
+ Folder = 19,
+ EnumMember = 20,
+ Constant = 21,
+ Struct = 22,
+ Event = 23,
+ Operator = 24,
+ TypeParameter = 25,
}
local function eq(a, b)
@@ -79,7 +79,25 @@ a@
}
TEST [[
+local abcdefg
local abcde
-abcde
+abcde@
]]
-{}
+{
+ {
+ label = 'abcdefg',
+ kind = CompletionItemKind.Variable,
+ }
+}
+
+TEST [[
+local abcdefg
+a@
+local abcde
+]]
+{
+ {
+ label = 'abcdefg',
+ kind = CompletionItemKind.Variable,
+ }
+}