diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2021-11-03 17:29:18 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2021-11-03 17:29:18 +0800 |
commit | 7b76328600dd9bc5206f38a549da9e4f99c9ff84 (patch) | |
tree | 979dccdcb4c29a2f8e57f0730c0ff58b827b1af8 | |
parent | ed6011c30754bfaa646f5a9a819f20f1f32cbfba (diff) | |
download | lua-language-server-7b76328600dd9bc5206f38a549da9e4f99c9ff84.zip |
#687 `---@nodiscard`
-rw-r--r-- | .luarc.json | 4 | ||||
-rw-r--r-- | changelog.md | 4 | ||||
-rw-r--r-- | script/core/completion.lua | 1 | ||||
-rw-r--r-- | script/core/diagnostics/discard-returns.lua | 29 | ||||
-rw-r--r-- | script/parser/luadoc.lua | 10 | ||||
-rw-r--r-- | script/proto/define.lua | 2 | ||||
-rw-r--r-- | script/vm/getDocs.lua | 56 | ||||
-rw-r--r-- | test/diagnostics/init.lua | 19 |
8 files changed, 113 insertions, 12 deletions
diff --git a/.luarc.json b/.luarc.json index a1e5df0b..8dd4a5a9 100644 --- a/.luarc.json +++ b/.luarc.json @@ -18,10 +18,10 @@ "runtime": { "version": "Lua 5.4", "path": [ - "?.lua", "script/?.lua", "script/?/init.lua" - ] + ], + "pathStrict": true }, "workspace": { "maxPreload": 1600, diff --git a/changelog.md b/changelog.md index 8dee9bd0..c1ee6dcb 100644 --- a/changelog.md +++ b/changelog.md @@ -8,8 +8,10 @@ * `NEW` file encoding supports `utf16le` and `utf16be` * `NEW` `LuaDoc` annotations: + `---@async`: mark a function as async + + `---@nodiscard`: the return value of the marking function cannot be discarded * `NEW` diagnostics: - + `await-in-sync`: check if calls async function in sync function. disabled by default. + + `await-in-sync`: check whether calls async function in sync function. disabled by default. + + `discard-returns`: check whether the return value is discarded * `CHG` `LuaDoc` supports unicode * `CHG` no longer asks to trust plugin in VSCode, because VSCode already provides the workspace trust feature * `CHG` skip huge files (>= 10 MB) diff --git a/script/core/completion.lua b/script/core/completion.lua index 21fd69bd..b7de7578 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1630,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/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/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/define.lua b/script/proto/define.lua index 2409f972..039ce722 100644 --- a/script/proto/define.lua +++ b/script/proto/define.lua @@ -45,6 +45,7 @@ m.DiagnosticDefaultSeverity = { ['deprecated'] = 'Warning', ['different-requires'] = 'Warning', ['await-in-sync'] = 'Warning', + ['discard-returns'] = 'Warning', ['type-check'] = 'Warning', ['duplicate-doc-class'] = 'Warning', @@ -100,6 +101,7 @@ m.DiagnosticDefaultNeededFileStatus = { ['deprecated'] = 'Opened', ['different-requires'] = 'Any', ['await-in-sync'] = 'None', + ['discard-returns'] = 'Opened', ['type-check'] = 'None', ['duplicate-doc-class'] = 'Any', diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index 1af85409..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,25 +200,46 @@ 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) - if isAsync(value) then +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 @@ -210,7 +248,7 @@ function vm.isAsync(value, deep) return false end for _, def in ipairs(defs) do - if isAsync(def) then + if isNoDiscard(def) then return true end end diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua index 57c28bbb..d1d0f68f 100644 --- a/test/diagnostics/init.lua +++ b/test/diagnostics/init.lua @@ -1408,3 +1408,22 @@ end return nil end) ]] + +TEST [[ +---@nodiscard +local function f() + return 1 +end + +<!f()!> +]] + + +TEST [[ +---@nodiscard +local function f() + return 1 +end + +X = f() +]] |