summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.luarc.json3
-rw-r--r--changelog.md2
-rw-r--r--locale/en-us/script.lua2
-rw-r--r--locale/zh-cn/script.lua2
-rw-r--r--meta/template/coroutine.lua1
-rw-r--r--script/core/code-action.lua40
-rw-r--r--script/core/diagnostics/await-in-sync.lua26
-rw-r--r--script/proto/define.lua2
-rw-r--r--test/diagnostics/init.lua17
9 files changed, 91 insertions, 4 deletions
diff --git a/.luarc.json b/.luarc.json
index 2a2fcd2f..a5eed93c 100644
--- a/.luarc.json
+++ b/.luarc.json
@@ -9,7 +9,8 @@
"close-non-object"
],
"neededFileStatus": {
- "undefined-field": "Any"
+ "undefined-field": "Any",
+ "await-in-sync": "any"
},
"ignoredFiles": "Opened",
"libraryFiles": "Opened"
diff --git a/changelog.md b/changelog.md
index 963a236c..ff4a8b19 100644
--- a/changelog.md
+++ b/changelog.md
@@ -8,6 +8,8 @@
* `NEW` file encoding supports `utf16le` and `utf16be`
* `NEW` `LuaDoc` annotations:
+ `---@async`: mark a function as async
+* `NEW` diagnostics:
+ + `await-in-sync`: check if calls async function in sync function. disabled by default.
* `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/locale/en-us/script.lua b/locale/en-us/script.lua
index fde50ae9..eb8c12ee 100644
--- a/locale/en-us/script.lua
+++ b/locale/en-us/script.lua
@@ -43,6 +43,7 @@ DIAG_IMPLICIT_ANY = 'Can not infer type.'
DIAG_DEPRECATED = 'Deprecated.'
DIAG_DIFFERENT_REQUIRES = 'The same file is required with different names.'
DIAG_REDUNDANT_RETURN = 'Redundant return.'
+DIAG_AWAIT_IN_SYNC = 'Async function can only be called in async function.'
DIAG_CIRCLE_DOC_CLASS = 'Circularly inherited classes.'
DIAG_DOC_FIELD_NO_CLASS = 'The field must be defined after the class.'
@@ -191,6 +192,7 @@ ACTION_FIX_INSERT_SPACE = 'Insert space.'
ACTION_JSON_TO_LUA = 'Convert JSON to Lua'
ACTION_DISABLE_DIAG_LINE= 'Disable diagnostics on this line ({}).'
ACTION_DISABLE_DIAG_FILE= 'Disable diagnostics in this file ({}).'
+ACTION_MARK_ASYNC = 'Mark current function as async.'
COMMAND_DISABLE_DIAG = 'Disable diagnostics'
COMMAND_MARK_GLOBAL = 'Mark defined global'
diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua
index 120ce765..2843d2b0 100644
--- a/locale/zh-cn/script.lua
+++ b/locale/zh-cn/script.lua
@@ -43,6 +43,7 @@ DIAG_IMPLICIT_ANY = '无法推测出类型。'
DIAG_DEPRECATED = '已废弃。'
DIAG_DIFFERENT_REQUIRES = '使用了不同的名字 require 了同一个文件。'
DIAG_REDUNDANT_RETURN = '冗余返回。'
+DIAG_AWAIT_IN_SYNC = '只能在标记为异步的函数中调用异步函数。'
DIAG_CIRCLE_DOC_CLASS = '循环继承的类。'
DIAG_DOC_FIELD_NO_CLASS = '字段必须定义在类之后。'
@@ -190,6 +191,7 @@ ACTION_FIX_INSERT_SPACE = '插入空格'
ACTION_JSON_TO_LUA = '把 JSON 转成 Lua'
ACTION_DISABLE_DIAG_LINE= '在此行禁用诊断 ({})。'
ACTION_DISABLE_DIAG_FILE= '在此文件禁用诊断 ({})。'
+ACTION_MARK_ASYNC = '将当前函数标记为异步。'
COMMAND_DISABLE_DIAG = '禁用诊断'
COMMAND_MARK_GLOBAL = '标记全局变量'
diff --git a/meta/template/coroutine.lua b/meta/template/coroutine.lua
index 804c84c6..7d8e2cb2 100644
--- a/meta/template/coroutine.lua
+++ b/meta/template/coroutine.lua
@@ -55,6 +55,7 @@ function coroutine.status(co) end
function coroutine.wrap(f) end
---#DES 'coroutine.yield'
+---@async
---@return ...
function coroutine.yield(...) end
diff --git a/script/core/code-action.lua b/script/core/code-action.lua
index 8256107e..ad048c48 100644
--- a/script/core/code-action.lua
+++ b/script/core/code-action.lua
@@ -308,6 +308,44 @@ local function solveTrailingSpace(uri, diag, results)
}
end
+local function solveAwaitInSync(uri, diag, results)
+ local state = files.getState(uri)
+ if not state then
+ return
+ end
+ local start, finish = converter.unpackRange(uri, diag.range)
+ local parentFunction
+ guide.eachSourceType(state.ast, 'function', function (source)
+ if source.start > finish
+ or source.finish < start then
+ return
+ end
+ if not parentFunction or parentFunction.start < source.start then
+ parentFunction = source
+ end
+ end)
+ if not parentFunction then
+ return
+ end
+ local row = guide.rowColOf(parentFunction.start)
+ local pos = guide.positionOf(row, 0)
+ results[#results+1] = {
+ title = lang.script.ACTION_MARK_ASYNC,
+ kind = 'quickfix',
+ edit = {
+ changes = {
+ [uri] = {
+ {
+ start = pos,
+ finish = pos,
+ newText = '---@async\n',
+ }
+ }
+ }
+ },
+ }
+end
+
local function solveDiagnostic(uri, diag, start, results)
if diag.source == lang.script.DIAG_SYNTAX_CHECK then
solveSyntax(uri, diag, results)
@@ -326,6 +364,8 @@ local function solveDiagnostic(uri, diag, start, results)
solveAmbiguity1(uri, diag, results)
elseif diag.code == 'trailing-space' then
solveTrailingSpace(uri, diag, results)
+ elseif diag.code == 'await-in-sync' then
+ solveAwaitInSync(uri, diag, results)
end
disableDiagnostic(uri, diag.code, start, results)
end
diff --git a/script/core/diagnostics/await-in-sync.lua b/script/core/diagnostics/await-in-sync.lua
new file mode 100644
index 00000000..5fb6467d
--- /dev/null
+++ b/script/core/diagnostics/await-in-sync.lua
@@ -0,0 +1,26 @@
+local files = require 'files'
+local guide = require 'parser.guide'
+local vm = require 'vm'
+local lang = require 'language'
+
+return function (uri, callback)
+ local state = files.getState(uri)
+ if not state then
+ return
+ end
+
+ guide.eachSourceType(state.ast, 'call', function (source)
+ local currentFunc = guide.getParentFunction(source)
+ if currentFunc and vm.isAsync(currentFunc) then
+ return
+ end
+ if not vm.isAsync(source.node, true) then
+ return
+ end
+ callback {
+ start = source.node.start,
+ finish = source.node.finish,
+ message = lang.script('DIAG_AWAIT_IN_SYNC'),
+ }
+ end)
+end
diff --git a/script/proto/define.lua b/script/proto/define.lua
index 713857af..2409f972 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -44,6 +44,7 @@ m.DiagnosticDefaultSeverity = {
['no-implicit-any'] = 'Information',
['deprecated'] = 'Warning',
['different-requires'] = 'Warning',
+ ['await-in-sync'] = 'Warning',
['type-check'] = 'Warning',
['duplicate-doc-class'] = 'Warning',
@@ -98,6 +99,7 @@ m.DiagnosticDefaultNeededFileStatus = {
['no-implicit-any'] = 'None',
['deprecated'] = 'Opened',
['different-requires'] = 'Any',
+ ['await-in-sync'] = 'None',
['type-check'] = 'None',
['duplicate-doc-class'] = 'Any',
diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua
index ab55cd92..6d97c7f6 100644
--- a/test/diagnostics/init.lua
+++ b/test/diagnostics/init.lua
@@ -6,6 +6,7 @@ local catch = require 'catch'
config.get 'Lua.diagnostics.neededFileStatus'['deprecated'] = 'Any'
config.get 'Lua.diagnostics.neededFileStatus'['type-check'] = 'Any'
+config.get 'Lua.diagnostics.neededFileStatus'['await-in-sync'] = 'Any'
rawset(_G, 'TEST', true)
@@ -1348,12 +1349,22 @@ end
f()
]]
----TODO(arthur)
-do return end
-
TEST [[
---@type file*
local f
f:read '*a'
f:read('*a')
]]
+
+TEST [[
+function F()
+ <!coroutine.yield!>()
+end
+]]
+
+TEST [[
+---@async
+function F()
+ coroutine.yield()
+end
+]]