summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-05-08 16:20:30 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-05-08 16:20:30 +0800
commitb5dd953912738cac05d8292eb080c6860f18d418 (patch)
treeeba01883c6989f7b3c814cfba755246d22869431
parent5e0c1dfa6beaf4431d7fae3e392aab7e7da34213 (diff)
parentf3bf7d8fcf18f8fb5b07e17236356012732ee46a (diff)
downloadlua-language-server-b5dd953912738cac05d8292eb080c6860f18d418.zip
Merge remote-tracking branch 'origin/master' into 2.0.0
m---------3rd/bee.lua0
m---------3rd/luamake0
-rw-r--r--changelog.md41
-rw-r--r--locale/en-us/script.lua2
-rw-r--r--locale/zh-cn/script.lua2
-rw-r--r--make.lua2
-rw-r--r--script/config.lua3
-rw-r--r--script/core/completion.lua105
-rw-r--r--script/core/folding.lua4
-rw-r--r--script/core/guide2.lua13
-rw-r--r--script/core/highlight.lua91
-rw-r--r--script/core/hover/description.lua8
-rw-r--r--script/parser/ast.lua85
-rw-r--r--script/parser/grammar.lua49
-rw-r--r--script/parser/luadoc.lua18
-rw-r--r--script/provider/provider.lua2
-rw-r--r--script/utility.lua37
-rw-r--r--test/completion/init.lua202
-rw-r--r--test/crossfile/hover.lua30
-rw-r--r--test/diagnostics/init.lua8
-rw-r--r--test/document_symbol/init.lua32
21 files changed, 470 insertions, 264 deletions
diff --git a/3rd/bee.lua b/3rd/bee.lua
-Subproject 3e2bf12fe97c0b337694dbb24ef8fb5c0f48252
+Subproject 28a9af609cbc1c6b787e28a5a946a96164103f2
diff --git a/3rd/luamake b/3rd/luamake
-Subproject 4979b37ede5eb7a0d28d70377855374c5d45427
+Subproject 36a40b9a9cb044564bca7cef7d2cf244b22d781
diff --git a/changelog.md b/changelog.md
index b3281ef9..6dc280f2 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,21 +1,40 @@
# changelog
+## 1.21.1
+`2021-5-8`
+* `FIX` [#529](https://github.com/sumneko/lua-language-server/issues/529)
+
+## 1.21.0
+`2021-5-7`
+* `NEW` setting: `completion.showParams`
+* `NEW` `LuaDoc`: supports multiline comments
+* `NEW` `LuaDoc`: tail comments support lua string
+
+## 1.20.5
+`2021-4-30`
+* `NEW` setting: `completion.autoRequire`
+* `NEW` setting: `hover.enumsLimit`
+* `CHG` folding: supports `-- #region`
+* `FIX` completion: details may be suspended
+* `FIX` [#522](https://github.com/sumneko/lua-language-server/issues/522)
+* `FIX` [#523](https://github.com/sumneko/lua-language-server/issues/523)
+
## 1.20.4
`2021-4-13`
-`NEW` diagnostic: `deprecated`
-`FIX` [#464](https://github.com/sumneko/lua-language-server/issues/464)
-`FIX` [#497](https://github.com/sumneko/lua-language-server/issues/497)
-`FIX` [#502](https://github.com/sumneko/lua-language-server/issues/502)
+* `NEW` diagnostic: `deprecated`
+* `FIX` [#464](https://github.com/sumneko/lua-language-server/issues/464)
+* `FIX` [#497](https://github.com/sumneko/lua-language-server/issues/497)
+* `FIX` [#502](https://github.com/sumneko/lua-language-server/issues/502)
## 1.20.3
`2021-4-6`
-`FIX` [#479](https://github.com/sumneko/lua-language-server/issues/479)
-`FIX` [#483](https://github.com/sumneko/lua-language-server/issues/483)
-`FIX` [#485](https://github.com/sumneko/lua-language-server/issues/485)
-`FIX` [#487](https://github.com/sumneko/lua-language-server/issues/487)
-`FIX` [#488](https://github.com/sumneko/lua-language-server/issues/488)
-`FIX` [#490](https://github.com/sumneko/lua-language-server/issues/490)
-`FIX` [#495](https://github.com/sumneko/lua-language-server/issues/495)
+* `FIX` [#479](https://github.com/sumneko/lua-language-server/issues/479)
+* `FIX` [#483](https://github.com/sumneko/lua-language-server/issues/483)
+* `FIX` [#485](https://github.com/sumneko/lua-language-server/issues/485)
+* `FIX` [#487](https://github.com/sumneko/lua-language-server/issues/487)
+* `FIX` [#488](https://github.com/sumneko/lua-language-server/issues/488)
+* `FIX` [#490](https://github.com/sumneko/lua-language-server/issues/490)
+* `FIX` [#495](https://github.com/sumneko/lua-language-server/issues/495)
## 1.20.2
`2021-4-2`
diff --git a/locale/en-us/script.lua b/locale/en-us/script.lua
index 9fbcb72e..69f97bb1 100644
--- a/locale/en-us/script.lua
+++ b/locale/en-us/script.lua
@@ -94,6 +94,7 @@ PARSER_UNEXPECT_SYMBOL = 'Unexpected symbol `{symbol}` .'
PARSER_UNKNOWN_TAG = 'Unknown attribute.'
PARSER_MULTI_TAG = 'Dose not support multi attributes.'
PARSER_UNEXPECT_LFUNC_NAME = 'Local function can only use identifiers as name.'
+PARSER_UNEXPECT_EFUNC_NAME = 'Function as expression cannot be named.'
PARSER_ERR_LCOMMENT_END = 'Multi-line annotations should be closed by `{symbol}` .'
PARSER_ERR_C_LONG_COMMENT = 'Lua should use `--[[ ]]` for multi-line annotations.'
PARSER_ERR_LSTRING_END = 'Long string should be closed by `{symbol}` .'
@@ -153,6 +154,7 @@ HOVER_STRING_BYTES = '{} bytes'
HOVER_STRING_CHARACTERS = '{} bytes, {} characters'
HOVER_MULTI_DEF_PROTO = '({} definitions, {} prototypes)'
HOVER_MULTI_PROTO_NOT_FUNC = '({} non functional definition)'
+HOVER_MORE_ENUMS = '|...(+{})'
HOVER_USE_LUA_PATH = '(Search path: `{}`)'
HOVER_EXTENDS = 'Expand to {}'
diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua
index ab369a8e..e949ad31 100644
--- a/locale/zh-cn/script.lua
+++ b/locale/zh-cn/script.lua
@@ -94,6 +94,7 @@ PARSER_UNEXPECT_SYMBOL = '未知的符号 `{symbol}` 。'
PARSER_UNKNOWN_TAG = '不支持的属性。'
PARSER_MULTI_TAG = '只能设置一个属性。'
PARSER_UNEXPECT_LFUNC_NAME = '局部函数只能使用标识符作为名称。'
+PARSER_UNEXPECT_EFUNC_NAME = '函数作为表达式时不能命名。'
PARSER_ERR_LCOMMENT_END = '应使用`{symbol}`来关闭多行注释。'
PARSER_ERR_C_LONG_COMMENT = 'Lua应使用`--[[ ]]`来进行多行注释。'
PARSER_ERR_LSTRING_END = '应使用`{symbol}`来关闭长字符串。'
@@ -152,6 +153,7 @@ HOVER_STRING_BYTES = '{} 个字节'
HOVER_STRING_CHARACTERS = '{} 个字节,{} 个字符'
HOVER_MULTI_DEF_PROTO = '({} 个定义,{} 个原型)'
HOVER_MULTI_PROTO_NOT_FUNC = '({} 个非函数定义)'
+HOVER_MORE_ENUMS = '|...(+{})'
HOVER_USE_LUA_PATH = '(搜索路径: `{}`)'
HOVER_EXTENDS = '展开为 {}'
diff --git a/make.lua b/make.lua
index f1268d8a..6fd709f7 100644
--- a/make.lua
+++ b/make.lua
@@ -1,7 +1,5 @@
local lm = require 'luamake'
-lm.target = 'x64'
-
if lm.plat == "macos" then
lm.flags = {
"-mmacosx-version-min=10.13",
diff --git a/script/config.lua b/script/config.lua
index 7991e1ad..97df7c17 100644
--- a/script/config.lua
+++ b/script/config.lua
@@ -164,6 +164,8 @@ local ConfigTemplate = {
keywordSnippet = {'Replace', String},
displayContext = {6, Integer},
workspaceWord = {true, Boolean},
+ autoRequire = {true, Boolean},
+ showParams = {true, Boolean},
},
signatureHelp = {
enable = {true, Boolean},
@@ -175,6 +177,7 @@ local ConfigTemplate = {
viewNumber = {true, Boolean},
fieldInfer = {3000, Integer},
previewFields = {100, Integer},
+ enumsLimit = {5, Integer},
},
color = {
mode = {'Semantic', String},
diff --git a/script/core/completion.lua b/script/core/completion.lua
index 3ed2b070..0a5f688e 100644
--- a/script/core/completion.lua
+++ b/script/core/completion.lua
@@ -48,9 +48,7 @@ local function resolveStack(id)
return nil
end
- -- 当进行新的 resolve 时,放弃当前的 resolve
- await.close('completion.resolve')
- return await.await(callback, 'completion.resolve')
+ return callback()
end
local function trim(str)
@@ -123,17 +121,9 @@ local function findParentInStringIndex(ast, text, offset)
return parent.node, false
end
-local function buildFunctionSnip(source, oop)
+local function buildFunctionSnip(source, value, oop)
local name = getName(source):gsub('^.+[$.:]', '')
- local defs = vm.getDefs(source, 0)
- local args = ''
- for _, def in ipairs(defs) do
- local defArgs = getArg(def, oop)
- if defArgs ~= '' then
- args = defArgs
- break
- end
- end
+ local args = getArg(value, oop)
local id = 0
args = args:gsub('[^,]+', function (arg)
id = id + 1
@@ -193,7 +183,7 @@ local function buildDesc(source)
return md:string()
end
-local function buildFunction(results, source, oop, data)
+local function buildFunction(results, source, value, oop, data)
local snipType = config.config.completion.callSnippet
if snipType == 'Disable' or snipType == 'Both' then
results[#results+1] = data
@@ -201,8 +191,7 @@ local function buildFunction(results, source, oop, data)
if snipType == 'Both' or snipType == 'Replace' then
local snipData = util.deepCopy(data)
snipData.kind = define.CompletionItemKind.Snippet
- snipData.label = snipData.label .. '()'
- snipData.insertText = buildFunctionSnip(source, oop)
+ snipData.insertText = buildFunctionSnip(source, value, oop)
snipData.insertTextFormat = 2
snipData.id = stack(function ()
return {
@@ -255,6 +244,26 @@ local function isSameSource(ast, source, pos)
return source.start <= pos and source.finish >= pos
end
+local function getParams(func, oop)
+ if not func.args then
+ return '()'
+ end
+ local args = {}
+ for _, arg in ipairs(func.args) do
+ if arg.type == '...' then
+ args[#args+1] = '...'
+ elseif arg.type == 'doc.type.arg' then
+ args[#args+1] = arg.name[1]
+ else
+ args[#args+1] = arg[1]
+ end
+ end
+ if oop and args[1] ~= '...' then
+ table.remove(args, 1)
+ end
+ return '(' .. table.concat(args, ', ') .. ')'
+end
+
local function checkLocal(ast, word, offset, results)
local locals = searcher.getVisibleLocals(ast.ast, offset)
for name, source in pairs(locals) do
@@ -265,16 +274,23 @@ local function checkLocal(ast, word, offset, results)
goto CONTINUE
end
if vm.hasType(source, 'function') then
- buildFunction(results, source, false, {
- label = name,
- kind = define.CompletionItemKind.Function,
- id = stack(function ()
- return {
- detail = buildDetail(source),
- description = buildDesc(source),
- }
- end),
- })
+ for _, def in ipairs(vm.getDefs(source, 0)) do
+ if def.type == 'function'
+ or def.type == 'doc.type.function' then
+ local funcLabel = name .. getParams(def, false)
+ buildFunction(results, source, def, false, {
+ label = funcLabel,
+ insertText = name,
+ kind = define.CompletionItemKind.Function,
+ id = stack(function ()
+ return {
+ detail = buildDetail(source),
+ description = buildDesc(source),
+ }
+ end),
+ })
+ end
+ end
else
results[#results+1] = {
label = name,
@@ -292,6 +308,9 @@ local function checkLocal(ast, word, offset, results)
end
local function checkModule(ast, word, offset, results)
+ if not config.config.completion.autoRequire then
+ return
+ end
local locals = searcher.getVisibleLocals(ast.ast, offset)
for uri in files.eachFile() do
if files.eq(uri, searcher.getUri(ast.ast)) then
@@ -400,15 +419,17 @@ end
local function checkFieldThen(name, src, word, start, offset, parent, oop, results)
local value = searcher.getObjectValue(src) or src
local kind = define.CompletionItemKind.Field
- if value.type == 'function' then
+ if value.type == 'function'
+ or value.type == 'doc.type.function' then
if oop then
kind = define.CompletionItemKind.Method
else
kind = define.CompletionItemKind.Function
end
- buildFunction(results, src, oop, {
+ buildFunction(results, src, value, oop, {
label = name,
kind = kind,
+ insertText = name:match '^[^(]+',
deprecated = vm.isDeprecated(src) or nil,
id = stack(function ()
return {
@@ -469,8 +490,28 @@ local function checkFieldOfRefs(refs, ast, word, start, offset, parent, oop, res
if not matchKey(word, name, count >= 100) then
goto CONTINUE
end
+ local funcLabel
+ if config.config.completion.showParams then
+ local value = guide.getObjectValue(src) or src
+ if value.type == 'function'
+ or value.type == 'doc.type.function' then
+ funcLabel = name .. getParams(value, oop)
+ fields[funcLabel] = src
+ fields[name] = false
+ count = count + 1
+ if value.type == 'function' and value.bindDocs then
+ for _, doc in ipairs(value.bindDocs) do
+ if doc.type == 'doc.overload' then
+ funcLabel = name .. getParams(doc.overload, oop)
+ fields[funcLabel] = doc.overload
+ end
+ end
+ end
+ goto CONTINUE
+ end
+ end
local last = fields[name]
- if not last then
+ if last == nil then
fields[name] = src
count = count + 1
goto CONTINUE
@@ -490,7 +531,9 @@ local function checkFieldOfRefs(refs, ast, word, start, offset, parent, oop, res
::CONTINUE::
end
for name, src in util.sortPairs(fields) do
- checkFieldThen(name, src, word, start, offset, parent, oop, results)
+ if src then
+ checkFieldThen(name, src, word, start, offset, parent, oop, results)
+ end
end
end
@@ -543,7 +586,7 @@ local function checkCommon(myUri, word, text, offset, results)
results.enableCommon = true
local used = {}
for _, result in ipairs(results) do
- used[result.label] = true
+ used[result.label:match '^[^(]*'] = true
end
for _, data in ipairs(keyWordMap) do
used[data[1]] = true
diff --git a/script/core/folding.lua b/script/core/folding.lua
index d089b816..1bbae944 100644
--- a/script/core/folding.lua
+++ b/script/core/folding.lua
@@ -1,5 +1,6 @@
-local files = require "files"
+local files = require "files"
local searcher = require "core.searcher"
+local util = require 'utility'
local Care = {
['function'] = function (source, text, results)
@@ -92,6 +93,7 @@ local Care = {
end,
['comment.short'] = function (source, text, results, status)
local ltext = source.text:lower()
+ ltext = util.trim(ltext, 'left')
if ltext:sub(1, #'region') == 'region'
or ltext:sub(1, #'#region') == '#region' then
if not status.regions then
diff --git a/script/core/guide2.lua b/script/core/guide2.lua
index 64192297..576c0c20 100644
--- a/script/core/guide2.lua
+++ b/script/core/guide2.lua
@@ -1,4 +1,6 @@
local util = require 'utility'
+local config = require 'config'
+local lang = require 'language'
local error = error
local type = type
local next = next
@@ -1845,6 +1847,8 @@ function m.checkSameSimpleByBindDocs(status, obj, start, pushQueue, mode)
if obj.type == '...' then
results[#results+1] = doc
end
+ elseif doc.type == 'doc.overload' then
+ results[#results+1] = doc.overload
end
end
for _, res in ipairs(results) do
@@ -3401,7 +3405,14 @@ function m.mergeTypes(types)
end
end)
- return tableConcat(results, '|')
+ local enumsLimit = config.config.hover.enumsLimit
+ if #results > enumsLimit then
+ return tableConcat(results, '|', 1, enumsLimit)
+ .. lang.script('HOVER_MORE_ENUMS', #results - enumsLimit)
+ else
+ return tableConcat(results, '|')
+ end
+
end
function m.getClassExtends(class)
diff --git a/script/core/highlight.lua b/script/core/highlight.lua
index 75adcb1f..b070c77e 100644
--- a/script/core/highlight.lua
+++ b/script/core/highlight.lua
@@ -3,6 +3,7 @@ local files = require 'files'
local vm = require 'vm'
local define = require 'proto.define'
local findSource = require 'core.find-source'
+local util = require 'utility'
local function eachRef(source, callback)
local results = searcher.requestReference(source)
@@ -138,6 +139,88 @@ local function findKeyWord(ast, text, offset, callback)
end)
end
+local function isRegion(str)
+ if str:sub(1, #'region') == 'region'
+ or str:sub(1, #'#region') == '#region' then
+ return true
+ end
+ return false
+end
+
+local function isEndRegion(str)
+ if str:sub(1, #'endregion') == 'endregion'
+ or str:sub(1, #'#endregion') == '#endregion' then
+ return true
+ end
+ return false
+end
+
+local function checkRegion(ast, text, offset, callback)
+ local count
+ local start, finish
+ local selected
+ for i, comment in ipairs(ast.comms) do
+ if comment.type == 'comment.short' then
+ if comment.start <= offset
+ and comment.finish >= offset then
+ local ltext = comment.text:lower()
+ ltext = util.trim(ltext, 'left')
+ if isRegion(ltext) then
+ start = comment.start - 2
+ count = 1
+ selected = i
+ elseif isEndRegion(ltext) then
+ finish = comment.finish
+ count = 1
+ selected = i
+ else
+ return
+ end
+ break
+ end
+ end
+ end
+ if not selected then
+ return
+ end
+ if start then
+ for i = selected + 1, #ast.comms do
+ local comment = ast.comms[i]
+ if comment.type == 'comment.short' then
+ local ltext = comment.text:lower()
+ ltext = util.trim(ltext, 'left')
+ if isRegion(ltext) then
+ count = count + 1
+ elseif isEndRegion(ltext) then
+ count = count - 1
+ if count == 0 then
+ callback(start, comment.finish)
+ return
+ end
+ end
+ end
+ end
+ end
+ if finish then
+ for i = selected - 1, 1, -1 do
+ local comment = ast.comms[i]
+ if comment.type == 'comment.short' then
+ local ltext = comment.text:lower()
+ ltext = util.trim(ltext, 'left')
+ if isEndRegion(ltext) then
+ count = count + 1
+ elseif isRegion(ltext) then
+ count = count - 1
+ if count == 0 then
+ callback(comment.start - 2, finish)
+ return
+ end
+ end
+ end
+ end
+ end
+end
+
local accept = {
['label'] = true,
['goto'] = true,
@@ -255,6 +338,14 @@ return function (uri, offset)
}
end)
+ checkRegion(ast, text, offset, function (start, finish)
+ results[#results+1] = {
+ start = start,
+ finish = finish,
+ kind = define.DocumentHighlightKind.Text
+ }
+ end)
+
if #results == 0 then
return nil
end
diff --git a/script/core/hover/description.lua b/script/core/hover/description.lua
index 33cae0a6..85224c66 100644
--- a/script/core/hover/description.lua
+++ b/script/core/hover/description.lua
@@ -170,7 +170,7 @@ local function buildEnumChunk(docType, name)
or (enum.additional and '+>')
or ' |',
enum[1],
- enum.comment and (' -- %s'):format(enum.comment:gsub('[\r\n]+', ' ')) or ''
+ enum.comment and (' -- %s'):format(enum.comment) or ''
)
end
return table.concat(lines, '\n')
@@ -264,7 +264,7 @@ local function getFunctionComment(source)
comments[#comments+1] = '\n'
comments[#comments+1] = ('@*param* `%s` — %s'):format(
doc.param[1],
- doc.comment.text:gsub('[\r\n]+', ' ')
+ doc.comment.text
)
comments[#comments+1] = '\n'
end
@@ -280,9 +280,9 @@ local function getFunctionComment(source)
end
if doc.comment then
if #name == 0 then
- comments[#comments+1] = ('@*return* — %s'):format(doc.comment.text:gsub('[\r\n]+', ' '))
+ comments[#comments+1] = ('@*return* — %s'):format(doc.comment.text)
else
- comments[#comments+1] = ('@*return* `%s` — %s'):format(table.concat(name, ','), doc.comment.text:gsub('[\r\n]+', ' '))
+ comments[#comments+1] = ('@*return* `%s` — %s'):format(table.concat(name, ','), doc.comment.text)
end
else
if #name == 0 then
diff --git a/script/parser/ast.lua b/script/parser/ast.lua
index 0a188da4..4f27d37d 100644
--- a/script/parser/ast.lua
+++ b/script/parser/ast.lua
@@ -9,7 +9,12 @@ local tableSort = table.sort
_ENV = nil
-local State
+local DefaultState = {
+ lua = '',
+ options = {},
+}
+
+local State = DefaultState
local PushError
local PushDiag
local PushComment
@@ -277,7 +282,7 @@ local Defs = {
type = 'comment.long',
start = start,
finish = finish - 1,
- text = '',
+ text = str,
}
if not close then
local endSymbol = ']' .. ('='):rep(afterEq-beforeEq) .. ']'
@@ -318,7 +323,7 @@ local Defs = {
}
end
end,
- CLongComment = function (start1, finish1, start2, finish2)
+ CLongComment = function (start1, finish1, str, start2, finish2)
if State.options.nonstandardSymbol and State.options.nonstandardSymbol['/**/'] then
else
PushError {
@@ -344,7 +349,7 @@ local Defs = {
type = 'comment.clong',
start = start1,
finish = finish2 - 1,
- text = '',
+ text = str,
}
end,
CCommentPrefix = function (start, finish, commentFinish)
@@ -983,19 +988,7 @@ local Defs = {
finish = start,
}
end,
- Function = function (functionStart, functionFinish, args, actions, endStart, endFinish)
- actions.type = 'function'
- actions.start = functionStart
- actions.finish = endFinish - 1
- actions.args = args
- actions.keyword= {
- functionStart, functionFinish - 1,
- endStart, endFinish - 1,
- }
- checkMissEnd(functionStart)
- return actions
- end,
- NamedFunction = function (functionStart, functionFinish, name, args, actions, endStart, endFinish)
+ Function = function (functionStart, functionFinish, name, args, actions, endStart, endFinish)
actions.type = 'function'
actions.start = functionStart
actions.finish = endFinish - 1
@@ -1006,7 +999,7 @@ local Defs = {
}
checkMissEnd(functionStart)
if not name then
- return
+ return actions
end
if name.type == 'getname' then
name.type = 'setname'
@@ -1030,35 +1023,49 @@ local Defs = {
name.vstart = functionStart
return name
end,
- LocalFunction = function (start, functionStart, functionFinish, name, args, actions, endStart, endFinish)
- actions.type = 'function'
- actions.start = start
- actions.finish = endFinish - 1
- actions.args = args
- actions.keyword= {
- functionStart, functionFinish - 1,
- endStart, endFinish - 1,
- }
- checkMissEnd(start)
-
- if not name then
- return
+ LocalFunction = function (start, name)
+ if name.type == 'function' then
+ PushError {
+ type = 'MISS_NAME',
+ start = name.keyword[2] + 1,
+ finish = name.keyword[2] + 1,
+ }
+ return name
end
-
- if name.type ~= 'getname' then
+ if name.type ~= 'setname' then
PushError {
type = 'UNEXPECT_LFUNC_NAME',
start = name.start,
finish = name.finish,
}
- return
+ return name
end
- local loc = createLocal(name, name.start, actions)
+ local loc = createLocal(name, name.start, name.value)
loc.localfunction = true
- loc.vstart = functionStart
-
- return loc
+ loc.vstart = name.value.start
+ return name
+ end,
+ NamedFunction = function (name)
+ if name.type == 'function' then
+ PushError {
+ type = 'MISS_NAME',
+ start = name.keyword[2] + 1,
+ finish = name.keyword[2] + 1,
+ }
+ end
+ return name
+ end,
+ ExpFunction = function (func)
+ if func.type ~= 'function' then
+ PushError {
+ type = 'UNEXPECT_EFUNC_NAME',
+ start = func.start,
+ finish = func.finish,
+ }
+ return func.value
+ end
+ return func
end,
Table = function (start, tbl, finish)
tbl.type = 'table'
@@ -1923,7 +1930,7 @@ local function init(state)
end
local function close()
- State = nil
+ State = DefaultState
PushError = function (...) end
PushDiag = function (...) end
PushComment = function (...) end
diff --git a/script/parser/grammar.lua b/script/parser/grammar.lua
index 53d174f3..01756c2a 100644
--- a/script/parser/grammar.lua
+++ b/script/parser/grammar.lua
@@ -88,13 +88,13 @@ end
grammar 'Comment' [[
Comment <- LongComment
/ '--' ShortComment
-LongComment <- ({} '--[' {} {:eq: '='* :} {} '['
+LongComment <- ({} '--[' {} {:eq: '='* :} {} '[' %nl?
{(!CommentClose .)*}
((CommentClose / %nil) {}))
-> LongComment
/ (
- {} '/*' {}
- (!'*/' .)*
+ {} '/*' {} %nl?
+ {(!'*/' .)*}
{} '*/' {}
)
-> CLongComment
@@ -319,7 +319,7 @@ ExpUnit <- Nil
/ Number
/ Dots
/ Table
- / Function
+ / ExpFunction
/ Simple
Simple <- {| Prefix (Sp Suffix)* |}
@@ -327,7 +327,7 @@ Simple <- {| Prefix (Sp Suffix)* |}
Prefix <- Sp ({} PL DirtyExp DirtyPR {})
-> Paren
/ Single
-Single <- Name
+Single <- !FUNCTION Name
-> Single
Suffix <- SuffixWithoutCall
/ ({} PL SuffixCall DirtyPR {})
@@ -377,8 +377,21 @@ NewIndex <- Sp ({} Index NeedAssign DirtyExp {})
NewField <- Sp ({} MustName ASSIGN DirtyExp {})
-> NewField
+ExpFunction <- Function
+ -> ExpFunction
Function <- FunctionBody
-> Function
+FunctionBody
+ <- FUNCTION FuncName FuncArgs
+ {| (!END Action)* |}
+ NeedEnd
+ / FUNCTION FuncName FuncArgsMiss
+ {| %nil |}
+ NeedEnd
+FuncName <- !END {| Single (Sp SuffixWithoutCall)* |}
+ -> Simple
+ / %nil
+
FuncArgs <- Sp ({} PL {| FuncArg+ |} DirtyPR {})
-> FuncArgs
/ PL DirtyPR %nil
@@ -386,12 +399,6 @@ FuncArgsMiss<- {} -> MissPL DirtyPR %nil
FuncArg <- DOTS
/ Name
/ COMMA
-FunctionBody<- FUNCTION FuncArgs
- {| (!END Action)* |}
- NeedEnd
- / FUNCTION FuncArgsMiss
- {| %nil |}
- NeedEnd
-- 纯占位,修改了 `relabel.lua` 使重复定义不抛错
Action <- !END .
@@ -515,26 +522,16 @@ LocalNameList
LocalName <- (MustName LocalAttr?)
-> LocalName
+NamedFunction
+ <- Function
+ -> NamedFunction
+
Call <- Simple
-> SimpleCall
LocalFunction
- <- Sp ({} LOCAL FunctionNamedBody)
+ <- Sp ({} LOCAL Function)
-> LocalFunction
-
-NamedFunction
- <- FunctionNamedBody
- -> NamedFunction
-FunctionNamedBody
- <- FUNCTION FuncName FuncArgs
- {| (!END Action)* |}
- NeedEnd
- / FUNCTION FuncName FuncArgsMiss
- {| %nil |}
- NeedEnd
-FuncName <- {| Single (Sp SuffixWithoutCall)* |}
- -> Simple
- / {} -> MissName %nil
]]
grammar 'Lua' [[
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index af5071b3..0edf5371 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -2,6 +2,7 @@ local m = require 'lpeglabel'
local re = require 'parser.relabel'
local lines = require 'parser.lines'
local guide = require 'parser.guide'
+local grammar = require 'parser.grammar'
local TokenTypes, TokenStarts, TokenFinishs, TokenContents
local Ci, Offset, pushError, Ct, NextComment, Lines
@@ -990,16 +991,23 @@ local function convertTokens()
end
local function trimTailComment(text)
+ local comment = text
if text:sub(1, 1) == '@' then
- return text:sub(2)
+ comment = text:sub(2)
end
if text:sub(1, 1) == '#' then
- return text:sub(2)
+ comment = text:sub(2)
end
if text:sub(1, 2) == '--' then
- return text:sub(3)
+ comment = text:sub(3)
end
- return text
+ if comment:find '^%s*[\'"[]' then
+ local result = grammar(nil, comment:gsub('^%s+', ''), 'string')
+ if result then
+ comment = result[1][1]
+ end
+ end
+ return comment
end
local function buildLuaDoc(comment)
@@ -1177,7 +1185,7 @@ local function bindDoc(sources, lns, binded)
end
bindGeneric(binded)
local row = guide.positionOf(lns, lastDoc.finish)
- local cstart, cfinish = guide.lineRange(lns, row)
+ local cstart, cfinish = guide.lineRange(lns, row)
local nstart, nfinish = guide.lineRange(lns, row + 1)
bindDocsBetween(sources, binded, bindSources, cstart, cfinish)
if #bindSources == 0 then
diff --git a/script/provider/provider.lua b/script/provider/provider.lua
index 65993940..a6f4d9cc 100644
--- a/script/provider/provider.lua
+++ b/script/provider/provider.lua
@@ -550,6 +550,8 @@ proto.on('completionItem/resolve', function (item)
if not item.data then
return item
end
+ await.close 'completion.resolve'
+ await.setID 'completion.resolve'
local id = item.data.id
local uri = item.data.uri
--await.setPriority(1000)
diff --git a/script/utility.lua b/script/utility.lua
index a98bef92..04597a39 100644
--- a/script/utility.lua
+++ b/script/utility.lua
@@ -23,6 +23,14 @@ local utf8 = utf8
_ENV = nil
+local function isInteger(n)
+ if mathType then
+ return mathType(n) == 'integer'
+ else
+ return type(n) == 'number' and n % 1 == 0
+ end
+end
+
local function formatNumber(n)
if n == inf
or n == -inf
@@ -30,7 +38,7 @@ local function formatNumber(n)
or n ~= n then -- IEEE 标准中,NAN 不等于自己。但是某些实现中没有遵守这个规则
return ('%q'):format(n)
end
- if mathType(n) == 'integer' then
+ if isInteger(n) then
return tostring(n)
end
local str = ('%.10f'):format(n)
@@ -38,14 +46,6 @@ local function formatNumber(n)
return str
end
-local function isInteger(n)
- if mathType then
- return mathType(n) == 'integer'
- else
- return type(n) == 'number' and n % 1 == 0
- end
-end
-
local TAB = setmetatable({}, { __index = function (self, n)
self[n] = stringRep(' ', n)
return self[n]
@@ -204,7 +204,10 @@ function m.equal(a, b)
end
return true
elseif tp1 == 'number' then
- return mathAbs(a - b) <= 1e-10
+ if mathAbs(a - b) <= 1e-10 then
+ return true
+ end
+ return tostring(a) == tostring(b)
else
return a == b
end
@@ -617,4 +620,18 @@ function m.sortByScore(tbl, callbacks)
end)
end
+---裁剪字符串
+---@param str string
+---@param mode? '"left"'|'"right"'
+---@return string
+function m.trim(str, mode)
+ if mode == "left" then
+ return str:gsub('^%s+', '')
+ end
+ if mode == "right" then
+ return str:gsub('%s+$', '')
+ end
+ return str:match '^%s*(%S+)%s*$'
+end
+
return m
diff --git a/test/completion/init.lua b/test/completion/init.lua
index 22103896..89772853 100644
--- a/test/completion/init.lua
+++ b/test/completion/init.lua
@@ -60,6 +60,8 @@ local Cared = {
['deprecated'] = true,
}
+local IgnoreFunction = false
+
function TEST(script)
return function (expect)
files.removeAll()
@@ -86,6 +88,16 @@ function TEST(script)
end
end
end
+ if IgnoreFunction then
+ for i = #result, 1, -1 do
+ local item = result[i]
+ if item.label:find '%('
+ and not item.label:find 'function' then
+ result[i] = result[#result]
+ result[#result] = nil
+ end
+ end
+ end
assert(result)
if expect.include then
expect.include = nil
@@ -175,11 +187,11 @@ ass$
]]
{
{
- label = 'assert',
+ label = 'assert(v, message)',
kind = define.CompletionItemKind.Function,
},
{
- label = 'assert()',
+ label = 'assert(v, message)',
kind = define.CompletionItemKind.Snippet,
},
}
@@ -201,11 +213,11 @@ _G.ass$
]]
{
{
- label = 'assert',
+ label = 'assert(v, message)',
kind = define.CompletionItemKind.Function,
},
{
- label = 'assert()',
+ label = 'assert(v, message)',
kind = define.CompletionItemKind.Snippet,
},
}
@@ -217,11 +229,11 @@ ff$
]]
{
{
- label = 'ffff',
+ label = 'ffff(a, b)',
kind = define.CompletionItemKind.Function,
},
{
- label = 'ffff()',
+ label = 'ffff(a, b)',
kind = define.CompletionItemKind.Snippet,
}
}
@@ -285,11 +297,11 @@ mt:g$
]]
{
{
- label = 'get',
+ label = 'get(a, b)',
kind = define.CompletionItemKind.Method,
},
{
- label = 'get()',
+ label = 'get(a, b)',
kind = define.CompletionItemKind.Snippet,
},
{
@@ -311,15 +323,16 @@ loc$
kind = define.CompletionItemKind.Snippet,
},
{
- label = 'collectgarbage',
+ label = 'collectgarbage(opt, ...)',
kind = define.CompletionItemKind.Function,
},
{
- label = 'collectgarbage()',
+ label = 'collectgarbage(opt, ...)',
kind = define.CompletionItemKind.Snippet,
},
}
+IgnoreFunction = true
TEST [[
do$
]]
@@ -332,50 +345,6 @@ do$
label = 'do .. end',
kind = define.CompletionItemKind.Snippet,
},
- {
- label = 'dofile',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'dofile()',
- kind = define.CompletionItemKind.Snippet,
- },
- {
- label = 'load',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'load()',
- kind = define.CompletionItemKind.Snippet,
- },
- {
- label = 'loadfile',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'loadfile()',
- kind = define.CompletionItemKind.Snippet,
- },
- {
- label = 'loadstring',
- kind = define.CompletionItemKind.Function,
- deprecated = true,
- },
- {
- label = 'loadstring()',
- kind = define.CompletionItemKind.Snippet,
- deprecated = true,
- },
- {
- label = 'module',
- kind = define.CompletionItemKind.Function,
- deprecated = true,
- },
- {
- label = 'module()',
- kind = define.CompletionItemKind.Snippet,
- deprecated = true,
- },
}
TEST [[
@@ -454,6 +423,7 @@ t. $
},
}
+IgnoreFunction = false
TEST [[
t.a = {}
function t:b()
@@ -462,7 +432,7 @@ t:$
]]
{
{
- label = 'b',
+ label = 'b()',
kind = define.CompletionItemKind.Method,
},
{
@@ -507,6 +477,7 @@ TEST 'local s = "a:$"' (nil)
TEST 'debug.$'
(EXISTS)
+IgnoreFunction = true
TEST [[
local xxxx = {
xxyy = 1,
@@ -530,22 +501,6 @@ local t = {
label = 'xxzz',
kind = define.CompletionItemKind.Property,
},
- {
- label = 'next',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'next()',
- kind = define.CompletionItemKind.Snippet,
- },
- {
- label = 'xpcall',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'xpcall()',
- kind = define.CompletionItemKind.Snippet,
- },
}
TEST [[
@@ -1030,25 +985,10 @@ else$
label = 'ELSE',
kind = define.CompletionItemKind.Enum,
},
- {
- label = 'select',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'select()',
- kind = define.CompletionItemKind.Snippet,
- },
- {
- label = 'setmetatable',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'setmetatable()',
- kind = define.CompletionItemKind.Snippet,
- },
}
Cared['insertText'] = true
+IgnoreFunction = false
TEST [[
local xpcal
xpcal$
@@ -1059,11 +999,12 @@ xpcal$
kind = define.CompletionItemKind.Variable,
},
{
- label = 'xpcall',
+ label = 'xpcall(f, msgh, arg1, ...)',
kind = define.CompletionItemKind.Function,
+ insertText = EXISTS,
},
{
- label = 'xpcall()',
+ label = 'xpcall(f, msgh, arg1, ...)',
kind = define.CompletionItemKind.Snippet,
insertText = EXISTS,
},
@@ -1077,11 +1018,12 @@ mt:f$
]]
{
{
- label = 'f',
+ label = 'f(a, b, c)',
kind = define.CompletionItemKind.Method,
+ insertText = EXISTS,
},
{
- label = 'f()',
+ label = 'f(a, b, c)',
kind = define.CompletionItemKind.Snippet,
insertText = 'f(${1:a: any}, ${2:b: any}, ${3:c: any})',
},
@@ -1123,6 +1065,7 @@ end",
},
}
Cared['insertText'] = false
+IgnoreFunction = true
TEST [[
local function f()
@@ -1143,22 +1086,6 @@ end
label = 'elseif .. then',
kind = define.CompletionItemKind.Snippet,
},
- {
- label = 'select',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'select()',
- kind = define.CompletionItemKind.Snippet,
- },
- {
- label = 'setmetatable',
- kind = define.CompletionItemKind.Function,
- },
- {
- label = 'setmetatable()',
- kind = define.CompletionItemKind.Snippet,
- },
}
TEST [[
@@ -1259,17 +1186,18 @@ io$
]]
(EXISTS)
+IgnoreFunction = false
TEST [[
loadstring$
]]
{
{
- label = 'loadstring',
+ label = 'loadstring(text, chunkname)',
kind = define.CompletionItemKind.Function,
deprecated = true,
},
{
- label = 'loadstring()',
+ label = 'loadstring(text, chunkname)',
kind = define.CompletionItemKind.Snippet,
deprecated = true,
},
@@ -1293,13 +1221,23 @@ loadstring$
]]
{
{
- label = 'loadstring',
+ label = 'loadstring()',
kind = define.CompletionItemKind.Function,
},
{
label = 'loadstring()',
kind = define.CompletionItemKind.Snippet,
},
+ {
+ label = 'loadstring(text, chunkname)',
+ deprecated = true,
+ kind = define.CompletionItemKind.Function,
+ },
+ {
+ label = 'loadstring(text, chunkname)',
+ deprecated = true,
+ kind = define.CompletionItemKind.Snippet,
+ },
}
TEST [[
@@ -1307,12 +1245,12 @@ debug.setcsta$
]]
{
{
- label = 'setcstacklimit',
+ label = 'setcstacklimit(limit)',
kind = define.CompletionItemKind.Function,
deprecated = true,
},
{
- label = 'setcstacklimit()',
+ label = 'setcstacklimit(limit)',
kind = define.CompletionItemKind.Snippet,
deprecated = true,
},
@@ -1837,9 +1775,6 @@ end)
TEST [[
--- JustTest
----@overload fun(list:table):string
----@overload fun(list:table, sep:string):string
----@overload fun(list:table, sep:string, i:number):string
---@param list table
---@param sep string
---@param i number
@@ -1851,11 +1786,12 @@ zzz$
]]
{
{
- label = 'zzzzz',
+ label = 'zzzzz(list, sep, i, j)',
kind = define.CompletionItemKind.Function,
+ insertText = EXISTS,
},
{
- label = 'zzzzz()',
+ label = 'zzzzz(list, sep, i, j)',
kind = define.CompletionItemKind.Snippet,
insertText = EXISTS,
}
@@ -2334,8 +2270,9 @@ end
m.f$
]]{
{
- label = "f",
+ label = "f()",
kind = define.CompletionItemKind.Function,
+ insertText = EXISTS,
},
{
label = "f()",
@@ -2541,3 +2478,32 @@ TEST [[
},
}
}
+
+Cared['insertText'] = true
+TEST [[
+---@overload fun(a: any, b: any)
+local function zzzz(a) end
+zzzz$
+]]
+{
+ {
+ label = 'zzzz(a)',
+ kind = define.CompletionItemKind.Function,
+ insertText = 'zzzz',
+ },
+ {
+ label = 'zzzz(a)',
+ kind = define.CompletionItemKind.Snippet,
+ insertText = 'zzzz(${1:a: any})',
+ },
+ {
+ label = 'zzzz(a, b)',
+ kind = define.CompletionItemKind.Function,
+ insertText = 'zzzz',
+ },
+ {
+ label = 'zzzz(a, b)',
+ kind = define.CompletionItemKind.Snippet,
+ insertText = 'zzzz(${1:a: any}, ${2:b: any})',
+ },
+}
diff --git a/test/crossfile/hover.lua b/test/crossfile/hover.lua
index 521f5a49..bf56b39a 100644
--- a/test/crossfile/hover.lua
+++ b/test/crossfile/hover.lua
@@ -731,3 +731,33 @@ hover = {
label = 'field Food.firstField: integer = 0',
name = 'food.firstField',
}}
+
+TEST {{ path = 'a.lua', content = '', }, {
+ path = 'b.lua',
+ content = [[
+--[=[
+I'm a multiline comment
+]=]
+local <?food?>
+]]
+},
+hover = {
+ label = 'local food: any',
+ name = 'food',
+ description = "I'm a multiline comment\n"
+}}
+
+TEST {{ path = 'a.lua', content = '', }, {
+ path = 'b.lua',
+ content = [[
+---@return string # 'this is a tab `\t`'
+local function <?f?>() end
+]]
+},
+hover = {
+ label = [[
+function f()
+ -> string]],
+ name = 'food',
+ description = "@*return* — this is a tab `\t`"
+}}
diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua
index 00a2cda8..d4bffdb5 100644
--- a/test/diagnostics/init.lua
+++ b/test/diagnostics/init.lua
@@ -100,7 +100,7 @@ local <!t!> = {}
]]
TEST([[
-<!local function x()
+local <!function x()
end!>
]],
[[
@@ -119,9 +119,9 @@ local <!x!>
]]
TEST([[
-<!local function x()
+local <!function x()
end!>
-<!local function y()
+local <!function y()
x()
end!>
]],
@@ -363,7 +363,7 @@ local f;f = <!function () end!>
]]
TEST [[
-<!local function f() end!>
+local <!function f() end!>
]]
config.config.diagnostics.disable['unused-local'] = nil
diff --git a/test/document_symbol/init.lua b/test/document_symbol/init.lua
index d9f1bec3..718089e2 100644
--- a/test/document_symbol/init.lua
+++ b/test/document_symbol/init.lua
@@ -77,9 +77,9 @@ end
name = 'f',
detail = 'function ()',
kind = define.SymbolKind.Function,
- range = {1, 22},
+ range = {7, 22},
selectionRange = {16, 16},
- valueRange = {1, 22},
+ valueRange = {7, 22},
}
}
@@ -227,9 +227,9 @@ local z
name = 'f',
detail = 'function ()',
kind = define.SymbolKind.Function,
- range = {13, 79},
+ range = {19, 79},
selectionRange = {28, 28},
- valueRange = {13, 79},
+ valueRange = {19, 79},
children = {
[1] = {
name = 'x',
@@ -360,9 +360,9 @@ g = 1
name = 'g',
detail = 'function ()',
kind = define.SymbolKind.Function,
- range = {1, 22},
+ range = {7, 22},
selectionRange = {16, 16},
- valueRange = {1, 22},
+ valueRange = {7, 22},
},
[2] = {
name = 'g',
@@ -449,6 +449,14 @@ local function
range = {7, 7},
selectionRange = {7, 7},
},
+ [2] = {
+ name = "",
+ detail = "function ()",
+ kind = 12,
+ range = {15, 22},
+ selectionRange = {15, 15},
+ valueRange = {15, 22},
+ },
}
TEST [[
@@ -496,17 +504,17 @@ end
name = 'x',
detail = 'function ()',
kind = define.SymbolKind.Function,
- range = {1, 22},
+ range = {7, 22},
selectionRange = {16, 16},
- valueRange = {1, 22},
+ valueRange = {7, 22},
},
[2] = {
name = 'f',
detail = 'function ()',
kind = define.SymbolKind.Function,
- range = {25, 58},
+ range = {31, 58},
selectionRange = {40, 40},
- valueRange = {25, 58},
+ valueRange = {31, 58},
children = {
[1] = {
name = 'c',
@@ -563,9 +571,9 @@ end
name = 'f',
detail = 'function (a, b)',
kind = define.SymbolKind.Function,
- range = {15, 40},
+ range = {21, 40},
selectionRange = {30, 30},
- valueRange = {15, 40},
+ valueRange = {21, 40},
children = {
[1] = {
name = 'a',