diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | .vscode/launch.json | 3 | ||||
m--------- | 3rd/bee.lua | 0 | ||||
m--------- | 3rd/luamake | 0 | ||||
-rw-r--r-- | changelog.md | 4 | ||||
-rw-r--r-- | script/brave/work.lua | 8 | ||||
-rw-r--r-- | script/config/config.lua | 2 | ||||
-rw-r--r-- | script/core/completion/completion.lua | 27 | ||||
-rw-r--r-- | script/core/hover/init.lua | 8 | ||||
-rw-r--r-- | script/core/look-backward.lua | 2 | ||||
-rw-r--r-- | script/core/signature.lua | 2 | ||||
-rw-r--r-- | script/files.lua | 51 | ||||
-rw-r--r-- | script/filewatch.lua | 4 | ||||
-rw-r--r-- | script/global.d.lua | 4 | ||||
-rw-r--r-- | script/parser/guide.lua | 3 | ||||
-rw-r--r-- | script/service/service.lua | 2 | ||||
-rw-r--r-- | script/vm/doc.lua | 7 | ||||
-rw-r--r-- | script/vm/function.lua | 25 | ||||
-rw-r--r-- | script/workspace/loading.lua | 13 | ||||
-rw-r--r-- | script/workspace/workspace.lua | 4 | ||||
-rw-r--r-- | test/completion/common.lua | 111 | ||||
-rw-r--r-- | test/crossfile/hover.lua | 38 | ||||
-rw-r--r-- | test/signature/init.lua | 13 |
23 files changed, 301 insertions, 35 deletions
@@ -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)', +} |