summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--.vscode/launch.json3
m---------3rd/bee.lua0
m---------3rd/luamake0
-rw-r--r--changelog.md4
-rw-r--r--script/brave/work.lua8
-rw-r--r--script/config/config.lua2
-rw-r--r--script/core/completion/completion.lua27
-rw-r--r--script/core/hover/init.lua8
-rw-r--r--script/core/look-backward.lua2
-rw-r--r--script/core/signature.lua2
-rw-r--r--script/files.lua51
-rw-r--r--script/filewatch.lua4
-rw-r--r--script/global.d.lua4
-rw-r--r--script/parser/guide.lua3
-rw-r--r--script/service/service.lua2
-rw-r--r--script/vm/doc.lua7
-rw-r--r--script/vm/function.lua25
-rw-r--r--script/workspace/loading.lua13
-rw-r--r--script/workspace/workspace.lua4
-rw-r--r--test/completion/common.lua111
-rw-r--r--test/crossfile/hover.lua38
-rw-r--r--test/signature/init.lua13
23 files changed, 301 insertions, 35 deletions
diff --git a/.gitignore b/.gitignore
index b88e4489..ea882678 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,4 @@
/meta/*
!/meta/template
!/meta/3rd
-/bin-Windows
-/bin-Linux
-/bin-macOS
-/bin
+/bin*
diff --git a/.vscode/launch.json b/.vscode/launch.json
index b80e7f49..2b077bee 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -36,6 +36,9 @@
]
],
"windows": {
+ "name": "🍄attach",
+ "type": "lua",
+ "request": "attach",
"sourceMaps": [
[
"script\\*",
diff --git a/3rd/bee.lua b/3rd/bee.lua
-Subproject c065344d04a0376a060602323d2459dd69b4471
+Subproject 13d8b64fed24c353cb75dc7b9a63c42722f0f0c
diff --git a/3rd/luamake b/3rd/luamake
-Subproject 1e78bb4c2a4bddee348fcc7057200fe9d6dc896
+Subproject df6317b5fa7c25cb844a8dd893e0d1d9d794bd6
diff --git a/changelog.md b/changelog.md
index 23da8fa2..001fa032 100644
--- a/changelog.md
+++ b/changelog.md
@@ -36,6 +36,7 @@ server will generate `doc.json` and `doc.md` in `LOGPATH`.
* `redundant-return-value`
* `return-type-mismatch`
* `CHG` workspace-symbol: supports chain fields based on global variables and types. try `io.open` or `iolib.open`
+* `CHG` [#1641] if a function only has varargs and has `---@overload`, the varargs will be ignored
* `FIX` [#1567]
* `FIX` [#1593]
* `FIX` [#1595]
@@ -43,6 +44,7 @@ server will generate `doc.json` and `doc.md` in `LOGPATH`.
* `FIX` [#1606]
* `FIX` [#1608]
* `FIX` [#1637]
+* `FIX` [#1642]
[#1177]: https://github.com/sumneko/lua-language-server/issues/1177
[#1458]: https://github.com/sumneko/lua-language-server/issues/1458
@@ -58,6 +60,8 @@ server will generate `doc.json` and `doc.md` in `LOGPATH`.
[#1608]: https://github.com/sumneko/lua-language-server/issues/1608
[#1626]: https://github.com/sumneko/lua-language-server/issues/1626
[#1637]: https://github.com/sumneko/lua-language-server/issues/1637
+[#1641]: https://github.com/sumneko/lua-language-server/issues/1641
+[#1642]: https://github.com/sumneko/lua-language-server/issues/1642
## 3.5.6
`2022-9-16`
diff --git a/script/brave/work.lua b/script/brave/work.lua
index 33172d7e..d62d9a79 100644
--- a/script/brave/work.lua
+++ b/script/brave/work.lua
@@ -40,6 +40,7 @@ brave.on('removeCaches', function (path)
end)
---@class brave.param.compile
+---@field uri uri
---@field text string
---@field mode string
---@field version string
@@ -53,10 +54,15 @@ end)
---@param param brave.param.compile
brave.on('compile', function (param)
local parser = require 'parser'
+ local clock = os.clock()
local state, err = parser.compile(param.text
, param.mode
, param.version
, param.options
)
- return state, err
+ log.debug('compile', param.uri, 'takes:', os.clock() - clock)
+ return {
+ state = state,
+ err = err,
+ }
end)
diff --git a/script/config/config.lua b/script/config/config.lua
index 70e83fc8..b10b0a6d 100644
--- a/script/config/config.lua
+++ b/script/config/config.lua
@@ -76,7 +76,7 @@ end
function m.set(uri, key, value)
local unit = template[key]
assert(unit, 'unknown key: ' .. key)
- local scp = getScope(uri)
+ local scp = getScope(uri, key)
local oldValue = m.get(uri, key)
m.setByScope(scp, key, value)
local newValue = m.get(uri, key)
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua
index 8f42226a..a8909d06 100644
--- a/script/core/completion/completion.lua
+++ b/script/core/completion/completion.lua
@@ -315,7 +315,7 @@ local function checkLocal(state, word, position, results)
return orders[a] < orders[b]
end)
for _, def in ipairs(defs) do
- if def.type == 'function'
+ if (def.type == 'function' and not vm.isVarargFunctionWithOverloads(def))
or def.type == 'doc.type.function' then
local funcLabel = name .. getParams(def, false)
buildFunction(results, source, def, false, {
@@ -364,7 +364,7 @@ local function checkModule(state, word, position, results)
if not locals[stemName]
and not vm.hasGlobalSets(state.uri, 'variable', stemName)
and not globals[stemName]
- and stemName:match '^[%a_][%w_]*$'
+ and stemName:match(guide.namePatternFull)
and matchKey(word, stemName) then
local targetState = files.getState(uri)
if not targetState then
@@ -422,8 +422,11 @@ local function checkModule(state, word, position, results)
end
local function checkFieldFromFieldToIndex(state, name, src, parent, word, startPos, position)
- if name:match '^[%a_][%w_]*$' then
- return nil
+ if name:match(guide.namePatternFull) then
+ if not name:match '[\x80-\xff]'
+ or config.get(state.uri, 'Lua.runtime.unicodeName') then
+ return nil
+ end
end
local textEdit, additionalTextEdits
local startOffset = guide.positionToOffset(state, startPos)
@@ -474,8 +477,8 @@ local function checkFieldFromFieldToIndex(state, name, src, parent, word, startP
}
end
else
- if config.get(state.uri, 'Lua.runtime.version') == 'lua 5.1'
- or config.get(state.uri, 'Lua.runtime.version') == 'luaJIT' then
+ if config.get(state.uri, 'Lua.runtime.version') == 'Lua 5.1'
+ or config.get(state.uri, 'Lua.runtime.version') == 'LuaJIT' then
textEdit.newText = '_G' .. textEdit.newText
else
textEdit.newText = '_ENV' .. textEdit.newText
@@ -487,7 +490,7 @@ end
local function checkFieldThen(state, name, src, word, startPos, position, parent, oop, results)
local value = vm.getObjectFunctionValue(src) or src
local kind = define.CompletionItemKind.Field
- if value.type == 'function'
+ if (value.type == 'function' and not vm.isVarargFunctionWithOverloads(value))
or value.type == 'doc.type.function' then
if oop then
kind = define.CompletionItemKind.Method
@@ -569,9 +572,11 @@ local function checkFieldOfRefs(refs, state, word, startPos, position, parent, o
local value = vm.getObjectFunctionValue(src) or src
if value.type == 'function'
or value.type == 'doc.type.function' then
- funcLabel = name .. getParams(value, oop)
- fields[funcLabel] = src
- count = count + 1
+ if not vm.isVarargFunctionWithOverloads(value) then
+ funcLabel = name .. getParams(value, oop)
+ fields[funcLabel] = src
+ count = count + 1
+ end
if value.type == 'function' and value.bindDocs then
for _, doc in ipairs(value.bindDocs) do
if doc.type == 'doc.overload' then
@@ -726,7 +731,7 @@ local function checkCommon(state, word, position, results)
end
end
end
- for str, offset in state.lua:gmatch '([%a_][%w_]+)()' do
+ for str, offset in state.lua:gmatch('(' .. guide.namePattern .. ')()') do
if #results >= 100 then
results.incomplete = true
break
diff --git a/script/core/hover/init.lua b/script/core/hover/init.lua
index 5a65cbce..61f09455 100644
--- a/script/core/hover/init.lua
+++ b/script/core/hover/init.lua
@@ -60,8 +60,12 @@ local function getHover(source)
if guide.isOOP(def) then
oop = true
end
- if def.type == 'function'
- or def.type == 'doc.type.function' then
+ if def.type == 'function'
+ and not vm.isVarargFunctionWithOverloads(def) then
+ hasFunc = true
+ addHover(def, true, oop)
+ end
+ if def.type == 'doc.type.function' then
hasFunc = true
addHover(def, true, oop)
end
diff --git a/script/core/look-backward.lua b/script/core/look-backward.lua
index d90c4fff..508b57eb 100644
--- a/script/core/look-backward.lua
+++ b/script/core/look-backward.lua
@@ -37,7 +37,7 @@ end
function m.findWord(text, offset)
for i = offset, 1, -1 do
- if not text:sub(i, i):match '[%w_]' then
+ if not text:sub(i, i):match '[%w_\x80-\xff]' then
if i == offset then
return nil
end
diff --git a/script/core/signature.lua b/script/core/signature.lua
index c411d787..de38cb80 100644
--- a/script/core/signature.lua
+++ b/script/core/signature.lua
@@ -137,7 +137,7 @@ local function makeSignatures(text, call, pos)
node = node:getData 'originNode' or node
local mark = {}
for src in node:eachObject() do
- if src.type == 'function'
+ if (src.type == 'function' and not vm.isVarargFunctionWithOverloads(src))
or src.type == 'doc.type.function' then
if not mark[src] then
mark[src] = true
diff --git a/script/files.lua b/script/files.lua
index 8dcbdb8c..25d374ca 100644
--- a/script/files.lua
+++ b/script/files.lua
@@ -16,6 +16,7 @@ local scope = require 'workspace.scope'
local lazy = require 'lazytable'
local cacher = require 'lazy-cacher'
local sp = require 'bee.subprocess'
+local pub = require 'pub'
---@class file
---@field uri uri
@@ -73,6 +74,9 @@ end
---@param uri uri
---@return uri
function m.getRealUri(uri)
+ if platform.OS ~= 'Windows' then
+ return uri
+ end
local filename = furi.decode(uri)
-- normalize uri
uri = furi.encode(filename)
@@ -283,6 +287,9 @@ end
function m.resetText(uri)
local file = m.fileMap[uri]
+ if not file then
+ return
+ end
local originText = file.originText
file.originText = nil
m.setText(uri, originText, file.trusted)
@@ -548,10 +555,13 @@ function m.compileStateThen(state, file)
end
---@param uri uri
----@param file file
---@param async boolean?
---@return parser.state?
-function m.compileState(uri, file, async)
+function m.compileState(uri, async)
+ local file = m.fileMap[uri]
+ if not file then
+ return
+ end
if file.state then
return file.state
end
@@ -580,17 +590,42 @@ function m.compileState(uri, file, async)
end
return nil
end
+
+ ---@type brave.param.compile.options
+ local options = {
+ special = config.get(uri, 'Lua.runtime.special'),
+ unicodeName = config.get(uri, 'Lua.runtime.unicodeName'),
+ nonstandardSymbol = util.arrayToHash(config.get(uri, 'Lua.runtime.nonstandardSymbol')),
+ }
+
+ if async then
+ ---@type brave.param.compile
+ local params = {
+ uri = uri,
+ text = file.text,
+ mode = 'Lua',
+ version = config.get(uri, 'Lua.runtime.version'),
+ options = options
+ }
+ pub.task('compile', params, function (result)
+ if file.text ~= params.text then
+ return
+ end
+ if not result.state then
+ log.error('Compile failed:', uri, result.err)
+ return
+ end
+ m.compileStateThen(result.state, file)
+ end)
+ end
+
local prog <close> = progress.create(uri, lang.script.WINDOW_COMPILING, 0.5)
prog:setMessage(ws.getRelativePath(uri))
local clock = os.clock()
local state, err = parser.compile(file.text
, 'Lua'
, config.get(uri, 'Lua.runtime.version')
- , {
- special = config.get(uri, 'Lua.runtime.special'),
- unicodeName = config.get(uri, 'Lua.runtime.unicodeName'),
- nonstandardSymbol = util.arrayToHash(config.get(uri, 'Lua.runtime.nonstandardSymbol')),
- }
+ , options
)
local passed = os.clock() - clock
if passed > 0.1 then
@@ -620,7 +655,7 @@ function m.getState(uri)
if not file then
return nil
end
- local state = m.compileState(uri, file)
+ local state = m.compileState(uri)
file.cacheActiveTime = timer.clock()
return state
end
diff --git a/script/filewatch.lua b/script/filewatch.lua
index 66e8afb3..2b687dd2 100644
--- a/script/filewatch.lua
+++ b/script/filewatch.lua
@@ -1,5 +1,6 @@
local fw = require 'bee.filewatch'
local fs = require 'bee.filesystem'
+local plat = require 'bee.platform'
local await = require 'await'
local MODIFY = 1 << 0
@@ -11,6 +12,9 @@ local function isExists(filename)
if not suc or not exists then
return false
end
+ if plat.OS ~= 'Windows' then
+ return true
+ end
local suc, res = pcall(fs.fullpath, path)
if not suc then
return false
diff --git a/script/global.d.lua b/script/global.d.lua
index 04b1855b..9065060a 100644
--- a/script/global.d.lua
+++ b/script/global.d.lua
@@ -60,3 +60,7 @@ LAZY = false
-- (experiment) Improve performance, but reduce accuracy
---@type boolean
CACHEALIVE = false
+
+-- (experiment) Compile files in multi cpu cores
+---@type integer
+COMPILECORES = 0
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index e8a53240..391dd3ad 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -81,6 +81,9 @@ local m = {}
m.ANY = {"<ANY>"}
+m.namePattern = '[%a_\x80-\xff][%w_\x80-\xff]*'
+m.namePatternFull = '^' .. m.namePattern .. '$'
+
local blockTypes = {
['while'] = true,
['in'] = true,
diff --git a/script/service/service.lua b/script/service/service.lua
index 7c6deec2..7e0c48c3 100644
--- a/script/service/service.lua
+++ b/script/service/service.lua
@@ -260,7 +260,7 @@ end
function m.start()
util.enableCloseFunction()
await.setErrorHandle(log.error)
- pub.recruitBraves(8)
+ pub.recruitBraves(4 + (COMPILECORES or 0))
proto.listen()
m.report()
m.testVersion()
diff --git a/script/vm/doc.lua b/script/vm/doc.lua
index 293cf5c3..b292bc3c 100644
--- a/script/vm/doc.lua
+++ b/script/vm/doc.lua
@@ -112,6 +112,13 @@ local function getDeprecated(value)
end
end
end
+ if value.type == 'function' then
+ local doc = getDeprecated(value.parent)
+ if doc then
+ value._deprecated = doc
+ return doc
+ end
+ end
value._deprecated = false
return nil
end
diff --git a/script/vm/function.lua b/script/vm/function.lua
index 7cde6298..8b996721 100644
--- a/script/vm/function.lua
+++ b/script/vm/function.lua
@@ -218,7 +218,7 @@ function vm.getMatchedFunctions(func, args, mark)
local funcs = {}
local node = vm.compileNode(func)
for n in node:eachObject() do
- if n.type == 'function'
+ if (n.type == 'function' and not vm.isVarargFunctionWithOverloads(n))
or n.type == 'doc.type.function' then
funcs[#funcs+1] = n
end
@@ -243,3 +243,26 @@ function vm.getMatchedFunctions(func, args, mark)
return matched
end
end
+
+---@param func table
+---@return boolean
+function vm.isVarargFunctionWithOverloads(func)
+ if func.type ~= 'function' then
+ return false
+ end
+ if not func.args then
+ return false
+ end
+ if func.args[1].type ~= '...' then
+ return false
+ end
+ if not func.bindDocs then
+ return false
+ end
+ for _, doc in ipairs(func.bindDocs) do
+ if doc.type == 'doc.overload' then
+ return true
+ end
+ end
+ return false
+end
diff --git a/script/workspace/loading.lua b/script/workspace/loading.lua
index 9344949c..43909357 100644
--- a/script/workspace/loading.lua
+++ b/script/workspace/loading.lua
@@ -88,7 +88,12 @@ function mt:loadFile(uri, libraryUri)
self._cache[uri] = true
log.debug(('Skip loaded file: %s'):format(uri))
else
- local content = pub.awaitTask('loadFile', furi.decode(uri))
+ local content
+ if COMPILECORES then
+ content = util.loadFile(furi.decode(uri))
+ else
+ content = pub.awaitTask('loadFile', furi.decode(uri))
+ end
self.read = self.read + 1
self:update()
if not content then
@@ -99,7 +104,11 @@ function mt:loadFile(uri, libraryUri)
-- self._sets[#self._sets+1] = waker
--end)
files.setText(uri, content, false)
- files.getState(uri)
+ if COMPILECORES then
+ files.compileState(uri, true)
+ else
+ files.compileState(uri)
+ end
if not self._cache[uri] then
files.addRef(uri)
end
diff --git a/script/workspace/workspace.lua b/script/workspace/workspace.lua
index 45fd6595..272ceb0e 100644
--- a/script/workspace/workspace.lua
+++ b/script/workspace/workspace.lua
@@ -558,7 +558,9 @@ config.watch(function (uri, key, value, oldValue)
or key:find '^Lua.type'
or key:find '^files' then
if value ~= oldValue then
- m.reload(scope.getScope(uri))
+ local scp = scope.getScope(uri)
+ m.reload(scp)
+ m.resetFiles(scp)
end
end
end)
diff --git a/test/completion/common.lua b/test/completion/common.lua
index 9f5e5f6f..cc164d3a 100644
--- a/test/completion/common.lua
+++ b/test/completion/common.lua
@@ -1069,7 +1069,7 @@ t['<??>']
}
TEST [[
-_ENV['z.b.c'] = {}
+_G['z.b.c'] = {}
z<??>
]]
@@ -1085,6 +1085,58 @@ z<??>
},
}
+config.set(nil, 'Lua.runtime.version', 'Lua 5.1')
+
+TEST [[
+_G['z.b.c'] = {}
+
+z<??>
+]]
+{
+ {
+ label = 'z.b.c',
+ kind = define.CompletionItemKind.Field,
+ textEdit = {
+ start = 20000,
+ finish = 20001,
+ newText = '_G["z.b.c"]',
+ },
+ },
+}
+
+config.set(nil, 'Lua.runtime.version', 'Lua 5.4')
+
+TEST [[
+中文字段 = 1
+
+中文<??>
+]]
+{
+ {
+ label = '中文字段',
+ kind = define.CompletionItemKind.Enum,
+ textEdit = {
+ start = 20000,
+ finish = 20006,
+ newText = '_ENV["中文字段"]',
+ },
+ },
+}
+
+config.set(nil, 'Lua.runtime.unicodeName', true)
+TEST [[
+中文字段 = 1
+
+中文<??>
+]]
+{
+ {
+ label = '中文字段',
+ kind = define.CompletionItemKind.Enum,
+ },
+}
+config.set(nil, 'Lua.runtime.unicodeName', false)
+
TEST [[
io.close(1, <??>)
]]
@@ -3795,3 +3847,60 @@ print(t2.A.<??>)
kind = define.CompletionItemKind.Field,
},
}
+
+TEST [[
+---@overload fun(x: number)
+---@overload fun(x: number, y: number)
+local function fff(...)
+end
+
+fff<??>
+]]
+{
+ {
+ label = 'fff(x)',
+ kind = define.CompletionItemKind.Function,
+ },
+ {
+ label = 'fff(x, y)',
+ kind = define.CompletionItemKind.Function,
+ },
+}
+
+TEST [[
+---@overload fun(x: number)
+---@overload fun(x: number, y: number)
+function fff(...)
+end
+
+fff<??>
+]]
+{
+ {
+ label = 'fff(x)',
+ kind = define.CompletionItemKind.Function,
+ },
+ {
+ label = 'fff(x, y)',
+ kind = define.CompletionItemKind.Function,
+ },
+}
+
+TEST [[
+---@overload fun(x: number)
+---@overload fun(x: number, y: number)
+function t.fff(...)
+end
+
+t.fff<??>
+]]
+{
+ {
+ label = 'fff(x)',
+ kind = define.CompletionItemKind.Function,
+ },
+ {
+ label = 'fff(x, y)',
+ kind = define.CompletionItemKind.Function,
+ },
+}
diff --git a/test/crossfile/hover.lua b/test/crossfile/hover.lua
index c3d7078c..6d1f3df6 100644
--- a/test/crossfile/hover.lua
+++ b/test/crossfile/hover.lua
@@ -1606,3 +1606,41 @@ someType:
| "#" -- description
```]]
}
+
+TEST { { path = 'a.lua', content = [[
+---@overload fun(x: number)
+---@overload fun(x: number, y: number)
+local function <?f?>(...)
+end
+]] },
+hover = [[
+```lua
+function f(x: number)
+```
+
+---
+
+```lua
+function f(x: number, y: number)
+```]]
+}
+
+TEST { { path = 'a.lua', content = [[
+---@overload fun(x: number)
+---@overload fun(x: number, y: number)
+local function f(...)
+end
+
+<?f?>
+]] },
+hover = [[
+```lua
+function f(x: number)
+```
+
+---
+
+```lua
+function f(x: number, y: number)
+```]]
+}
diff --git a/test/signature/init.lua b/test/signature/init.lua
index b78fdaa5..e92b89e8 100644
--- a/test/signature/init.lua
+++ b/test/signature/init.lua
@@ -316,3 +316,16 @@ X({}, <??>)
{
'function X(a: { x: number, y: number, z: number }, <!b: string!>)'
}
+
+TEST [[
+---@overload fun(x: number)
+---@overload fun(x: number, y: number)
+local function f(...)
+end
+
+f(<??>)
+]]
+{
+'function f(<!x: number!>)',
+'function f(<!x: number!>, y: number)',
+}