diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-12-09 20:28:18 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-12-09 20:28:18 +0800 |
commit | d803249a1aedafad9b08349ed16c941bf4c3ba4e (patch) | |
tree | e25c274c1c1f16eddefa3ca572202f7536c6b7d8 | |
parent | 9e193c1d17d64137191c5aa9e4f39c18a795396f (diff) | |
download | lua-language-server-d803249a1aedafad9b08349ed16c941bf4c3ba4e.zip |
自动完成搜索局部变量
-rw-r--r-- | script-beta/core/completion.lua | 51 | ||||
-rw-r--r-- | script-beta/core/matchkey.lua | 30 | ||||
-rw-r--r-- | script-beta/parser/guide.lua | 33 | ||||
-rw-r--r-- | test-beta.lua | 2 | ||||
-rw-r--r-- | test-beta/completion/init.lua | 2 |
5 files changed, 116 insertions, 2 deletions
diff --git a/script-beta/core/completion.lua b/script-beta/core/completion.lua index e69de29b..d3a7a022 100644 --- a/script-beta/core/completion.lua +++ b/script-beta/core/completion.lua @@ -0,0 +1,51 @@ +local ckind = require 'define.CompletionItemKind' +local files = require 'files' +local guide = require 'parser.guide' +local matchKey = require 'core.matchKey' + +local function findWord(text, offset) + for i = offset, 1, -1 do + if not text:sub(i, i):match '[%w_]' then + if i == offset then + return nil + end + return text:sub(i+1, offset) + end + end + return nil +end + +local function checkLocal(ast, word, offset, results) + guide.getVisibleLocalNames(ast.ast, offset, function (name) + if matchKey(word, name) then + results[#results+1] = { + label = name, + kind = ckind.Variable, + } + end + end) +end + +local function tryWord(ast, text, offset, results) + local word = findWord(text, offset) + if not word then + return nil + end + checkLocal(ast, word, offset, results) +end + +return function (uri, offset) + local ast = files.getAst(uri) + if not ast then + return nil + end + local text = files.getText(uri) + local results = {} + + tryWord(ast, text, offset, results) + + if #results == 0 then + return nil + end + return results +end diff --git a/script-beta/core/matchkey.lua b/script-beta/core/matchkey.lua new file mode 100644 index 00000000..b46250cb --- /dev/null +++ b/script-beta/core/matchkey.lua @@ -0,0 +1,30 @@ +return function (me, other) + if me == other then + return true + end + if me == '' then + return true + end + if #me > #other then + return false + end + local lMe = me:lower() + local lOther = other:lower() + if lMe == lOther:sub(1, #lMe) then + return true + end + local chars = {} + for i = 1, #lOther do + local c = lOther:sub(i, i) + chars[c] = (chars[c] or 0) + 1 + end + for i = 1, #lMe do + local c = lMe:sub(i, i) + if chars[c] and chars[c] > 0 then + chars[c] = chars[c] - 1 + else + return false + end + end + return true +end diff --git a/script-beta/parser/guide.lua b/script-beta/parser/guide.lua index 2e26a3da..4ccfd23d 100644 --- a/script-beta/parser/guide.lua +++ b/script-beta/parser/guide.lua @@ -235,6 +235,39 @@ function m.getLocal(block, name, pos) error('guide.getLocal overstack') end +--- 获取指定区块中所有的可见局部变量名称 +function m.getVisibleLocalNames(block, pos, callback) + block = m.getBlock(block) + local used = {} + for _ = 1, 1000 do + if not block then + return nil + end + local locals = block.locals + local res + if not locals then + goto CONTINUE + end + for i = 1, #locals do + local loc = locals[i] + if loc.effect > pos then + break + end + local name = loc[1] + if not used[name] then + used[name] = true + callback(name) + end + end + if res then + return res, res + end + ::CONTINUE:: + block = m.getParentBlock(block) + end + error('guide.getLocal overstack') +end + --- 获取指定区块中可见的标签 ---@param block table ---@param name string {comment = '标签名'} diff --git a/test-beta.lua b/test-beta.lua index cf9f9ea3..ccd5c681 100644 --- a/test-beta.lua +++ b/test-beta.lua @@ -43,7 +43,7 @@ local function main() test 'rename' test 'type_inference' test 'hover' - --test 'completion' + test 'completion' --test 'signature' --test 'document_symbol' test 'crossfile' diff --git a/test-beta/completion/init.lua b/test-beta/completion/init.lua index 18920704..e834e73a 100644 --- a/test-beta/completion/init.lua +++ b/test-beta/completion/init.lua @@ -35,7 +35,7 @@ rawset(_G, 'TEST', true) function TEST(script) return function (expect) files.removeAll() - local pos = script:find('$', 1, true) + local pos = script:find('$', 1, true) - 1 local new_script = script:gsub('%$', '') files.setText('', new_script) |