summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-11-08 15:54:58 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-11-08 15:54:58 +0800
commit93abb07995244becd028828c1bfb9ee4a76ca7f9 (patch)
treebe0f7cfe7a3c86eec157585f82f407ed067b5f59 /script
parente9c0fee9f413cc55d141231a40775cb48037ccf3 (diff)
parent5a8e3212d25a5c511e25cdf00232e807a7fb5da7 (diff)
downloadlua-language-server-93abb07995244becd028828c1bfb9ee4a76ca7f9.zip
Merge branch 'master' into not-yieldable
Diffstat (limited to 'script')
-rw-r--r--script/client.lua18
-rw-r--r--script/config/loader.lua21
-rw-r--r--script/core/completion.lua4
-rw-r--r--script/core/diagnostics/await-in-sync.lua16
-rw-r--r--script/core/diagnostics/deprecated.lua1
-rw-r--r--script/core/diagnostics/discard-returns.lua29
-rw-r--r--script/core/diagnostics/redundant-value.lua1
-rw-r--r--script/core/diagnostics/type-check.lua1
-rw-r--r--script/core/diagnostics/undefined-field.lua1
-rw-r--r--script/core/diagnostics/undefined-global.lua1
-rw-r--r--script/core/diagnostics/unused-function.lua1
-rw-r--r--script/core/document-symbol.lua1
-rw-r--r--script/core/hint.lua6
-rw-r--r--script/core/semantic-tokens.lua1
-rw-r--r--script/encoder/ansi.lua4
-rw-r--r--script/encoder/init.lua29
-rw-r--r--script/encoder/utf16.lua147
-rw-r--r--script/encoder/utf16be.lua46
-rw-r--r--script/encoder/utf16le.lua46
-rw-r--r--script/files.lua7
-rw-r--r--script/parser/luadoc.lua10
-rw-r--r--script/proto/converter.lua5
-rw-r--r--script/proto/define.lua2
-rw-r--r--script/provider/capability.lua1
-rw-r--r--script/provider/diagnostic.lua3
-rw-r--r--script/provider/provider.lua10
-rw-r--r--script/vm/getDocs.lua112
27 files changed, 380 insertions, 144 deletions
diff --git a/script/client.lua b/script/client.lua
index 4d338016..4d39cd0d 100644
--- a/script/client.lua
+++ b/script/client.lua
@@ -59,6 +59,23 @@ function m.getAbility(name)
return current
end
+function m.getOffsetEncoding()
+ if m._offsetEncoding then
+ return m._offsetEncoding
+ end
+ local clientEncodings = m.getAbility 'offsetEncoding'
+ if type(clientEncodings) == 'table' then
+ for _, encoding in ipairs(clientEncodings) do
+ if encoding == 'utf-8' then
+ m._offsetEncoding = 'utf-8'
+ return m._offsetEncoding
+ end
+ end
+ end
+ m._offsetEncoding = 'utf-16'
+ return m._offsetEncoding
+end
+
local function packMessage(...)
local strs = table.pack(...)
for i = 1, strs.n do
@@ -255,6 +272,7 @@ function m.init(t)
m.client(t.clientInfo.name)
nonil.disable()
lang(LOCALE or t.locale)
+ converter.setOffsetEncoding(m.getOffsetEncoding())
hookPrint()
end
diff --git a/script/config/loader.lua b/script/config/loader.lua
index 03588634..e754be49 100644
--- a/script/config/loader.lua
+++ b/script/config/loader.lua
@@ -19,37 +19,43 @@ local m = {}
function m.loadRCConfig(filename)
local path = workspace.getAbsolutePath(filename)
if not path then
- return
+ m.lastRCConfig = nil
+ return nil
end
local buf = util.loadFile(path)
if not buf then
- return
+ m.lastRCConfig = nil
+ return nil
end
local suc, res = pcall(json.decode, buf)
if not suc then
errorMessage(lang.script('CONFIG_LOAD_ERROR', res))
- return
+ return m.lastRCConfig
end
+ m.lastRCConfig = res
return res
end
function m.loadLocalConfig(filename)
local path = workspace.getAbsolutePath(filename)
if not path then
- return
+ m.lastLocalConfig = nil
+ return nil
end
local buf = util.loadFile(path)
if not buf then
errorMessage(lang.script('CONFIG_LOAD_FAILED', path))
- return
+ m.lastLocalConfig = nil
+ return nil
end
local firstChar = buf:match '%S'
if firstChar == '{' then
local suc, res = pcall(json.decode, buf)
if not suc then
errorMessage(lang.script('CONFIG_LOAD_ERROR', res))
- return
+ return m.lastLocalConfig
end
+ m.lastLocalConfig = res
return res
else
local suc, res = pcall(function ()
@@ -57,8 +63,9 @@ function m.loadLocalConfig(filename)
end)
if not suc then
errorMessage(lang.script('CONFIG_LOAD_ERROR', res))
- return
+ return m.lastLocalConfig
end
+ m.lastLocalConfig = res
return res
end
end
diff --git a/script/core/completion.lua b/script/core/completion.lua
index e30c9c91..b7de7578 100644
--- a/script/core/completion.lua
+++ b/script/core/completion.lua
@@ -718,7 +718,8 @@ end
local function isInString(state, position)
return guide.eachSourceContain(state.ast, position, function (source)
- if source.type == 'string' then
+ if source.type == 'string'
+ and source.start < position then
return true
end
end)
@@ -1629,6 +1630,7 @@ local function tryLuaDocCate(word, results)
'diagnostic',
'module',
'async',
+ 'nodiscard',
} do
if matchKey(word, docType) then
results[#results+1] = {
diff --git a/script/core/diagnostics/await-in-sync.lua b/script/core/diagnostics/await-in-sync.lua
index bfb4af38..558a5ff0 100644
--- a/script/core/diagnostics/await-in-sync.lua
+++ b/script/core/diagnostics/await-in-sync.lua
@@ -4,25 +4,27 @@ local vm = require 'vm'
local lang = require 'language'
local await = require 'await'
+---@async
return function (uri, callback)
local state = files.getState(uri)
if not state then
return
end
- guide.eachSourceType(state.ast, 'call', function (source) ---@async
+ ---@async
+ guide.eachSourceType(state.ast, 'call', function (source)
local currentFunc = guide.getParentFunction(source)
if currentFunc and vm.isAsync(currentFunc, false) then
return
end
await.delay()
- if not vm.isAsync(source.node, true) then
+ if vm.isAsyncCall(source) then
+ callback {
+ start = source.node.start,
+ finish = source.node.finish,
+ message = lang.script('DIAG_AWAIT_IN_SYNC'),
+ }
return
end
- callback {
- start = source.node.start,
- finish = source.node.finish,
- message = lang.script('DIAG_AWAIT_IN_SYNC'),
- }
end)
end
diff --git a/script/core/diagnostics/deprecated.lua b/script/core/diagnostics/deprecated.lua
index 7cd9e00f..e9a1fef7 100644
--- a/script/core/diagnostics/deprecated.lua
+++ b/script/core/diagnostics/deprecated.lua
@@ -8,6 +8,7 @@ local await = require 'await'
local noder = require 'core.noder'
local types = {'getglobal', 'getfield', 'getindex', 'getmethod'}
+---@async
return function (uri, callback)
local ast = files.getState(uri)
if not ast then
diff --git a/script/core/diagnostics/discard-returns.lua b/script/core/diagnostics/discard-returns.lua
new file mode 100644
index 00000000..cef7ece5
--- /dev/null
+++ b/script/core/diagnostics/discard-returns.lua
@@ -0,0 +1,29 @@
+local files = require 'files'
+local guide = require 'parser.guide'
+local vm = require 'vm'
+local await = require 'await'
+local lang = require 'language'
+
+---@async
+return function (uri, callback)
+ local state = files.getState(uri)
+ if not state then
+ return
+ end
+ ---@async
+ guide.eachSourceType(state.ast, 'call', function (source)
+ local parent = source.parent
+ if parent.type ~= 'function'
+ and parent.type ~= 'main' then
+ return
+ end
+ await.delay()
+ if vm.isNoDiscard(source.node, true) then
+ callback {
+ start = source.start,
+ finish = source.finish,
+ message = lang.script('DIAG_DISCARD_RETURNS'),
+ }
+ end
+ end)
+end
diff --git a/script/core/diagnostics/redundant-value.lua b/script/core/diagnostics/redundant-value.lua
index edead570..6f60303b 100644
--- a/script/core/diagnostics/redundant-value.lua
+++ b/script/core/diagnostics/redundant-value.lua
@@ -4,6 +4,7 @@ local lang = require 'language'
local guide = require 'parser.guide'
local await = require 'await'
+---@async
return function (uri, callback)
local state = files.getState(uri)
if not state then
diff --git a/script/core/diagnostics/type-check.lua b/script/core/diagnostics/type-check.lua
index 3fa5050c..8728b169 100644
--- a/script/core/diagnostics/type-check.lua
+++ b/script/core/diagnostics/type-check.lua
@@ -412,6 +412,7 @@ local function matchParams(paramsTypes, i, arg)
return false, messages
end
+---@async
return function (uri, callback)
local ast = files.getState(uri)
if not ast then
diff --git a/script/core/diagnostics/undefined-field.lua b/script/core/diagnostics/undefined-field.lua
index 66b1f8c5..2e64f0cc 100644
--- a/script/core/diagnostics/undefined-field.lua
+++ b/script/core/diagnostics/undefined-field.lua
@@ -18,6 +18,7 @@ local SkipCheckClass = {
['lightuserdata'] = true,
}
+---@async
return function (uri, callback)
local ast = files.getState(uri)
if not ast then
diff --git a/script/core/diagnostics/undefined-global.lua b/script/core/diagnostics/undefined-global.lua
index 640f521b..48c8a226 100644
--- a/script/core/diagnostics/undefined-global.lua
+++ b/script/core/diagnostics/undefined-global.lua
@@ -14,6 +14,7 @@ local requireLike = {
['load'] = true,
}
+---@async
return function (uri, callback)
local ast = files.getState(uri)
if not ast then
diff --git a/script/core/diagnostics/unused-function.lua b/script/core/diagnostics/unused-function.lua
index ada4a23d..0e0c0003 100644
--- a/script/core/diagnostics/unused-function.lua
+++ b/script/core/diagnostics/unused-function.lua
@@ -18,6 +18,7 @@ local function isToBeClosed(source)
return false
end
+---@async
return function (uri, callback)
local ast = files.getState(uri)
if not ast then
diff --git a/script/core/document-symbol.lua b/script/core/document-symbol.lua
index 00299867..07794e60 100644
--- a/script/core/document-symbol.lua
+++ b/script/core/document-symbol.lua
@@ -235,6 +235,7 @@ local function buildSource(source, text, used, symbols)
end
end
+---@async
local function makeSymbol(uri)
local ast = files.getState(uri)
local text = files.getText(uri)
diff --git a/script/core/hint.lua b/script/core/hint.lua
index e094fc51..42390443 100644
--- a/script/core/hint.lua
+++ b/script/core/hint.lua
@@ -6,6 +6,7 @@ local guide = require 'parser.guide'
local await = require 'await'
local define = require 'proto.define'
+---@async
local function typeHint(uri, results, start, finish)
local state = files.getState(uri)
if not state then
@@ -96,6 +97,7 @@ local function hasLiteralArgInCall(call)
return false
end
+---@async
local function paramName(uri, results, start, finish)
local paramConfig = config.get 'Lua.hint.paramName'
if not paramConfig or paramConfig == 'None' then
@@ -158,6 +160,7 @@ local function paramName(uri, results, start, finish)
end)
end
+---@async
local function awaitHint(uri, results, start, finish)
local awaitConfig = config.get 'Lua.hint.await'
if not awaitConfig then
@@ -173,7 +176,7 @@ local function awaitHint(uri, results, start, finish)
end
await.delay()
local node = source.node
- if not vm.isAsync(node, true) then
+ if not vm.isAsyncCall(source) then
return
end
results[#results+1] = {
@@ -185,6 +188,7 @@ local function awaitHint(uri, results, start, finish)
end)
end
+---@async
return function (uri, start, finish)
local results = {}
typeHint(uri, results, start, finish)
diff --git a/script/core/semantic-tokens.lua b/script/core/semantic-tokens.lua
index aef28aa6..8389cbb4 100644
--- a/script/core/semantic-tokens.lua
+++ b/script/core/semantic-tokens.lua
@@ -373,6 +373,7 @@ config.watch(function (key, value)
end
end)
+---@async
return function (uri, start, finish)
local state = files.getState(uri)
local text = files.getText(uri)
diff --git a/script/encoder/ansi.lua b/script/encoder/ansi.lua
index 1016e668..f5273c51 100644
--- a/script/encoder/ansi.lua
+++ b/script/encoder/ansi.lua
@@ -7,14 +7,14 @@ end
local m = {}
-function m.decode(text)
+function m.toutf8(text)
if not unicode then
return text
end
return unicode.a2u(text)
end
-function m.encode(text)
+function m.fromutf8(text)
if not unicode then
return text
end
diff --git a/script/encoder/init.lua b/script/encoder/init.lua
index d7753c1f..0011265a 100644
--- a/script/encoder/init.lua
+++ b/script/encoder/init.lua
@@ -1,6 +1,7 @@
local ansi = require 'encoder.ansi'
-local utf16le = require 'encoder.utf16le'
-local utf16be = require 'encoder.utf16be'
+local utf16 = require 'encoder.utf16'
+local utf16le = utf16('le', utf8.codepoint '�')
+local utf16be = utf16('be', utf8.codepoint '�')
---@alias encoder.encoding '"utf8"'|'"utf16"'|'"utf16le"'|'"utf16be"'
@@ -17,11 +18,11 @@ function m.len(encoding, s, i, j)
j = j or #s
if encoding == 'utf16'
or encoding == 'utf16' then
- local us = utf16le.encode(s:sub(i, j))
+ local us = utf16le.fromutf8(s:sub(i, j))
return #us // 2
end
if encoding == 'utf16be' then
- local us = utf16be.encode(s:sub(i, j))
+ local us = utf16be.fromutf8(s:sub(i, j))
return #us // 2
end
if encoding == 'utf8' then
@@ -43,8 +44,8 @@ function m.offset(encoding, s, n, i)
if not line:find '[\x80-\xff]' then
return n + i - 1
end
- local us = utf16le.encode(line)
- local os = utf16le.decode(us:sub(1, n * 2 - 2))
+ local us = utf16le.fromutf8(line)
+ local os = utf16le.toutf8(us:sub(1, n * 2 - 2))
return #os + i
end
if encoding == 'utf16be' then
@@ -52,8 +53,8 @@ function m.offset(encoding, s, n, i)
if not line:find '[\x80-\xff]' then
return n + i - 1
end
- local us = utf16be.encode(line)
- local os = utf16be.decode(us:sub(1, n * 2 - 2))
+ local us = utf16be.fromutf8(line)
+ local os = utf16be.toutf8(us:sub(1, n * 2 - 2))
return #os + i
end
if encoding == 'utf8' then
@@ -75,11 +76,11 @@ function m.encode(encoding, text, bom)
return text
end
if encoding == 'ansi' then
- return ansi.encode(text)
+ return ansi.fromutf8(text)
end
if encoding == 'utf16'
or encoding == 'utf16le' then
- text = utf16le.encode(text)
+ text = utf16le.fromutf8(text)
if bom == 'yes'
or bom == 'auto' then
text = '\xFF\xFE' .. text
@@ -87,7 +88,7 @@ function m.encode(encoding, text, bom)
return text
end
if encoding == 'utf16be' then
- text = utf16be.encode(text)
+ text = utf16be.fromutf8(text)
if bom == 'yes'
or bom == 'auto' then
text = '\xFE\xFF' .. text
@@ -106,14 +107,14 @@ function m.decode(encoding, text)
return text
end
if encoding == 'ansi' then
- return ansi.decode(text)
+ return ansi.toutf8(text)
end
if encoding == 'utf16'
or encoding == 'utf16le' then
- return utf16le.decode(text)
+ return utf16le.toutf8(text)
end
if encoding == 'utf16be' then
- return utf16be.decode(text)
+ return utf16be.toutf8(text)
end
log.error('Unsupport encode encoding:', encoding)
return text
diff --git a/script/encoder/utf16.lua b/script/encoder/utf16.lua
new file mode 100644
index 00000000..9e71de68
--- /dev/null
+++ b/script/encoder/utf16.lua
@@ -0,0 +1,147 @@
+local error = error
+local strchar = string.char
+local strbyte = string.byte
+local strmatch = string.match
+local utf8char = utf8.char
+local tconcat = table.concat
+
+local function be_tochar(code)
+ return strchar((code >> 8) & 0xFF, code & 0xFF)
+end
+
+local function be_tobyte(s, i)
+ local h, l = strbyte(s, i, i+1)
+ return (h << 8) | l
+end
+
+local function le_tochar(code)
+ return strchar(code & 0xFF, (code >> 8) & 0xFF)
+end
+
+local function le_tobyte(s, i)
+ local l, h = strbyte(s, i, i+1)
+ return (h << 8) | l
+end
+
+local function utf16char(tochar, code)
+ if code < 0x10000 then
+ return tochar(code)
+ else
+ code = code - 0x10000
+ return tochar(0xD800 + (code >> 10))..tochar(0xDC00 + (code & 0x3FF))
+ end
+end
+
+local function utf16next(s, n, tobyte)
+ if n > #s then
+ return
+ end
+ local code1 = tobyte(s, n)
+ if code1 < 0xD800 or code1 >= 0xE000 then
+ return n+2, code1
+ elseif code1 >= 0xD800 and code1 < 0xDC00 then
+ n = n + 2
+ if n > #s then
+ return n --invaild
+ end
+ local code2 = tobyte(s, n)
+ if code2 < 0xDC00 or code2 >= 0xE000 then
+ return n --invaild
+ end
+ local code = 0x10000 + ((code1 - 0xD800) << 10) + ((code2 - 0xDC00) & 0x3FF)
+ return n+2, code
+ else
+ return n+2 --invaild
+ end
+end
+
+local function utf16codes(s, tobyte)
+ return function (_, n)
+ return utf16next(s, n, tobyte)
+ end, s, 1
+end
+
+local _utf8byte = utf8.codes ""
+local function utf8byte(s, n)
+ local _, code = _utf8byte(s, n-1)
+ return code
+end
+
+--[[
+ U+0000.. U+007F 00..7F
+ U+0080.. U+07FF C2..DF 80..BF
+ U+0800.. U+0FFF E0 A0..BF 80..BF
+ U+1000.. U+CFFF E1..EC 80..BF 80..BF
+ U+D000.. U+D7FF ED 80..9F 80..BF
+ U+E000.. U+FFFF EE..EF 80..BF 80..BF
+ U+10000.. U+3FFFF F0 90..BF 80..BF 80..BF
+ U+40000.. U+FFFFF F1..F3 80..BF 80..BF 80..BF
+U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+]]
+local function utf8next(s, n)
+ if n > #s then
+ return
+ end
+ if strmatch(s, "^[\0-\x7F]", n) then
+ return n+1, utf8byte(s, n)
+ elseif strmatch(s, "^[\xC2-\xDF][\x80-\xBF]", n) then
+ return n+2, utf8byte(s, n)
+ elseif strmatch(s, "^[\xE0-\xEF][\x80-\xBF][\x80-\xBF]", n) then
+ return n+3, utf8byte(s, n)
+ elseif strmatch(s, "^[\xF0-\xF4][\x80-\xBF][\x80-\xBF][\x80-\xBF]", n) then
+ return n+4, utf8byte(s, n)
+ else
+ return n+1 --invaild
+ end
+end
+
+local function utf8codes(s)
+ return utf8next, s, 1
+end
+
+return function (what, replace)
+ local tobyte, tochar
+ if what == "be" then
+ tobyte = be_tobyte
+ tochar = be_tochar
+ else
+ tobyte = le_tobyte
+ tochar = le_tochar
+ end
+ local utf8replace = replace and utf8char(replace)
+ local utf16replace = replace and utf16char(tochar, replace)
+ local function toutf8(s)
+ local r = {}
+ for _, code in utf16codes(s, tobyte) do
+ if code == nil then
+ if replace then
+ r[#r+1] = utf8replace
+ else
+ error "invalid UTF-16 code"
+ end
+ else
+ r[#r+1] = utf8char(code)
+ end
+ end
+ return tconcat(r)
+ end
+ local function fromutf8(s)
+ local r = {}
+ for _, code in utf8codes(s) do
+ if code == nil then
+ if replace then
+ r[#r+1] = utf16replace
+ else
+ error "invalid UTF-8 code"
+ end
+ else
+ r[#r+1] = utf16char(tochar, code)
+ end
+ end
+ return tconcat(r)
+ end
+ return {
+ toutf8 = toutf8,
+ fromutf8 = fromutf8,
+ }
+end
diff --git a/script/encoder/utf16be.lua b/script/encoder/utf16be.lua
deleted file mode 100644
index 5fc19b2c..00000000
--- a/script/encoder/utf16be.lua
+++ /dev/null
@@ -1,46 +0,0 @@
-local function tochar(code)
- return string.char((code >> 8) & 0xFF, code & 0xFF)
-end
-
-local function tobyte(s, i)
- local h, l = string.byte(s, i, i+1)
- return (h << 8) | l
-end
-
-local function char(code)
- if code <= 0xFFFF then
- return tochar(code)
- end
- code = code - 0x10000
- return tochar(0xD800 + (code >> 10))..tochar(0xDC00 + (code & 0x3FF))
-end
-
-local m = {}
-
-function m.encode(s)
- local r = {}
- for _, c in utf8.codes(s, true) do
- r[#r+1] = char(c)
- end
- return table.concat(r)
-end
-
-function m.decode(s)
- local r = {}
- local i = 1
- while i < #s do
- local code1 = tobyte(s, i)
- if code1 >= 0xD800 and code1 < 0xE000 then
- i = i + 2
- local code2 = tobyte(s, i)
- local code = 0x10000 + ((code1 - 0xD800) << 10) + ((code2 - 0xDC00) & 0x3FF)
- r[#r+1] = utf8.char(code)
- else
- r[#r+1] = utf8.char(code1)
- end
- i = i + 2
- end
- return table.concat(r)
-end
-
-return m
diff --git a/script/encoder/utf16le.lua b/script/encoder/utf16le.lua
deleted file mode 100644
index d51b4cfb..00000000
--- a/script/encoder/utf16le.lua
+++ /dev/null
@@ -1,46 +0,0 @@
-local function tochar(code)
- return string.char(code & 0xFF, (code >> 8) & 0xFF)
-end
-
-local function tobyte(s, i)
- local l, h = string.byte(s, i, i+1)
- return (h << 8) | l
-end
-
-local function char(code)
- if code <= 0xFFFF then
- return tochar(code)
- end
- code = code - 0x10000
- return tochar(0xD800 + (code >> 10))..tochar(0xDC00 + (code & 0x3FF))
-end
-
-local m = {}
-
-function m.encode(s)
- local r = {}
- for _, c in utf8.codes(s, true) do
- r[#r+1] = char(c)
- end
- return table.concat(r)
-end
-
-function m.decode(s)
- local r = {}
- local i = 1
- while i < #s do
- local code1 = tobyte(s, i)
- if code1 >= 0xD800 and code1 < 0xE000 then
- i = i + 2
- local code2 = tobyte(s, i)
- local code = 0x10000 + ((code1 - 0xD800) << 10) + ((code2 - 0xDC00) & 0x3FF)
- r[#r+1] = utf8.char(code)
- else
- r[#r+1] = utf8.char(code1)
- end
- i = i + 2
- end
- return table.concat(r)
-end
-
-return m
diff --git a/script/files.lua b/script/files.lua
index 9b22ea41..eca3d58d 100644
--- a/script/files.lua
+++ b/script/files.lua
@@ -120,7 +120,9 @@ end
--- 设置文件文本
---@param uri uri
---@param text string
-function m.setText(uri, text, isTrust)
+---@param isTrust boolean
+---@param version integer
+function m.setText(uri, text, isTrust, version)
if not text then
return
end
@@ -134,7 +136,6 @@ function m.setText(uri, text, isTrust)
if not m.fileMap[uri] then
m.fileMap[uri] = {
uri = uri,
- version = 0,
}
m.fileCount = m.fileCount + 1
create = true
@@ -159,7 +160,7 @@ function m.setText(uri, text, isTrust)
m.astMap[uri] = nil
file.cache = {}
file.cacheActiveTime = math.huge
- file.version = file.version + 1
+ file.version = version
m.globalVersion = m.globalVersion + 1
await.close('files.version')
m.onWatch('version')
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index 6f7593c1..c332d4c0 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -1119,6 +1119,14 @@ local function parseAsync()
}
end
+local function parseNoDiscard()
+ return {
+ type = 'doc.nodiscard',
+ start = getFinish(),
+ finish = getFinish(),
+ }
+end
+
local function convertTokens()
local tp, text = nextToken()
if not tp then
@@ -1164,6 +1172,8 @@ local function convertTokens()
return parseModule()
elseif text == 'async' then
return parseAsync()
+ elseif text == 'nodiscard' then
+ return parseNoDiscard()
end
end
diff --git a/script/proto/converter.lua b/script/proto/converter.lua
index cf6331f1..9c75f056 100644
--- a/script/proto/converter.lua
+++ b/script/proto/converter.lua
@@ -2,7 +2,6 @@ local guide = require 'parser.guide'
local files = require 'files'
local encoder = require 'encoder'
--- TODO
local offsetEncoding = 'utf16'
local m = {}
@@ -178,4 +177,8 @@ function m.textEdit(range, newtext)
}
end
+function m.setOffsetEncoding(encoding)
+ offsetEncoding = encoding:lower():gsub('%-', '')
+end
+
return m
diff --git a/script/proto/define.lua b/script/proto/define.lua
index e4216be1..dbb6ba85 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -46,6 +46,7 @@ m.DiagnosticDefaultSeverity = {
['different-requires'] = 'Warning',
['await-in-sync'] = 'Warning',
['not-yieldable'] = 'Warning',
+ ['discard-returns'] = 'Warning',
['type-check'] = 'Warning',
['duplicate-doc-class'] = 'Warning',
@@ -102,6 +103,7 @@ m.DiagnosticDefaultNeededFileStatus = {
['different-requires'] = 'Any',
['await-in-sync'] = 'None',
['not-yieldable'] = 'None',
+ ['discard-returns'] = 'Opened',
['type-check'] = 'None',
['duplicate-doc-class'] = 'Any',
diff --git a/script/provider/capability.lua b/script/provider/capability.lua
index 76cadc0d..b712defc 100644
--- a/script/provider/capability.lua
+++ b/script/provider/capability.lua
@@ -48,6 +48,7 @@ end
function m.getIniter()
local initer = {
+ offsetEncoding = client.getOffsetEncoding(),
-- 文本同步方式
textDocumentSync = {
-- 打开关闭文本时通知
diff --git a/script/provider/diagnostic.lua b/script/provider/diagnostic.lua
index 34bb10d4..c8d6c211 100644
--- a/script/provider/diagnostic.lua
+++ b/script/provider/diagnostic.lua
@@ -216,6 +216,8 @@ function m.doDiagnostic(uri)
return
end
+ local version = files.getVersion(uri)
+
await.setID('diag:' .. uri)
local prog <close> = progress.create(lang.script.WINDOW_DIAGNOSING, 0.5)
@@ -239,6 +241,7 @@ function m.doDiagnostic(uri)
proto.notify('textDocument/publishDiagnostics', {
uri = uri,
+ version = version,
diagnostics = full,
})
if #full > 0 then
diff --git a/script/provider/provider.lua b/script/provider/provider.lua
index 811dc4e0..36752d88 100644
--- a/script/provider/provider.lua
+++ b/script/provider/provider.lua
@@ -185,7 +185,7 @@ proto.on('textDocument/didChange', function (params) ---@async
local uri = doc.uri
--log.debug('changes', util.dump(changes))
local text = tm(uri, changes)
- files.setText(uri, text, true)
+ files.setText(uri, text, true, doc.version)
end)
proto.on('textDocument/hover', function (params) ---@async
@@ -834,14 +834,14 @@ do
if not config.get 'Lua.hint.enable' then
return
end
- await.close 'updateHint'
- await.setID 'updateHint'
- await.delay()
- workspace.awaitReady()
local visibles = files.getVisibles(uri)
if not visibles then
return
end
+ await.close 'updateHint'
+ await.setID 'updateHint'
+ await.delay()
+ workspace.awaitReady()
local edits = {}
local hint = require 'core.hint'
local _ <close> = progress.create(lang.script.WINDOW_PROCESSING_HINT, 0.5)
diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua
index ed2299ec..f5c4e4e1 100644
--- a/script/vm/getDocs.lua
+++ b/script/vm/getDocs.lua
@@ -163,6 +163,23 @@ local function isDeprecated(value)
return false
end
+function vm.isDeprecated(value, deep)
+ if deep then
+ local defs = vm.getDefs(value)
+ if #defs == 0 then
+ return false
+ end
+ for _, def in ipairs(defs) do
+ if not isDeprecated(def) then
+ return false
+ end
+ end
+ return true
+ else
+ return isDeprecated(value)
+ end
+end
+
local function isAsync(value)
if value.type == 'function' then
if not value.bindDocs then
@@ -183,38 +200,111 @@ local function isAsync(value)
return value.async == true
end
-function vm.isDeprecated(value, deep)
+function vm.isAsync(value, deep)
+ if isAsync(value) then
+ return true
+ end
if deep then
local defs = vm.getDefs(value)
if #defs == 0 then
return false
end
for _, def in ipairs(defs) do
- if not isDeprecated(def) then
- return false
+ if isAsync(def) then
+ return true
end
end
- return true
- else
- return isDeprecated(value)
end
+ return false
end
-function vm.isAsync(value, deep)
+local function isNoDiscard(value)
+ if value.type == 'function' then
+ if not value.bindDocs then
+ return false
+ end
+ if value._nodiscard ~= nil then
+ return value._nodiscard
+ end
+ for _, doc in ipairs(value.bindDocs) do
+ if doc.type == 'doc.nodiscard' then
+ value._nodiscard = true
+ return true
+ end
+ end
+ value._nodiscard = false
+ return false
+ end
+ return false
+end
+
+function vm.isNoDiscard(value, deep)
+ if isNoDiscard(value) then
+ return true
+ end
if deep then
local defs = vm.getDefs(value)
if #defs == 0 then
return false
end
for _, def in ipairs(defs) do
- if isAsync(def) then
+ if isNoDiscard(def) then
return true
end
end
- return false
- else
- return isAsync(value)
end
+ return false
+end
+
+local function isCalledInFunction(param)
+ local func = guide.getParentFunction(param)
+ for _, ref in ipairs(param.ref) do
+ if ref.type == 'getlocal' then
+ if ref.parent.type == 'call'
+ and guide.getParentFunction(ref) == func then
+ return true
+ end
+ if ref.parent.type == 'callargs'
+ and ref.parent[1] == ref
+ and guide.getParentFunction(ref) == func then
+ if ref.parent.parent.node.special == 'pcall'
+ or ref.parent.parent.node.special == 'xpcall' then
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+local function isLinkedCall(node, index)
+ for _, def in ipairs(vm.getDefs(node)) do
+ if def.type == 'function' then
+ local param = def.args and def.args[index]
+ if param then
+ if isCalledInFunction(param) then
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+function vm.isAsyncCall(call)
+ if vm.isAsync(call.node, true) then
+ return true
+ end
+ if not call.args then
+ return
+ end
+ for i, arg in ipairs(call.args) do
+ if vm.isAsync(arg, true)
+ and isLinkedCall(call.node, i) then
+ return true
+ end
+ end
+ return false
end
local function makeDiagRange(uri, doc, results)