summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--script-beta/core/completion.lua251
-rw-r--r--script-beta/core/diagnostics/undefined-global.lua3
-rw-r--r--script-beta/core/hover/arg.lua17
-rw-r--r--script-beta/core/hover/init.lua10
-rw-r--r--script-beta/core/hover/label.lua15
-rw-r--r--script-beta/core/hover/name.lua21
-rw-r--r--script-beta/utility.lua5
-rw-r--r--test-beta/completion/init.lua84
8 files changed, 304 insertions, 102 deletions
diff --git a/script-beta/core/completion.lua b/script-beta/core/completion.lua
index 099060de..9f3239c0 100644
--- a/script-beta/core/completion.lua
+++ b/script-beta/core/completion.lua
@@ -92,59 +92,8 @@ local function findParent(ast, text, offset)
return nil, nil
end
-local function checkLocal(ast, word, offset, results)
- local locals = guide.getVisibleLocals(ast.ast, offset)
- for name, source in pairs(locals) do
- if matchKey(word, name) then
- results[#results+1] = {
- label = name,
- kind = ckind.Variable,
- id = stack(function ()
- return {
- detail = getLabel(source),
- }
- end),
- }
- end
- end
-end
-
-local function isSameSource(source, pos)
- return source.start <= pos and source.finish >= pos
-end
-
-local function checkField(word, start, parent, oop, results)
- local used = {}
- vm.eachField(parent, function (info)
- local key = info.key
- if key
- and key:sub(1, 1) == 's'
- and not isSameSource(info.source, start) then
- local name = key:sub(3)
- if not used[name] and matchKey(word, name) then
- local kind = ckind.Field
- local literal = vm.getLiteral(info.source)
- if literal ~= nil then
- kind = ckind.Enum
- end
- results[#results+1] = {
- label = name,
- kind = kind,
- id = stack(function ()
- return {
- detail = getLabel(info.source),
- description = info.source.description,
- }
- end)
- }
- end
- used[name] = true
- end
- end)
-end
-
local function buildFunctionSnip(source)
- local name = getName(source)
+ local name = getName(source):gsub('^.-[$.:]', '')
local args = getArg(source)
local id = 0
args = args:gsub('[^,]+', function (arg)
@@ -171,6 +120,108 @@ local function buildFunction(results, source, oop, data)
end
end
+local function buildDesc(source)
+ if source.description then
+ return source.description
+ end
+ local lib = vm.getLibrary(source)
+ if lib then
+ return lib.description
+ end
+end
+
+local function checkLocal(ast, word, offset, results)
+ local locals = guide.getVisibleLocals(ast.ast, offset)
+ for name, source in pairs(locals) do
+ if matchKey(word, name) then
+ if vm.hasType(source, 'function') then
+ buildFunction(results, source, false, {
+ label = name,
+ kind = ckind.Function,
+ id = stack(function ()
+ return {
+ detail = getLabel(source),
+ description = buildDesc(source),
+ }
+ end),
+ })
+ else
+ results[#results+1] = {
+ label = name,
+ kind = ckind.Variable,
+ id = stack(function ()
+ return {
+ detail = getLabel(source),
+ description = buildDesc(source),
+ }
+ end),
+ }
+ end
+ end
+ end
+end
+
+local function isSameSource(source, pos)
+ return source.start <= pos and source.finish >= pos
+end
+
+local function checkField(word, start, parent, oop, results)
+ local used = {}
+ vm.eachField(parent, function (info)
+ local key = info.key
+ if not key or key:sub(1, 1) ~= 's' then
+ return
+ end
+ if isSameSource(info.source, start) then
+ return
+ end
+ local name = key:sub(3)
+ if used[name] then
+ return
+ end
+ if not matchKey(word, name) then
+ used[name] = true
+ return
+ end
+ local kind = ckind.Field
+ if vm.hasType(info.source, 'function') then
+ if oop then
+ kind = ckind.Method
+ end
+ used[name] = true
+ buildFunction(results, info.source, oop, {
+ label = name,
+ kind = kind,
+ id = stack(function ()
+ return {
+ detail = getLabel(info.source),
+ description = buildDesc(info.source),
+ }
+ end),
+ })
+ else
+ if oop then
+ return
+ end
+ used[name] = true
+ local literal = vm.getLiteral(info.source)
+ if literal ~= nil then
+ kind = ckind.Enum
+ end
+ results[#results+1] = {
+ label = name,
+ kind = kind,
+ id = stack(function ()
+ return {
+ detail = getLabel(info.source),
+ description = buildDesc(info.source),
+ }
+ end)
+ }
+ end
+ end)
+end
+
local function checkLibrary(word, results)
for name, lib in pairs(library.global) do
if matchKey(word, name) then
@@ -181,7 +232,7 @@ local function checkLibrary(word, results)
id = stack(function ()
return {
detail = getLabel(lib),
- documentation = lib.description,
+ documentation = buildDesc(lib),
}
end),
})
@@ -216,6 +267,99 @@ local function isInString(ast, offset)
end)
end
+local keyWordMap = {
+{'and'},
+{'break'},
+{'do', function (ast, text, start, results)
+ if config.config.completion.keywordSnippet then
+ guide.eachSourceContain()
+ results[#results+1] = {
+ label = 'do .. end',
+ kind = ckind.Snippet,
+ insertTextFormat = 2,
+ insertText = [[
+do
+ $0
+end]],
+ }
+ end
+end},
+{'else'},
+{'elseif', function (ast, text, start, results)
+ if config.config.completion.keywordSnippet then
+ results[#results+1] = {
+ label = 'elseif .. then',
+ kind = ckind.Snippet,
+ insertTextFormat = 2,
+ insertText = [[elseif $1 then]],
+ }
+ end
+end},
+{'end'},
+{'false'},
+{'for', function (ast, text, start, results)
+ if config.config.completion.keywordSnippet then
+ results[#results+1] = {
+ label = 'for .. in',
+ kind = ckind.Snippet,
+ insertTextFormat = 2,
+ insertText = [[
+for ${1:key, value} in ${2:pairs(t)} do
+ $0
+end]]
+ }
+ results[#results+1] = {
+ label = 'for i = ..',
+ kind = ckind.Snippet,
+ insertTextFormat = 2,
+ insertText = [[
+for ${1:i} = ${2:1}, ${3:10, 2} do
+ $0
+end]]
+ }
+ end
+end},
+{'function', function (ast, text, start, results)
+
+end},
+{'goto'},
+{'if'},
+{'in'},
+{'local', function (ast, text, start, results)
+ if config.config.completion.keywordSnippet then
+ results[#results+1] = {
+ label = 'local function',
+ kind = ckind.Snippet,
+ }
+ end
+end},
+{'nil'},
+{'not'},
+{'or'},
+{'repeat'},
+{'return'},
+{'then'},
+{'true'},
+{'until'},
+{'while'},
+}
+
+local function checkKeyWord(ast, text, start, word, results)
+ for _, data in ipairs(keyWordMap) do
+ local key = data[1]
+ if matchKey(word, key) then
+ results[#results+1] = {
+ label = key,
+ kind = ckind.Keyword,
+ }
+ local func = data[2]
+ if func then
+ func(ast, text, start, results)
+ end
+ end
+ end
+end
+
local function tryWord(ast, text, offset, results)
local word = findWord(text, offset)
if not word then
@@ -231,6 +375,7 @@ local function tryWord(ast, text, offset, results)
local env = guide.getLocal(ast.ast, '_ENV', start)
checkField(word, start, env, false, results)
checkLibrary(word, results)
+ checkKeyWord(ast, text, start, word, results)
end
end
checkCommon(word, text, results)
diff --git a/script-beta/core/diagnostics/undefined-global.lua b/script-beta/core/diagnostics/undefined-global.lua
index ed81ced3..ffb64582 100644
--- a/script-beta/core/diagnostics/undefined-global.lua
+++ b/script-beta/core/diagnostics/undefined-global.lua
@@ -14,6 +14,9 @@ return function (uri, callback)
-- 遍历全局变量,检查所有没有 mode['set'] 的全局变量
local globals = vm.getGlobals(ast.ast)
+ if not globals then
+ return
+ end
for key, infos in pairs(globals) do
if infos.mode['set'] == true then
goto CONTINUE
diff --git a/script-beta/core/hover/arg.lua b/script-beta/core/hover/arg.lua
index 9d557e3b..dc8db16c 100644
--- a/script-beta/core/hover/arg.lua
+++ b/script-beta/core/hover/arg.lua
@@ -1,7 +1,7 @@
local guide = require 'parser.guide'
local vm = require 'vm'
-local function asFunction(source, caller)
+local function asFunction(source, oop)
if not source.args then
return ''
end
@@ -15,28 +15,21 @@ local function asFunction(source, caller)
args[i] = ('%s'):format(vm.getType(arg))
end
end
- local methodDef, methodCall
+ local methodDef
local parent = source.parent
if parent and parent.type == 'setmethod' then
methodDef = true
end
- if caller then
- if caller.type == 'method'
- or caller.type == 'getmethod'
- or caller.type == 'setmethod' then
- methodCall = true
- end
- end
- if not methodDef and methodCall then
+ if not methodDef and oop then
return table.concat(args, ', ', 2)
else
return table.concat(args, ', ')
end
end
-return function (source, caller)
+return function (source, oop)
if source.type == 'function' then
- return asFunction(source, caller)
+ return asFunction(source, oop)
end
return ''
end
diff --git a/script-beta/core/hover/init.lua b/script-beta/core/hover/init.lua
index 63129c3e..47d4c5a6 100644
--- a/script-beta/core/hover/init.lua
+++ b/script-beta/core/hover/init.lua
@@ -11,9 +11,12 @@ local function getHoverAsFunction(source)
local defs = 0
local protos = 0
local other = 0
+ local oop = source.type == 'method'
+ or source.type == 'getmethod'
+ or source.type == 'setmethod'
for _, value in ipairs(values) do
if value.type == 'function' then
- local label = getLabel(value.source, source)
+ local label = getLabel(value.source, oop)
defs = defs + 1
labels[label] = (labels[label] or 0) + 1
if labels[label] == 1 then
@@ -54,7 +57,10 @@ local function getHoverAsFunction(source)
end
local function getHoverAsValue(source)
- local label = getLabel(source, source)
+ local oop = source.type == 'method'
+ or source.type == 'getmethod'
+ or source.type == 'setmethod'
+ local label = getLabel(source, oop)
local desc = getDesc(source)
return {
label = label,
diff --git a/script-beta/core/hover/label.lua b/script-beta/core/hover/label.lua
index dd25d42e..21330b17 100644
--- a/script-beta/core/hover/label.lua
+++ b/script-beta/core/hover/label.lua
@@ -6,9 +6,9 @@ local getClass = require 'core.hover.class'
local vm = require 'vm'
local util = require 'utility'
-local function asFunction(source, caller)
- local name = buildName(source, caller)
- local arg = buildArg(source, caller)
+local function asFunction(source, oop)
+ local name = buildName(source, oop)
+ local arg = buildArg(source, oop)
local rtn = buildReturn(source)
local lines = {}
lines[1] = ('function %s(%s)'):format(name, arg)
@@ -28,7 +28,10 @@ local function asValue(source, title)
type = nil
end
if lib then
- name = ('%s<%s>'):format(name, buildName(lib))
+ local libName = buildName(lib)
+ if name ~= libName then
+ name = ('%s<%s>'):format(name, buildName(lib))
+ end
end
local pack = {}
pack[#pack+1] = title
@@ -108,9 +111,9 @@ local function asString(source)
end
end
-return function (source, caller)
+return function (source, oop)
if source.type == 'function' then
- return asFunction(source, caller)
+ return asFunction(source, oop)
elseif source.type == 'local'
or source.type == 'getlocal'
or source.type == 'setlocal' then
diff --git a/script-beta/core/hover/name.lua b/script-beta/core/hover/name.lua
index 917bf96d..ea1906ed 100644
--- a/script-beta/core/hover/name.lua
+++ b/script-beta/core/hover/name.lua
@@ -5,14 +5,14 @@ local function asLocal(source)
return guide.getName(source)
end
-local function asMethod(source, caller)
+local function asMethod(source)
local class = getClass(source.node)
local node = class or guide.getName(source.node) or '?'
local method = guide.getName(source)
return ('%s:%s'):format(node, method)
end
-local function asField(source, caller)
+local function asField(source)
local class = getClass(source.node)
local node = class or guide.getName(source.node) or '?'
local method = guide.getName(source)
@@ -27,12 +27,9 @@ local function asGlobal(source)
return guide.getName(source)
end
-local function asLibrary(source, caller)
+local function asLibrary(source, oop)
local p
- if caller
- and (caller.type == 'method'
- or caller.type == 'getmethod'
- or caller.type == 'setmethod') then
+ if oop then
if source.parent then
for _, parent in ipairs(source.parent) do
if parent.type == 'object' then
@@ -58,9 +55,9 @@ local function asLibrary(source, caller)
end
end
-local function buildName(source, caller)
+local function buildName(source, oop)
if source.library then
- return asLibrary(source, caller) or ''
+ return asLibrary(source, oop) or ''
end
if source.type == 'local'
or source.type == 'getlocal'
@@ -73,18 +70,18 @@ local function buildName(source, caller)
end
if source.type == 'setmethod'
or source.type == 'getmethod' then
- return asMethod(source, caller) or ''
+ return asMethod(source) or ''
end
if source.type == 'setfield'
or source.type == 'getfield' then
- return asField(source, caller) or ''
+ return asField(source) or ''
end
if source.type == 'tablefield' then
return asTableField(source) or ''
end
local parent = source.parent
if parent then
- return buildName(parent, caller)
+ return buildName(parent, oop)
end
return ''
end
diff --git a/script-beta/utility.lua b/script-beta/utility.lua
index 9eaeb955..dfc7f510 100644
--- a/script-beta/utility.lua
+++ b/script-beta/utility.lua
@@ -420,9 +420,6 @@ function m.viewString(str, quo)
end)
return quo .. str:gsub([=[["\r\n]]=], esc) .. quo
else
- if str:find '\r' then
- return m.viewString(str)
- end
local eqnum = #quo - 2
local fsymb = ']' .. ('='):rep(eqnum) .. ']'
if not str:find(fsymb, 1, true) then
@@ -437,7 +434,7 @@ function m.viewString(str, quo)
return ssymb .. str .. fsymb
end
end
- return m.viewString(str)
+ return m.viewString(str, '"')
end
end
diff --git a/test-beta/completion/init.lua b/test-beta/completion/init.lua
index bebe481b..5736d9b0 100644
--- a/test-beta/completion/init.lua
+++ b/test-beta/completion/init.lua
@@ -132,12 +132,28 @@ ass$
{
{
label = 'assert',
- kind = CompletionItemKind.Function,
+ kind = CompletionItemKind.Function,
},
{
label = 'assert()',
- kind = CompletionItemKind.Snippet,
+ kind = CompletionItemKind.Snippet,
+ },
+}
+
+TEST [[
+local function ffff(a, b)
+end
+ff$
+]]
+{
+ {
+ label = 'ffff',
+ kind = CompletionItemKind.Function,
},
+ {
+ label = 'ffff()',
+ kind = CompletionItemKind.Snippet,
+ }
}
TEST [[
@@ -177,6 +193,7 @@ t.ab$
TEST [[
local mt = {}
+mt.ggg = 1
function mt:get(a, b)
return 1
end
@@ -186,16 +203,15 @@ mt:g$
{
label = 'get',
kind = CompletionItemKind.Method,
- documentation = EXISTS,
- detail = EXISTS,
},
{
label = 'get()',
kind = CompletionItemKind.Snippet,
- documentation = EXISTS,
- insertText = EXISTS,
- detail = EXISTS,
},
+ {
+ label = 'ggg',
+ kind = CompletionItemKind.Text,
+ }
}
TEST [[
@@ -205,15 +221,10 @@ loc$
{
label = 'collectgarbage',
kind = CompletionItemKind.Function,
- documentation = EXISTS,
- detail = EXISTS,
},
{
label = 'collectgarbage()',
kind = CompletionItemKind.Snippet,
- documentation = EXISTS,
- detail = EXISTS,
- insertText = EXISTS,
},
{
label = 'local',
@@ -222,11 +233,58 @@ loc$
{
label = 'local function',
kind = CompletionItemKind.Snippet,
- insertText = EXISTS,
}
}
TEST [[
+do$
+]]
+{
+ {
+ label = 'dofile',
+ kind = CompletionItemKind.Function,
+ },
+ {
+ label = 'dofile()',
+ kind = CompletionItemKind.Snippet,
+ },
+ {
+ label = 'load',
+ kind = CompletionItemKind.Function,
+ },
+ {
+ label = 'load()',
+ kind = CompletionItemKind.Snippet,
+ },
+ {
+ label = 'loadfile',
+ kind = CompletionItemKind.Function,
+ },
+ {
+ label = 'loadfile()',
+ kind = CompletionItemKind.Snippet,
+ },
+ {
+ label = 'do',
+ kind = CompletionItemKind.Keyword,
+ },
+ {
+ label = 'do .. end',
+ kind = CompletionItemKind.Snippet,
+ }
+}
+
+TEST [[
+while true d$
+]]
+{
+ {
+ label = 'do',
+ kind = CompletionItemKind.Keyword,
+ },
+}
+
+TEST [[
t.a = {}
t.b = {}
t.$