summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-11-03 17:29:18 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-11-03 17:29:18 +0800
commit7b76328600dd9bc5206f38a549da9e4f99c9ff84 (patch)
tree979dccdcb4c29a2f8e57f0730c0ff58b827b1af8
parented6011c30754bfaa646f5a9a819f20f1f32cbfba (diff)
downloadlua-language-server-7b76328600dd9bc5206f38a549da9e4f99c9ff84.zip
#687 `---@nodiscard`
-rw-r--r--.luarc.json4
-rw-r--r--changelog.md4
-rw-r--r--script/core/completion.lua1
-rw-r--r--script/core/diagnostics/discard-returns.lua29
-rw-r--r--script/parser/luadoc.lua10
-rw-r--r--script/proto/define.lua2
-rw-r--r--script/vm/getDocs.lua56
-rw-r--r--test/diagnostics/init.lua19
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()
+]]