summaryrefslogtreecommitdiff
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
parente9c0fee9f413cc55d141231a40775cb48037ccf3 (diff)
parent5a8e3212d25a5c511e25cdf00232e807a7fb5da7 (diff)
downloadlua-language-server-93abb07995244becd028828c1bfb9ee4a76ca7f9.zip
Merge branch 'master' into not-yieldable
-rw-r--r--.luarc.json7
-rw-r--r--README.md5
-rw-r--r--changelog.md8
-rw-r--r--locale/en-us/script.lua7
-rw-r--r--locale/pt-br/meta.lua429
-rw-r--r--locale/pt-br/script.lua270
-rw-r--r--locale/zh-cn/script.lua1
-rw-r--r--main.lua2
-rw-r--r--meta/template/basic.lua16
-rw-r--r--meta/template/bit.lua12
-rw-r--r--meta/template/bit32.lua12
-rw-r--r--meta/template/coroutine.lua6
-rw-r--r--meta/template/debug.lua12
-rw-r--r--meta/template/ffi.lua10
-rw-r--r--meta/template/io.lua5
-rw-r--r--meta/template/jit.lua1
-rw-r--r--meta/template/math.lua34
-rw-r--r--meta/template/os.lua6
-rw-r--r--meta/template/package.lua1
-rw-r--r--meta/template/string.lua17
-rw-r--r--meta/template/table.lua4
-rw-r--r--meta/template/utf8.lua6
-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
-rw-r--r--test/completion/common.lua10
-rw-r--r--test/diagnostics/init.lua55
51 files changed, 1270 insertions, 190 deletions
diff --git a/.luarc.json b/.luarc.json
index 5a32f889..6ace9089 100644
--- a/.luarc.json
+++ b/.luarc.json
@@ -11,7 +11,8 @@
"neededFileStatus": {
"undefined-field": "Any",
"await-in-sync": "Any",
- "not-yieldable": "Any"
+ "not-yieldable": "Any",
+ "discard-returns": "Any"
},
"ignoredFiles": "Opened",
"libraryFiles": "Opened"
@@ -19,10 +20,10 @@
"runtime": {
"version": "Lua 5.4",
"path": [
- "?.lua",
"script/?.lua",
"script/?/init.lua"
- ]
+ ],
+ "pathStrict": true
},
"workspace": {
"maxPreload": 1600,
diff --git a/README.md b/README.md
index 78d2120b..31c8a7aa 100644
--- a/README.md
+++ b/README.md
@@ -87,8 +87,9 @@ If you find any mistakes, please [tell me][issues] or use [Pull Requests][@meta]
## Locale
-- [x] en-US
-- [x] zh-CN
+- [x] en-us
+- [x] zh-cn
+- [x] pt-br (thanks [Jeferson Ferreira](https://github.com/jefersonf))
Please [help me][en-US] improve the quality of `en-US`.
diff --git a/changelog.md b/changelog.md
index ff4a8b19..b36642fd 100644
--- a/changelog.md
+++ b/changelog.md
@@ -8,12 +8,18 @@
* `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
+* `NEW` locale `pt-br`, thanks [Jeferson Ferreira](https://github.com/jefersonf)
+* `NEW` supports [utf-8-offsets](https://clangd.llvm.org/extensions#utf-8-offsets)
* `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)
+* `FIX` [#777](https://github.com/sumneko/lua-language-server/issues/777)
* `FIX` [#778](https://github.com/sumneko/lua-language-server/issues/778)
+* `FIX` [#780](https://github.com/sumneko/lua-language-server/issues/780)
## 2.4.7
`2021-10-27`
diff --git a/locale/en-us/script.lua b/locale/en-us/script.lua
index b81723b4..a03aec0a 100644
--- a/locale/en-us/script.lua
+++ b/locale/en-us/script.lua
@@ -45,6 +45,7 @@ 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_NOT_YIELDABLE = 'The {}th parameter of this function was not marked as yieldable, but an async function was passed in. (Use `---@param name async fun()` to mark as yieldable)'
+DIAG_DISCARD_RETURNS = 'The return values of this function cannot be discarded.'
DIAG_CIRCLE_DOC_CLASS = 'Circularly inherited classes.'
DIAG_DOC_FIELD_NO_CLASS = 'The field must be defined after the class.'
@@ -56,7 +57,7 @@ DIAG_UNDEFINED_DOC_NAME = 'Undefined type or alias `{}`.'
DIAG_UNDEFINED_DOC_PARAM = 'Undefined param `{}`.'
DIAG_UNKNOWN_DIAG_CODE = 'Unknown diagnostic code `{}`.'
-MWS_NOT_SUPPORT = '{} dose not support multi workspace for now, I may need to restart to support the new workspace ...'
+MWS_NOT_SUPPORT = '{} does not support multi workspace for now, I may need to restart to support the new workspace ...'
MWS_RESTART = 'Restart'
MWS_NOT_COMPLETE = 'Workspace is not complete yet. You may try again later...'
MWS_COMPLETE = 'Workspace is complete now. You may try again...'
@@ -77,7 +78,7 @@ PARSER_UNKNOWN_SYMBOL = 'Unexpected symbol `{symbol}`.'
PARSER_MISS_SYMBOL = 'Missed symbol `{symbol}`.'
PARSER_MISS_ESC_X = 'Should be 2 hexadecimal digits.'
PARSER_UTF8_SMALL = 'At least 1 hexadecimal digit.'
-PARSER_UTF8_MAX = 'Should between {min} and {max} .'
+PARSER_UTF8_MAX = 'Should be between {min} and {max} .'
PARSER_ERR_ESC = 'Invalid escape sequence.'
PARSER_MUST_X16 = 'Should be hexadecimal digits.'
PARSER_MISS_EXPONENT = 'Missed digits for the exponent.'
@@ -97,7 +98,7 @@ PARSER_UNSUPPORT_SYMBOL = '{version} does not support this grammar.'
PARSER_UNEXPECT_DOTS = 'Cannot use `...` outside a vararg function.'
PARSER_UNEXPECT_SYMBOL = 'Unexpected symbol `{symbol}` .'
PARSER_UNKNOWN_TAG = 'Unknown attribute.'
-PARSER_MULTI_TAG = 'Dose not support multi attributes.'
+PARSER_MULTI_TAG = 'Does not support multi attributes.'
PARSER_UNEXPECT_LFUNC_NAME = 'Local function can only use identifiers as name.'
PARSER_UNEXPECT_EFUNC_NAME = 'Function as expression cannot be named.'
PARSER_ERR_LCOMMENT_END = 'Multi-line annotations should be closed by `{symbol}` .'
diff --git a/locale/pt-br/meta.lua b/locale/pt-br/meta.lua
new file mode 100644
index 00000000..6e23cff8
--- /dev/null
+++ b/locale/pt-br/meta.lua
@@ -0,0 +1,429 @@
+-- basic
+arg = 'Argumentos de inicialização para a versão standalone da linguagem Lua.'
+assert = 'Emite um erro se o valor de seu argumento v for falso (i.e., `nil` ou `false`); caso contrário, devolve todos os seus argumentos. Em caso de erro, `message` é o objeto de erro que, quando ausente, por padrão é `"assertion failed!"`'
+cgopt.collect = 'Realiza um ciclo completo de coleta de lixo (i.e., garbage-collection cycle).'
+cgopt.stop = 'Interrompe a execução automática.'
+cgopt.restart = 'Reinicia a execução automática.'
+cgopt.count = 'Retorna, em Kbytes, a quantidade total de memória utilizada pela linguagem Lua.'
+cgopt.step = 'Executa a coleta de lixo (i.e., garbage-collection) em uma única etapa. A quantidade de execuções por etapa é controlada via `arg`.'
+cgopt.setpause = 'Estabelece pausa. Defina via `arg` o intervalo de pausa do coletor de lixo (i.e., garbage-collection).'
+cgopt.setstepmul = 'Estabelece um multiplicador para etapa de coleta de lixo (i.e., garbage-collection). Defina via `arg` o valor multiplicador.'
+cgopt.incremental = 'Altera o modo do coletor para incremental.'
+cgopt.generational = 'Altera o modo do coletor para geracional.'
+cgopt.isrunning = 'Retorna um valor booleano indicando se o coletor de lixo (i.e., garbage-collection) está em execução.'
+collectgarbage = 'Esta função é uma interface genérica para o coletor de lixo (i.e., garbage-collection). Ela executa diferentes funções de acordo com seu primeiro argumento, `opt`.'
+dofile = 'Abre o arquivo fornecido por argumento e executa seu conteúdo como código Lua. Quando chamado sem argumentos, `dofile` executa o conteúdo da entrada padrão (`stdin`). Retorna todos os valores retornados pelo trecho de código contido no arquivo. Em caso de erros, o `dofile` propaga o erro para seu chamador. Ou seja, o `dofile` não funciona em modo protegido.'
+error = [[
+Termina a última chamada de função protegida e retorna `message` como objeto de `erro`.
+
+Normalmente, o 'erro' adiciona algumas informações sobre a localização do erro no início da mensagem, quando a mensagem for uma string.
+]]
+_G = 'Uma variável global (não uma função) que detém o ambiente global (ver §2.2). Lua em si não usa esta variável; mudar seu valor não afeta nenhum ambiente e vice-versa.'
+getfenv = 'Retorna o ambiente atual em uso pela função. O `f` pode ser uma função Lua ou um número que especifica a função naquele nível de pilha.'
+getmetatable = 'Se o objeto não tiver uma metatable, o retorno é `nil`. Mas caso a metatable do objeto tenha um campo `__metatable`, é retornado o valor associado. Caso contrário, retorna a metatable do objeto dado.'
+ipairs = [[
+Retorna três valores (uma função iteradora, a tabela `t`, e `0`) para que a seguinte construção
+```lua
+ for i,v in ipairs(t) do body end
+```
+possa iterar sobre os pares de valor-chave `(1,t[1]), (2,t[2]), ...`, até o primeiro índice ausente.
+]]
+loadmode.b = 'Somente blocos binários.'
+loadmode.t = 'Somente blocos de texto.'
+loadmode.bt = 'Tanto binário quanto texto.'
+load['<5.1'] = 'Carrega um bloco utilizando a função `func` para obter suas partes. Cada chamada para o `func` deve retornar uma string que é concatenada com os resultados anteriores.'
+load['>5.2'] = [[
+Carrega um bloco.
+
+Se o bloco (i.e., `chunk`) é uma string, o bloco é essa string. Se o bloco é uma função, a função "load" é chamada repetidamente para obter suas partes. Cada chamada para o bloco deve retornar uma string que é concatenada com os resultados anteriores. O fim do bloco é sinalizado com o retorno de uma string vazia ou `nil`.
+]]
+loadfile = 'Carrega um bloco de arquivo `filename` ou da entrada padrão, se nenhum nome de arquivo for dado.'
+loadstring = 'Carrega um bloco a partir de uma string dada.'
+module = 'Cria um módulo.'
+next = [[
+Permite que um programa percorra todos os campos de uma tabela. Seu primeiro argumento é uma tabela e seu segundo argumento é um índice nesta tabela. Uma chamada `next` retorna o próximo índice da tabela e seu valor associado. Quando chamado usando `nil` como segundo argumento, `next` retorna um índice inicial e seu valor associado. Quando chamado com o último índice, ou com `nil` em uma tabela vazia, o `next` retorna o `nil`. Se o segundo argumento estiver ausente, então é interpretado como `nil`. Portanto, pode-se utilizar o `next(t)` para verificar se uma tabela está vazia.
+
+A ordem na qual os índices são enumerados não é especificada, *mesmo para índices numéricos*. (Para percorrer uma tabela em ordem numérica, utilize um `for`).
+
+O comportamento do `next` é indefinido se, durante a iteração/travessia, você atribuir qualquer valor a um campo inexistente na tabela. Você pode, entretanto, modificar os campos existentes e pode, inclusive, os definir como nulos.
+]]
+pairs = [[
+Se `t` tem um "meta" método (i.e., metamethod) `__pairs`, a chamada é feita usando t como argumento e retorna os três primeiros resultados.
+
+Caso contrário, retorna três valores: a função $next, a tabela `t` e `nil`, para que a seguinte construção
+```lua
+ for k,v in pairs(t) do body end
+```
+possa iterar sobre todos os pares de valor-chave da tabela 't'.
+
+Veja a função $next para saber as ressalvas em modificar uma tabela durante sua iteração.
+]]
+pcall = [[
+Chama a função `f` com os argumentos dados em modo *protegido*. Isto significa que qualquer erro dentro de `f` não é propagado; em vez disso, o `pcall` captura o erro e retorna um código de status. Seu primeiro resultado é o código de status (booleano), que é verdadeiro se a chamada for bem sucedida sem erros. Neste caso, `pcall' também retorna todos os resultados da chamada, após este primeiro resultado. Em caso de qualquer erro, `pcall` retorna `false` mais o objeto de erro.
+]]
+print = [[
+Recebe qualquer número de argumentos e imprime seus valores na saída padrão `stdout`, convertendo cada argumento em uma string seguindo as mesmas regras do $tostring.
+A função `print` não é destinada à saída formatada, mas apenas como uma forma rápida de mostrar um valor, por exemplo, para debugging. Para controle completo sobre a saída, use $string.format e $io.write.
+]]
+rawequal = 'Verifica se v1 é igual a v2, sem invocar a metatable `__eq`.'
+rawget = 'Obtém o valor real de `table[index]`, sem invocar a metatable `__index`.'
+rawlen = 'Retorna o comprimento do objeto `v`, sem invocar a metatable `__len`.'
+rawset = [[
+Define o valor real de `table[index]` para `value`, sem utilizar o metavalue `__newindex`. `table` deve ser uma tabela, `index` qualquer valor diferente de `nil` e `NaN`, e `value` qualquer valor de tipos do Lua.
+Esta função retorna uma `table`.
+]]
+select = 'Se `index` é um número, retorna todos os argumentos após o número do argumento `index`; um número negativo de índices do final (`-1` é o último argumento). Caso contrário, `index` deve ser a string `"#"`, e `select` retorna o número total de argumentos extras dados.'
+setfenv = 'Define o ambiente a ser utilizado pela função em questão.'
+setmetatable = [[
+Define a metatable para a tabela dada. Se `metatabela` for `nil`, remove a metatable da tabela em questão. Se a metatable original tiver um campo `__metatable', um erro é lançado.
+
+Esta função retorna uma `table`.
+
+Para alterar a metatable de outros tipos do código Lua, você deve utilizar a biblioteca de debugging (§6.10).
+]]
+tonumber = [[
+Quando chamado sem a base, `tonumber` tenta converter seu argumento para um número. Se o argumento já for um número ou uma string numérica, então `tonumber` retorna este número; caso contrário, retorna `fail`.
+
+A conversão de strings pode resultar em números inteiros ou de ponto flutuante, de acordo com as convenções lexicais de Lua (ver §3.1). A string pode ter espaços antes e depois e um sinal.
+]]
+tostring = [[
+Recebe um valor de qualquer tipo e o converte em uma string em formato legível por humanos.
+
+Se a metatable de `v` tem um campo `__tostring', então `tostring' chama o valor correspondente usando `v` como argumento, e utiliza o resultado da chamada como seu resultado. Caso contrário, se a metatable de `v` tiver um campo `__name` com um valor do tipo string, `tostring` pode utilizar essa string em seu resultado final.
+
+Para controle completo de como os números são convertidos, utilize $string.format.
+]]
+type = [[
+Retorna o tipo de seu único argumento, codificado como uma string. Os resultados possíveis desta função são `"nil"` (uma string, não o valor `nil`), `"number"`, `"string"`, `"boolean"`, `"table"`, `"function"`, `"thread"`, e `"userdata"`.
+]]
+_VERSION = 'Uma variável global (não uma função) que contém uma string contendo a versão Lua em execução.'
+warn = 'Emite um aviso com uma mensagem composta pela concatenação de todos os seus argumentos (que devem ser strings).'
+xpcall['=5.1'] = 'Faz chamada a função `f` com os argumentos dados e em modo protegido, usando um manipulador de mensagens dado.'
+xpcall['>5.2'] = 'Faz chamada a função `f` com os argumentos dados e em modo protegido, usando um manipulador de mensagens dado.'
+unpack = [[
+Retorna os elementos da lista dada. Esta função é equivalente a
+```lua
+ return list[i], list[i+1], ···, list[j]
+```
+]]
+
+bit32 = ''
+bit32.arshift = [[
+Retorna o número `x` deslocado `disp` bits para a direita. Deslocamentos negativos movem os bits para a esquerda.
+
+Esta operação de deslocamento é chamada de deslocamento aritmético. Os bits vagos à esquerda são preenchidos com cópias do bit mais significativo de `x`; os bits vagos à direita são preenchidos com zeros.
+]]
+bit32.band = 'Retorna a operação bitwise *and* de seus operandos.'
+bit32.bnot = [[
+Retorna a negação da operação bitwise de `x`.
+
+```lua
+assert(bit32.bnot(x) == (-1 - x) % 2^32)
+```
+]]
+bit32.bor = 'Retorna a operação bitwise *or* de seus operandos.'
+bit32.btest = 'Retorna um valor booleano verdadeiro se a operação bitwise *and* de seus operandos for diferente de zero. Falso, caso contrário.'
+bit32.bxor = 'Retorna a operação bitwise *exclusive or* de seus operandos.'
+bit32.extract = 'Retorna o número formado pelos bits de `field` a `field + width - 1` de `n`, sem sinal.'
+bit32.replace = 'Retorna uma cópia de `n` com os bits de `field` a `field + width - 1` substituídos pelo valor `v` .'
+bit32.lrotate = 'Retorna o número `x` rotacionado `disp` bits para a esquerda. Rotações negativos movem os bits para a direita. '
+bit32.lshift = [[
+Retorna o número `x` deslocado `disp` bits para a esquerda. Deslocamentos negativos movem os bits para a direita. Em ambas as direções, os bits vazios/vagos são preenchidos com zeros.
+
+```lua
+assert(bit32.lshift(b, disp) == (b * 2^disp) % 2^32)
+```
+]]
+bit32.rrotate = 'Retorna o número `x` rotacionado `disp` bits para a direita. Deslocamentos negativos movem os bits para a esquerda.'
+bit32.rshift = [[
+Retorna o número `x` deslocado `disp` bits para a direita. Deslocamentos negativos movem os bits para a esquerda. Em ambas as direções, os bits vazios são preenchidos com zeros.
+
+```lua
+assert(bit32.rshift(b, disp) == math.floor(b % 2^32 / 2^disp))
+```
+]]
+
+coroutine = ''
+coroutine.create = 'Cria uma nova `coroutine`, a partir de uma função `f` e retorna esta coroutine como objeto do tipo `"thread"`.'
+coroutine.isyieldable = 'Retorna verdadeiro quando a `coroutine` em execução for finalizada.'
+coroutine.isyieldable['>5.4']= 'Retorna verdadeiro quando a `coroutine` `co` for finalizada. Por padrão `co` é uma coroutine em execução.'
+coroutine.close = 'Finaliza a coroutine `co` , encerrando todas as variáveis pendentes e colocando a coroutine em um estado morto.'
+coroutine.resume = 'Inicia ou continua a execução da coroutine `co`.'
+coroutine.running = 'Retorna a `coroutine` corrente e um booleana verdadeiro quando a coroutine corrente é a principal.'
+coroutine.status = 'Retorna o status da `coroutine `co`.'
+coroutine.wrap = 'Cria uma nova `coroutine`, a partir de uma função `f` e retorna uma função que retorna a coroutine cada vez que ele é chamado.'
+coroutine.yield = 'Suspende a execução da coroutine chamada.'
+costatus.running = 'Está em execução.'
+costatus.suspended = 'Está suspenso ou não foi iniciado.'
+costatus.normal = 'Está ativo, mas não está em execução.'
+costatus.dead = 'Terminou ou parou devido a erro'
+
+debug = ''
+debug.debug = 'Entra em modo interativo com o usuário, executando os comandos de entrada.'
+debug.getfenv = 'Retorna o ambiente do objeto `o` .'
+debug.gethook = 'Retorna as configurações do `hook` atual da `thread`.'
+debug.getinfo = 'Retorna uma tabela com informações sobre uma função.'
+debug.getlocal['<5.1'] = 'Retorna o nome e o valor da variável local com índice `local` da função de nível `level` da pilha.'
+debug.getlocal['>5.2'] = 'Retorna o nome e o valor da variável local com índice `local` da função de nível `f` da pilha.'
+debug.getmetatable = 'Retorna a `metatable` do valor dado.'
+debug.getregistry = 'Retorna a tabela de registro.'
+debug.getupvalue = 'Retorna o nome e o valor da variável antecedente com índice `up` da função.'
+debug.getuservalue['<5.3'] = 'Retorna o valor de Lua associado a `u` (i.e., user).'
+debug.getuservalue['>5.4'] = [[
+Retorna o `n`-ésimo valor de usuário associado
+aos dados do usuário `u` e um booleano,
+`false`, se nos dados do usuário não existir esse valor.
+]]
+debug.setcstacklimit = [[
+### **Deprecated in `Lua 5.4.2`**
+
+Estabelece um novo limite para a pilha C. Este limite controla quão profundamente as chamadas aninhadas podem ir em Lua, com a intenção de evitar um transbordamento da pilha.
+
+Em caso de sucesso, esta função retorna o antigo limite. Em caso de erro, ela retorna `false`.
+]]
+debug.setfenv = 'Define o ambiente do `object` dado para a `table` dada .'
+debug.sethook = 'Define a função dada como um `hook`.'
+debug.setlocal = 'Atribui o valor `value` à variável local com índice `local` da função de nível `level` da pilha.'
+debug.setmetatable = 'Define a `metatable` com o valor dado para tabela dada (que pode ser `nil`).'
+debug.setupvalue = 'Atribui `value` a variável antecedente com índice `up` da função.'
+debug.setuservalue['<5.3'] = 'Define o valor dado como o valor Lua associado ao `udata` (i.e., user data).'
+debug.setuservalue['>5.4'] = [[
+Define o valor dado como
+o `n`-ésimo valor de usuário associado ao `udata` (i.e., user data).
+O `udata` deve ser um dado de usuário completo.
+]]
+debug.traceback = 'Retorna uma string com um `traceback` de chamadas. A string de mensagen (opcional) é anexada no início do traceback.'
+debug.upvalueid = 'Retorna um identificador único (como um dado de usuário leve) para o valor antecedente de numero `n` da função dada.'
+debug.upvaluejoin = 'Faz o `n1`-ésimo valor da função `f1` (i.e., closure Lua) referir-se ao `n2`-ésimo valor da função `f2`.'
+infowhat.n = '`name` e `namewhat`'
+infowhat.S = '`source`, `short_src`, `linedefined`, `lastlinedefined` e `what`'
+infowhat.l = '`currentline`'
+infowhat.t = '`istailcall`'
+infowhat.u['<5.1'] = '`nups`'
+infowhat.u['>5.2'] = '`nups`, `nparams` e `isvararg`'
+infowhat.f = '`func`'
+infowhat.r = '`ftransfer` e `ntransfer`'
+infowhat.L = '`activelines`'
+hookmask.c = 'Faz chamada a um `hook` quando o Lua chama uma função.'
+hookmask.r = 'Faz chamada a um `hook` quando o retorno de uma função é executado.'
+hookmask.l = 'Faz chamada a um `hook` quando encontra nova linha de código.'
+
+file = ''
+file[':close'] = 'Fecha o arquivo `file`.'
+file[':flush'] = 'Salva qualquer dado de entrada no arquivo `file`.'
+file[':lines'] = [[
+------
+```lua
+for c in file:lines(...) do
+ body
+end
+```
+]]
+file[':read'] = 'Lê o arquivo de acordo com o formato fornecido e que especifica o que deve ser lido.'
+file[':seek'] = 'Define e obtém a posição do arquivo, medida a partir do início do arquivo.'
+file[':setvbuf'] = 'Define o modo de `buffer` para um arquivo de saída.'
+file[':write'] = 'Escreve o valor de cada um de seus argumentos no arquivo.'
+readmode.n = 'Lê um numeral e o devolve como número.'
+readmode.a = 'Lê o arquivo completo.'
+readmode.l = 'Lê a próxima linha pulando o final da linha.'
+readmode.L = 'Lê a próxima linha mantendo o final da linha.'
+seekwhence.set = 'O cursor base é o início do arquivo.'
+seekwhence.cur = 'O cursor base é a posição atual.'
+seekwhence['.end'] = 'O cursor base é o final do arquivo.'
+vbuf.no = 'A saída da operação aparece imediatamente.'
+vbuf.full = 'Realizado apenas quando o `buffer` está cheio.'
+vbuf.line = '`Buffered` até que uma nova linha seja encontrada.'
+
+io = ''
+io.stdin = 'Entrada padrão.'
+io.stdout = 'Saída padrão.'
+io.stderr = 'Erro padrão.'
+io.close = 'Fecha o arquivo dado ou o arquivo de saída padrão.'
+io.flush = 'Salva todos os dados gravados no arquivo de saída padrão.'
+io.input = 'Define o arquivo de entrada padrão.'
+io.lines = [[
+------
+```lua
+for c in io.lines(filename, ...) do
+ body
+end
+```
+]]
+io.open = 'Abre um arquivo no modo especificado pela *string* `mode`.'
+io.output = 'Define o arquivo de saída padrão.'
+io.popen = 'Inicia o programa dado em um processo separado.'
+io.read = 'Lê o arquivo de acordo com o formato fornecido e que especifica o que deve ser lido.'
+io.tmpfile = 'Em caso de sucesso, retorna um `handler` para um arquivo temporário.'
+io.type = 'Verifica se `obj` é um identificador de arquivo válido.'
+io.write = 'Escreve o valor de cada um dos seus argumentos para o arquivo de saída padrão.'
+openmode.r = 'Modo de leitura.'
+openmode.w = 'Modo de escrita.'
+openmode.a = 'Modo de anexação.'
+openmode['.r+'] = 'Modo de atualização, todos os dados anteriores são preservados.'
+openmode['.w+'] = 'Modo de atualização, todos os dados anteriores são apagados.'
+openmode['.a+'] = 'Modo de anexação e atualização, os dados anteriores são preservados, a escrita só é permitida no final do arquivo.'
+openmode.rb = 'Modo de leitura. (em modo binário)'
+openmode.wb = 'Modo de escrita. (em modo binário)'
+openmode.ab = 'Modo de anexação. (em modo binário)'
+openmode['.r+b'] = 'Modo de atualização, todos os dados anteriores são preservados. (em modo binário)'
+openmode['.w+b'] = 'Modo de atualização, todos os dados anteriores são apagados. (em modo binário)'
+openmode['.a+b'] = 'Modo de anexação e atualização, todos os dados anteriores são preservados, a escrita só é permitida no final do arquivo. (em modo binário)'
+popenmode.r = 'Leia dados deste programa pelo arquivo.'
+popenmode.w = 'Escreva dados neste programa pelo arquivo.'
+filetype.file = '`handler` para arquivo aberto.'
+filetype['.closed file'] = '`handler` para arquivo fechado.'
+filetype['.nil'] = 'Não é um `handler` de arquivo'
+
+math = ''
+math.abs = 'Retorna o valor absoluto de `x`.'
+math.acos = 'Retorna o arco cosseno de `x` (em radianos).'
+math.asin = 'Retorna o arco seno de `x` (em radianos).'
+math.atan['<5.2'] = 'Retorna o arco tangente de `x` (em radianos).'
+math.atan['>5.3'] = 'Retorna o arco tangente de `y/x` (em radianos).'
+math.atan2 = 'Retorna o arco tangente de `y/x` (em radianos).'
+math.ceil = 'Retorna o menor valor inteiro maior ou igual a `x`.'
+math.cos = 'Retorna o cosseno de `x` (requer valor em radianos).'
+math.cosh = 'Retorna o cosseno hiperbólico de `x` (requer valor em radianos).'
+math.deg = 'Converte o ângulo `x` de radianos para graus.'
+math.exp = 'Retorna o valor `e^x` (onde `e` é a base do logaritmo natural).'
+math.floor = 'Retorna o maior valor inteiro menor ou igual a `x`.'
+math.fmod = 'Retorna o resto da divisão de `x` por `y` que arredonda o quociente para zero.'
+math.frexp = 'Decompõe `x` em fatores e expoentes. Retorna `m` e `e` tal que `x = m * (2 ^ e)` é um inteiro e o valor absoluto de `m` está no intervalo [0,5, 1) (ou zero quando `x` é zero).'
+math.huge = 'Um valor maior que qualquer outro valor numérico.'
+math.ldexp = 'Retorna `m * (2 ^ e)`.'
+math.log['<5.1'] = 'Retorna o logaritmo natural de `x`.'
+math.log['>5.2'] = 'Retorna o logaritmo de `x` na base dada.'
+math.log10 = 'Retorna o logaritmo `x` na base 10.'
+math.max = 'Retorna o argumento com o valor máximo de acordo com o operador `<`.'
+math.maxinteger = 'Retorna o valor máximo para um inteiro.'
+math.min = 'Retorna o argumento com o valor mínimo de acordo com o operador `<`.'
+math.mininteger = 'Retorna o valor mínimo para um inteiro.'
+math.modf = 'Retorna a parte inteira e a parte fracionária de `x`.'
+math.pi = 'O valor de *π*.'
+math.pow = 'Retorna `x ^ y`.'
+math.rad = 'Converte o ângulo `x` de graus para radianos.'
+math.random = [[
+* `math.random()`: Retorna um valor real (i.e., ponto flutuante) no intervalo [0,1).
+* `math.random(n)`: Retorna um inteiro no intervalo [1, n].
+* `math.random(m, n)`: Retorna um inteiro no intervalo [m, n].
+]]
+math.randomseed['<5.3'] = 'Define `x` como valor semente (i.e., `seed`) para a função geradora de números pseudo-aleatória.'
+math.randomseed['>5.4'] = [[
+* `math.randomseed(x, y)`: Concatena `x` e `y` em um espaço de 128-bits que é usado como valor semente (`seed`) para reinicializar o gerador de números pseudo-aleatório.
+* `math.randomseed(x)`: Equivale a `math.randomseed(x, 0)` .
+* `math.randomseed()`: Gera um valor semente (i.e., `seed`) com fraca probabilidade de aleatoriedade.
+]]
+math.sin = 'Retorna o seno de `x` (requer valor em radianos).'
+math.sinh = 'Retorna o seno hiperbólico de `x` (requer valor em radianos).'
+math.sqrt = 'Retorna a raiz quadrada de `x`.'
+math.tan = 'Retorna a tangente de `x` (requer valor em radianos).'
+math.tanh = 'Retorna a tangente hiperbólica de `x` (requer valor em radianos).'
+math.tointeger = 'Se o valor `x` pode ser convertido para um inteiro, retorna esse inteiro.'
+math.type = 'Retorna `"integer"` se `x` é um inteiro, `"float"` se for um valor real (i.e., ponto flutuante), ou `nil` se `x` não é um número.'
+math.ult = 'Retorna `true` se e somente se `m` é menor `n` quando eles são comparados como inteiros sem sinal.'
+
+os = ''
+os.clock = 'Retorna uma aproximação do valor, em segundos, do tempo de CPU usado pelo programa.'
+os.date = 'Retorna uma string ou uma tabela contendo data e hora, formatada de acordo com a string `format` fornecida.'
+os.difftime = 'Retorna a diferença, em segundos, do tempo `t1` para o tempo` t2`.'
+os.execute = 'Passa `command` para ser executado por um `shell` do sistema operacional.'
+os.exit['<5.1'] = 'Chama a função `exit` do C para encerrar o programa.'
+os.exit['>5.2'] = 'Chama a função `exit` do ISO C para encerrar o programa.'
+os.getenv = 'Retorna o valor da variável de ambiente de processo `varname`.'
+os.remove = 'Remove o arquivo com o nome dado.'
+os.rename = 'Renomeia o arquivo ou diretório chamado `oldname` para `newname`.'
+os.setlocale = 'Define a localidade atual do programa.'
+os.time = 'Retorna a hora atual quando chamada sem argumentos, ou um valor representando a data e a hora local especificados pela tabela fornecida.'
+os.tmpname = 'Retorna uma string com um nome de arquivo que pode ser usado como arquivo temporário.'
+osdate.year = 'Quatro dígitos.'
+osdate.month = '1-12'
+osdate.day = '1-31'
+osdate.hour = '0-23'
+osdate.min = '0-59'
+osdate.sec = '0-61'
+osdate.wday = 'Dia da semana, 1–7, Domingo é 1'
+osdate.yday = 'Dia do ano, 1–366'
+osdate.isdst = 'Bandeira para indicar horário de verão (i.e., `Daylight Saving Time`), um valor booleano.'
+
+package = ''
+require['<5.3'] = 'Carrega o módulo fornecido e retorna qualquer valor retornado pelo módulo (`true` quando `nil`).'
+require['>5.4'] = 'Carrega o módulo fornecido e retorna qualquer valor retornado pelo pesquisador (`true` quando `nil`). Além desse valor, também retorna como segundo resultado um carregador de dados retornados pelo pesquisador, o que indica como `require` encontrou o módulo. (Por exemplo, se o módulo vier de um arquivo, este carregador de dados é o caminho do arquivo.)'
+package.config = 'string descrevendo configurações a serem utilizadas durante a compilação de pacotes.'
+package.cpath = 'O caminho usado pelo `require` para procurar pelo carregador C.'
+package.loaded = 'Uma tabela usada pelo `require` para controlar quais módulos já estão carregados.'
+package.loaders = 'Uma tabela usada pelo `require` para controlar como carregar módulos.'
+package.loadlib = 'Dinamicamente vincula o programa no `host` com a biblioteca C `libname`.'
+package.path = 'O caminho usado pelo `require` para procurar por um carregador Lua.'
+package.preload = 'Uma tabela para armazenar carregadores de módulos específicos.'
+package.searchers = 'Uma tabela usada pelo `require` para controlar como buscar módulos.'
+package.searchpath = 'Procura por `name` em `path`.'
+package.seeall = 'Define uma `metatable` `module` com o campo `__index` referenciando o ambiente global, para que este módulo herde valores do ambiente global. Para ser usado como uma opção a função `module`.'
+
+string = ''
+string.byte = 'Retorna os códigos numéricos internos dos caracteres `s[i], s[i+1], ..., s[j]`.'
+string.char = 'Retorna uma string com comprimento igual ao número de argumentos, no qual cada caractere possui o código numérico interno igual ao seu argumento correspondente.'
+string.dump = 'Retorna uma string contendo uma representação binária (i.e., *binary chunk*) da função dada.'
+string.find = 'Procura a primeira correspondencia de `pattern` (veja §6.4.1) na string.'
+string.format = 'Retorna uma versão formatada de seu número variável de argumentos após a descrição dada em seu primeiro argumento.'
+string.gmatch = [[
+Retorna um iterator que, a cada vez que é chamado, retorna as próximas capturas de `pattern` (veja §6.4.1) sobre a string *s*.
+
+Por exemplo, o loop a seguir irá iterar em todas as palavras da string *s*, imprimindo cada palavra por linha:
+```lua
+ s = "hello world from Lua"
+ for w in string.gmatch(s, "%a+") do
+ print(w)
+ end
+```
+]]
+string.gsub = 'Retorna uma cópia da *s* em que todas ou, caso fornecido, as primeiras `n` ocorrências de `pattern` (veja §6.4.1) que tiverem sido substituídas por uma string de substituição especificada por `repl`.'
+string.len = 'Retorna o comprimento da string.'
+string.lower = 'Retorna uma cópia desta string com todas as letras maiúsculas alteradas para minúsculas.'
+string.match = 'Procura a primeira ocorrência do `pattern` (veja §6.4.1) na string.'
+string.pack = 'Retorna uma string binária contendo os valores `V1`, `v2`, etc. empacotados (isto é, serializado de forma binário) de acordo com o formato da string `fmt` fornecida (veja §6.4.2).'
+string.packsize = 'Retorna o tamanho de uma string resultante de `string.pack` com o formato da string `fmt` fornecida (veja §6.4.2).'
+string.rep['>5.2'] = 'Retorna uma string que é a concatenação de `n` cópias da string `s` separadas pela string `sep`.'
+string.rep['<5.1'] = 'Retorna uma string que é a concatenação de `n` cópias da string `s`.'
+string.reverse = 'Retorna uma string que representa a string `s` invertida.'
+string.sub = 'Retorna a substring da string `s` que começa no índice `i` e continua até o índice `j`.'
+string.unpack = 'Retorna os valores empacotados na string de acordo com o formato da string `fmt` fornecida (veja §6.4.2).'
+string.upper = 'Retorna uma cópia desta string com todas as letras minúsculas alteradas para maiúsculas.'
+
+table = ''
+table.concat = 'Dada uma lista onde todos os elementos são strings ou números, retorna a string `list[i]..sep..list[i+1] ··· sep..list[j]`.'
+table.insert = 'Insere o elemento `value` na posição `pos` de `list`.'
+table.maxn = 'Retorna o maior índice numérico positivo da tabela fornecida ou zero se a tabela não tiver índices numéricos positivos.'
+table.move = [[
+Move os elementos da tabela `a1` para tabela `a2`.
+```lua
+a2[t],··· = a1[f],···,a1[e]
+return a2
+```
+]]
+table.pack = 'Retorna uma nova tabela com todos os argumentos armazenados em chaves `1`, `2`, etc. e com um campo `"n"` com o número total de argumentos.'
+table.remove = 'Remove de `list` o elemento na posição `pos`, retornando o valor do elemento removido.'
+table.sort = 'Ordena os elementos de `list` em uma determinada ordem, *in-place*, de `list[1]` para `list[#list]`.'
+table.unpack = [[
+Retorna os elementos da lista fornecida. Esta função é equivalente a
+```lua
+ return list[i], list[i+1], ···, list[j]
+```
+Por padrão, `i` é `1` e `j` é `#list`.
+]]
+
+utf8 = ''
+utf8.char = 'Recebe zero ou mais inteiros, converte cada um à sua sequência de byte UTF-8 correspondente e retorna uma string com a concatenação de todas essas sequências.'
+utf8.charpattern = 'O padrão que corresponde exatamente uma sequência de byte UTF-8, supondo que seja uma sequência válida UTF-8.'
+utf8.codes = [[
+Retorna valores tal que a seguinte construção
+```lua
+for p, c in utf8.codes(s) do
+ body
+end
+```
+itere em todos os caracteres UTF-8 na string s, com p sendo a posição (em bytes) e c o *codepoint* de cada caractere. Ele gera um erro se encontrado qualquer sequência de byte inválida.
+]]
+utf8.codepoint = 'Retorna os *codepoints* (em inteiros) de todos os caracteres em `s` que iniciam entre as posições do byte `i` e `j` (ambos inclusos).'
+utf8.len = 'Retorna o número de caracteres UTF-8 na string `s` que começa entre as posições `i` e `j` (ambos inclusos).'
+utf8.offset = 'Returns the position (in bytes) where the encoding of the `n`-th character of `s` (counting from position `i`) starts.'
+utf8.offset = 'Retorna a posição (em bytes) onde a codificação do `n`-ésimo caractere de `s` inícia (contando a partir da posição `i`).'
diff --git a/locale/pt-br/script.lua b/locale/pt-br/script.lua
new file mode 100644
index 00000000..9bd7ca8a
--- /dev/null
+++ b/locale/pt-br/script.lua
@@ -0,0 +1,270 @@
+DIAG_LINE_ONLY_SPACE = 'Linha com espaços apenas.'
+DIAG_LINE_POST_SPACE = 'Linha com espaço extra ao final.'
+DIAG_UNUSED_LOCAL = 'Escopo não utilizado `{}`.'
+DIAG_UNDEF_GLOBAL = 'Escopo global indefinido `{}`.'
+DIAG_UNDEF_FIELD = 'Campo indefinido `{}`.'
+DIAG_UNDEF_ENV_CHILD = 'Variável indefinida `{}` (overloaded `_ENV` ).'
+DIAG_UNDEF_FENV_CHILD = 'Variável indefinida `{}` (módulo interno).'
+DIAG_GLOBAL_IN_NIL_ENV = 'Valor global inválido (`_ENV` é `nil`).'
+DIAG_GLOBAL_IN_NIL_FENV = 'Valor global inválido (Ambiente do módulo é `nil`).'
+DIAG_UNUSED_LABEL = 'Identificador não utilizado `{}`.'
+DIAG_UNUSED_FUNCTION = 'Funções não utilizadas.'
+DIAG_UNUSED_VARARG = 'vararg não utilizado.'
+DIAG_REDEFINED_LOCAL = 'Valor local redefinido `{}`.'
+DIAG_DUPLICATE_INDEX = 'Índice duplicado `{}`.'
+DIAG_DUPLICATE_METHOD = 'Método duplicado `{}`.'
+DIAG_PREVIOUS_CALL = 'Será interpretado como `{}{}`. Pode ser necessário adicionar uma `,`.'
+DIAG_PREFIELD_CALL = 'Será interpretado como `{}{}`. Pode ser necessário adicionar uma `,` ou `;`.'
+DIAG_OVER_MAX_ARGS = 'A função aceita apenas os parâmetros {:d}, mas você passou {:d}.'
+DIAG_OVER_MAX_ARGS = 'Recebe apenas {} variáveis, mas você definiu {}.'
+DIAG_AMBIGUITY_1 = 'Calcule primeiro `{}`. Você pode precisar adicionar colchetes.'
+DIAG_LOWERCASE_GLOBAL = 'Variável global com inicial minúscula, você esqueceu o `local` ou digitou errado?'
+DIAG_EMPTY_BLOCK = 'Bloco vazio.'
+DIAG_DIAGNOSTICS = 'Diagnósticos Lua.'
+DIAG_SYNTAX_CHECK = 'Verificação de sintaxe Lua.'
+DIAG_NEED_VERSION = 'Suportado em {}, atual é {}.'
+DIAG_DEFINED_VERSION = 'Definido em {}, a corrente é {}.'
+DIAG_DEFINED_CUSTOM = 'Definido em {}.'
+DIAG_DUPLICATE_CLASS = 'Classe duplicada `{}`.'
+DIAG_UNDEFINED_CLASS = 'Classe indefinida `{}`.'
+DIAG_CYCLIC_EXTENDS = 'Herança cíclica.'
+DIAG_INEXISTENT_PARAM = 'Parâmetro inexistente.'
+DIAG_DUPLICATE_PARAM = 'Parâmetro duplicado.'
+DIAG_NEED_CLASS = 'Classe precisa ser definida primeiro.'
+DIAG_DUPLICATE_SET_FIELD= 'Campo duplicado `{}`.'
+DIAG_SET_CONST = 'Atribuição à variável constante.'
+DIAG_SET_FOR_STATE = 'Atribuição à variável to tipo for-state.'
+DIAG_CODE_AFTER_BREAK = 'Não é possível executar o código depois `break`.'
+DIAG_UNBALANCED_ASSIGNMENTS = 'O valor é atribuído como `nil` porque o número de valores não é suficiente. Em Lua, `x, y = 1` é equivalente a `x, y = 1, nil` .'
+DIAG_REQUIRE_LIKE = 'Você pode tratar `{}` como `require` por configuração.'
+DIAG_COSE_NON_OBJECT = 'Não é possível fechar um valor desse tipo. (A menos que se defina o meta método `__close`)'
+DIAG_COUNT_DOWN_LOOP = 'Você quer dizer `{}` ?'
+DIAG_IMPLICIT_ANY = 'Não pode inferir tipo.'
+DIAG_DEPRECATED = 'Descontinuada.'
+DIAG_DIFFERENT_REQUIRES = 'O mesmo arquivo é necessário com nomes diferentes.'
+DIAG_REDUNDANT_RETURN = 'Retorno redundante.'
+
+DIAG_CIRCLE_DOC_CLASS = 'Classes com herança cíclica.'
+DIAG_DOC_FIELD_NO_CLASS = 'O campo deve ser definido após a classe.'
+DIAG_DUPLICATE_DOC_CLASS = 'Classe definida duplicada `{}`.'
+DIAG_DUPLICATE_DOC_FIELD = 'Campos definidos duplicados `{}`.'
+DIAG_DUPLICATE_DOC_PARAM = 'Parâmetros duplicados `{}`.'
+DIAG_UNDEFINED_DOC_CLASS = 'Classe indefinida `{}`.'
+DIAG_UNDEFINED_DOC_NAME = 'Tipo ou alias indefinido `{}`.'
+DIAG_UNDEFINED_DOC_PARAM = 'Parâmetro indefinido `{}`.'
+DIAG_UNKNOWN_DIAG_CODE = 'Código de diagnóstico desconhecido `{}`.'
+
+MWS_NOT_SUPPORT = '{} não é suportado múltiplos espaços de trabalho por enquanto, posso precisar reiniciar para estabelecer um novo espaço de trabalho ...'
+MWS_RESTART = 'Reiniciar'
+MWS_NOT_COMPLETE = 'O espaço de trabalho ainda não está completo. Você pode tentar novamente mais tarde ...'
+MWS_COMPLETE = 'O espaço de trabalho está completo agora. Você pode tentar novamente ...'
+MWS_MAX_PRELOAD = 'Arquivos pré-carregados atingiram o limite máximo ({}), você precisa abrir manualmente os arquivos que precisam ser carregados.'
+MWS_UCONFIG_FAILED = 'Armazenamento da configuração do usuário falhou.'
+MWS_UCONFIG_UPDATED = 'Configuração do usuário atualizada.'
+MWS_WCONFIG_UPDATED = 'Configuração do espaço de trabalho atualizado.'
+
+WORKSPACE_SKIP_LARGE_FILE = 'Arquivo muito grande: {} ignorada. O limite de tamanho atualmente definido é: {} KB, e o tamanho do arquivo é: {} KB.'
+WORKSPACE_LOADING = 'Carregando espaço de trabalho.'
+WORKSPACE_DIAGNOSTIC = 'Diagnóstico de espaço de trabalho.'
+WORKSPACE_SKIP_HUGE_FILE = 'Por motivos de desempenho, a análise deste arquivo foi interrompida: {}'
+
+PARSER_CRASH = 'Parser quebrou! Últimas palavras: {}'
+PARSER_UNKNOWN = 'Erro de sintaxe desconhecido ...'
+PARSER_MISS_NAME = '<name> esperado.'
+PARSER_UNKNOWN_SYMBOL = 'Símbolo inesperado `{symbol}`.'
+PARSER_MISS_SYMBOL = 'Símbolo não encontrado `{symbol}`.'
+PARSER_MISS_ESC_X = 'Deve ser 2 dígitos hexadecimais.'
+PARSER_UTF8_SMALL = 'Pelo menos 1 dígito hexadecimal.'
+PARSER_UTF8_MAX = 'Deve estar entre {min} e {max}.'
+PARSER_ERR_ESC = 'Sequência de saída inválida.'
+PARSER_MUST_X16 = 'Deve ser dígitos hexadecimais.'
+PARSER_MISS_EXPONENT = 'Dígitos perdidos para o expoente.'
+PARSER_MISS_EXP = '<exp> esperada.'
+PARSER_MISS_FIELD = '<field> esperado.'
+PARSER_MISS_METHOD = '<method> esperado.'
+PARSER_ARGS_AFTER_DOTS = '`...` deve ser o último argumento.'
+PARSER_KEYWORD = '<keyword> não pode ser usado como nome.'
+PARSER_EXP_IN_ACTION = 'Inesperada <exp>.'
+PARSER_BREAK_OUTSIDE = '<break> não está dentro de um loop.'
+PARSER_MALFORMED_NUMBER = 'Número malformado.'
+PARSER_ACTION_AFTER_RETURN = '<eof> esperado após `return`.'
+PARSER_ACTION_AFTER_BREAK = '<eof> esperado após `break`.'
+PARSER_NO_VISIBLE_LABEL = 'Nenhum identificador visível `{label}` .'
+PARSER_REDEFINE_LABEL = 'Identificador `{label}` já foi definido.'
+PARSER_UNSUPPORT_SYMBOL = '{version} não suporta esta gramática.'
+PARSER_UNEXPECT_DOTS = 'Não pode usar `...` fora de uma função vararg.'
+PARSER_UNEXPECT_SYMBOL = 'Símbolo inesperado `{symbol}` .'
+PARSER_UNKNOWN_TAG = 'Atributo desconhecido.'
+PARSER_MULTI_TAG = 'Não suporta múltiplos atributos.'
+PARSER_UNEXPECT_LFUNC_NAME = 'A função local só pode usar identificadores como nome.'
+PARSER_UNEXPECT_EFUNC_NAME = 'Função como expressão não pode ser nomeada.'
+PARSER_ERR_LCOMMENT_END = 'Anotações em múltiplas linhas devem ser fechadas por `{symbol}` .'
+PARSER_ERR_C_LONG_COMMENT = 'Lua deve usar `--[[ ]]` para anotações em múltiplas linhas.'
+PARSER_ERR_LSTRING_END = 'String longa deve ser fechada por `{symbol}` .'
+PARSER_ERR_ASSIGN_AS_EQ = 'Deveria usar `=` para atribuição.'
+PARSER_ERR_EQ_AS_ASSIGN = 'Deveria usar `==` para comparação de igualdade.'
+PARSER_ERR_UEQ = 'Deveria usar `~=` para comparação de desigualdade.'
+PARSER_ERR_THEN_AS_DO = 'Deveria usar `then` .'
+PARSER_ERR_DO_AS_THEN = 'Deveria usar `do` .'
+PARSER_MISS_END = 'Falta o `end` correspondente.'
+PARSER_ERR_COMMENT_PREFIX = 'Lua usa `--` para anotações/comentários.'
+PARSER_MISS_SEP_IN_TABLE = 'Falta o símbolo `,` ou `;` .'
+PARSER_SET_CONST = 'Atribuição à variável constante.'
+PARSER_UNICODE_NAME = 'Contém caracteres Unicode.'
+PARSER_ERR_NONSTANDARD_SYMBOL = 'Deveria usar `{symbol}`.'
+PARSER_MISS_SPACE_BETWEEN = 'Devem ser deixados espaços entre símbolos.'
+PARSER_INDEX_IN_FUNC_NAME = 'A forma `[name]` não pode ser usada em nome de uma função nomeada.'
+PARSER_UNKNOWN_ATTRIBUTE = 'Atributo local deve ser `const` ou `close`'
+
+PARSER_LUADOC_MISS_CLASS_NAME = 'Esperado <class name>.'
+PARSER_LUADOC_MISS_EXTENDS_SYMBOL = 'Esperado `:`.'
+PARSER_LUADOC_MISS_CLASS_EXTENDS_NAME = 'Esperado <class extends name>.'
+PARSER_LUADOC_MISS_SYMBOL = 'Esperado `{symbol}`.'
+PARSER_LUADOC_MISS_ARG_NAME = 'Esperado <arg name>.'
+PARSER_LUADOC_MISS_TYPE_NAME = 'Esperado <type name>.'
+PARSER_LUADOC_MISS_ALIAS_NAME = 'Esperado <alias name>.'
+PARSER_LUADOC_MISS_ALIAS_EXTENDS = 'Esperado <alias extends>.'
+PARSER_LUADOC_MISS_PARAM_NAME = 'Esperado <param name>.'
+PARSER_LUADOC_MISS_PARAM_EXTENDS = 'Esperado <param extends>.'
+PARSER_LUADOC_MISS_FIELD_NAME = 'Esperado <field name>.'
+PARSER_LUADOC_MISS_FIELD_EXTENDS = 'Esperado <field extends>.'
+PARSER_LUADOC_MISS_GENERIC_NAME = 'Esperado <generic name>.'
+PARSER_LUADOC_MISS_GENERIC_EXTENDS_NAME = 'Esperado <generic extends name>.'
+PARSER_LUADOC_MISS_VARARG_TYPE = 'Esperado <vararg type>.'
+PARSER_LUADOC_MISS_FUN_AFTER_OVERLOAD = 'Esperado `fun`.'
+PARSER_LUADOC_MISS_CATE_NAME = 'Esperado <doc name>.'
+PARSER_LUADOC_MISS_DIAG_MODE = 'Esperado <diagnostic mode>.'
+PARSER_LUADOC_ERROR_DIAG_MODE = '<diagnostic mode> incorreto.'
+
+SYMBOL_ANONYMOUS = '<Anonymous>'
+
+HOVER_VIEW_DOCUMENTS = 'Visualizar documentos'
+
+HOVER_DOCUMENT_LUA51 = 'http://www.lua.org/manual/5.1/manual.html#{}'
+HOVER_DOCUMENT_LUA52 = 'http://www.lua.org/manual/5.2/manual.html#{}'
+HOVER_DOCUMENT_LUA53 = 'http://www.lua.org/manual/5.3/manual.html#{}'
+HOVER_DOCUMENT_LUA54 = 'http://www.lua.org/manual/5.4/manual.html#{}'
+HOVER_DOCUMENT_LUAJIT = 'http://www.lua.org/manual/5.1/manual.html#{}'
+
+
+HOVER_NATIVE_DOCUMENT_LUA51 = 'command:extension.lua.doc?["en-us/51/manual.html/{}"]'
+HOVER_NATIVE_DOCUMENT_LUA52 = 'command:extension.lua.doc?["en-us/52/manual.html/{}"]'
+HOVER_NATIVE_DOCUMENT_LUA53 = 'command:extension.lua.doc?["en-us/53/manual.html/{}"]'
+HOVER_NATIVE_DOCUMENT_LUA54 = 'command:extension.lua.doc?["en-us/54/manual.html/{}"]'
+HOVER_NATIVE_DOCUMENT_LUAJIT = 'command:extension.lua.doc?["en-us/51/manual.html/{}"]'
+
+HOVER_MULTI_PROTOTYPE = '({} protótipos)'
+HOVER_STRING_BYTES = '{} bytes'
+HOVER_STRING_CHARACTERS = '{} bytes, {} caracteres'
+HOVER_MULTI_DEF_PROTO = '({} definições., {} protótipos)'
+HOVER_MULTI_PROTO_NOT_FUNC = '({} definição não funcional)'
+
+HOVER_USE_LUA_PATH = '(Caminho de busca: `{}`)'
+HOVER_EXTENDS = 'Expande para {}'
+HOVER_TABLE_TIME_UP = 'Inferência de tipo parcial foi desativada por motivos de desempenho.'
+HOVER_WS_LOADING = 'Carregando espaço de trabalho: {} / {}'
+
+ACTION_DISABLE_DIAG = 'Desativar diagnósticos no espaço de trabalho ({}).'
+ACTION_MARK_GLOBAL = 'Marque `{}` como definição global.'
+ACTION_REMOVE_SPACE = 'Limpe todos os espaços desnecessários.'
+ACTION_ADD_SEMICOLON = 'Adicione `;` .'
+ACTION_ADD_BRACKETS = 'Adicione colchetes.'
+ACTION_RUNTIME_VERSION = 'Altere a versão de tempo de execução para {}.'
+ACTION_OPEN_LIBRARY = 'Carregue variáveis globais de {}.'
+ACTION_ADD_DO_END = 'Adicione `do ... end`.'
+ACTION_FIX_LCOMMENT_END = 'Modifique para o símbolo de fechamento de anotação/comentário de múltiplas linhas correto.'
+ACTION_ADD_LCOMMENT_END = 'Feche as anotações/comentário de múltiplas linhas.'
+ACTION_FIX_C_LONG_COMMENT = 'Modifique para o formato de anotações/comentários em múltiplas linhas.'
+ACTION_FIX_LSTRING_END = 'Modifique para o símbolo de fechamento de string correta.'
+ACTION_ADD_LSTRING_END = 'Feche a string longa.'
+ACTION_FIX_ASSIGN_AS_EQ = 'Modifique para `=` .'
+ACTION_FIX_EQ_AS_ASSIGN = 'Modifique para `==` .'
+ACTION_FIX_UEQ = 'Modifique para `~=` .'
+ACTION_FIX_THEN_AS_DO = 'Modifique para `then` .'
+ACTION_FIX_DO_AS_THEN = 'Modifique para `do` .'
+ACTION_ADD_END = 'Adicione `end` (Adiciona marcação de fim com base na identação).'
+ACTION_FIX_COMMENT_PREFIX = 'Modifique para `--` .'
+ACTION_FIX_NONSTANDARD_SYMBOL = 'Modifique para `{symbol}` .'
+ACTION_RUNTIME_UNICODE_NAME = 'Permite caracteres Unicode.'
+ACTION_SWAP_PARAMS = 'Mude para o parâmetro {index} de `{node}`.'
+ACTION_FIX_INSERT_SPACE = 'Insira espaço.'
+ACTION_JSON_TO_LUA = 'Converte de JSON para Lua.'
+ACTION_DISABLE_DIAG_LINE= 'Desativa diagnósticos nesta linha ({}).'
+ACTION_DISABLE_DIAG_FILE= 'Desativa diagnósticos nesta linha ({}).'
+
+COMMAND_DISABLE_DIAG = 'Desativar diagnósticos.'
+COMMAND_MARK_GLOBAL = 'Marca como variável global.'
+COMMAND_REMOVE_SPACE = 'Limpa todos os espaços desnecessários.'
+COMMAND_ADD_BRACKETS = 'Adiciona colchetes.'
+COMMAND_RUNTIME_VERSION = 'Altera a versão de tempo de execução.'
+COMMAND_OPEN_LIBRARY = 'Carrega variáveis globais de bibliotecas de terceiros.'
+COMMAND_UNICODE_NAME = 'Permite caracteres Unicode.'
+COMMAND_JSON_TO_LUA = 'Converte de JSON para Lua.'
+COMMAND_JSON_TO_LUA_FAILED = 'Converção de JSON para Lua falhou: {}.'
+
+COMPLETION_IMPORT_FROM = 'Importa de {}.'
+COMPLETION_DISABLE_AUTO_REQUIRE = 'Desativa auto require.'
+COMPLETION_ASK_AUTO_REQUIRE = 'Adicione o código na parte superior do arquivo como auto require?'
+
+DEBUG_MEMORY_LEAK = "{} Sinto muito pelo sério vazamento de memória. O serviço de idioma será reiniciado em breve."
+DEBUG_RESTART_NOW = 'Reinicie agora'
+
+WINDOW_COMPILING = 'Compilando'
+WINDOW_DIAGNOSING = 'Realizando diagnóstico'
+WINDOW_INITIALIZING = 'Inicializando...'
+WINDOW_PROCESSING_HOVER = 'Processando hover...'
+WINDOW_PROCESSING_DEFINITION = 'Processando definições...'
+WINDOW_PROCESSING_REFERENCE = 'Processando referências...'
+WINDOW_PROCESSING_RENAME = 'Processando renomeações...'
+WINDOW_PROCESSING_COMPLETION = 'Processando finalizações...'
+WINDOW_PROCESSING_SIGNATURE = 'Processando ajuda de assinatura...'
+WINDOW_PROCESSING_SYMBOL = 'Processando símbolos do arquivo...'
+WINDOW_PROCESSING_WS_SYMBOL = 'Processando símbolos do espaço de trabalho...'
+WINDOW_PROCESSING_SEMANTIC_FULL = 'Processando tokens semânticas completos...'
+WINDOW_PROCESSING_SEMANTIC_RANGE = 'Processando tokens semânticas incrementais...'
+WINDOW_PROCESSING_TYPE_HINT = 'Processando dicas de lina...'
+WINDOW_INCREASE_UPPER_LIMIT = 'Aumente o limite superior'
+WINDOW_CLOSE = 'Fechar'
+WINDOW_SETTING_WS_DIAGNOSTIC = 'Você pode atrasar ou desativar os diagnósticos do espaço de trabalho nas configurações'
+WINDOW_DONT_SHOW_AGAIN = 'Não mostre novamente'
+WINDOW_DELAY_WS_DIAGNOSTIC = 'Diagnóstico de tempo ocioso (atraso de {} segundos)'
+WINDOW_DISABLE_DIAGNOSTIC = 'Desativa diagnósticos do espaço de trabalho'
+WINDOW_LUA_STATUS = [[
+Área de trabalho : {ws}
+Arquivos em cache: {ast}/{max}
+Uso de memória: {mem:.f}M
+]]
+WINDOW_APPLY_SETTING = 'Aplicar configuração'
+WINDOW_CHECK_SEMANTIC = 'Se você estiver usando o tema de cores do market, talvez seja necessário modificar `editor.semanticHighlighting.enabled` para `true` para fazer com tokens semânticas sejam habilitados.'
+WINDOW_TELEMETRY_HINT = 'Por favor, permita o envio de dados de uso e relatórios de erro anônimos para nos ajudar a melhorar ainda mais essa extensão. Leia nossa política de privacidade [aqui](https://github.com/sumneko/lua-language-server/wiki/Privacy-Policy) .'
+WINDOW_TELEMETRY_ENABLE = 'Permitir'
+WINDOW_TELEMETRY_DISABLE = 'Desabilitar'
+WINDOW_CLIENT_NOT_SUPPORT_CONFIG = 'Seu cliente não suporta configurações de modificação do lado do servidor, modifique manualmente as seguintes configurações:'
+WINDOW_LCONFIG_NOT_SUPPORT_CONFIG= 'A modificação automática de configurações locais não é suportada atualmente, modifique manualmente as seguintes configurações:'
+WINDOW_MANUAL_CONFIG_ADD = '`{key}`: adiciona o elemento `{value:q}` ;'
+WINDOW_MANUAL_CONFIG_SET = '`{key}`: defini como `{value:q}` ;'
+WINDOW_MANUAL_CONFIG_PROP = '`{key}`: define a propriedade `{prop}` para `{value:q}`;'
+WINDOW_APPLY_WHIT_SETTING = 'Aplicar e modificar configurações'
+WINDOW_APPLY_WHITOUT_SETTING = 'Aplicar mas não modificar configurações'
+WINDOW_ASK_APPLY_LIBRARY = 'Você precisa configurar seu ambiente de trabalho como `{}`?'
+
+CONFIG_LOAD_FAILED = 'Não é possível ler o arquivo de configurações: {}'
+CONFIG_LOAD_ERROR = 'Configurando o erro de carregamento do arquivo: {}'
+CONFIG_TYPE_ERROR = 'O arquivo de configuração deve estar no formato LUA ou JSON: {}'
+
+PLUGIN_RUNTIME_ERROR = [[
+Ocorreu um erro no plugin, envie o erro ao autor do plugin.
+Por favor, verifique os detalhes na saída ou log.
+Caminho do plugin: {}
+]]
+PLUGIN_TRUST_LOAD = [[
+As configurações atuais tentam carregar o plugin neste local: {}
+
+Note que plugins mal-intencionados podem prejudicar seu computador
+]]
+PLUGIN_TRUST_YES = [[
+Confie e carregue este plugin
+]]
+PLUGIN_TRUST_NO = [[
+Não carregue este plugin
+]]
diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua
index 6f27176c..89ade0e8 100644
--- a/locale/zh-cn/script.lua
+++ b/locale/zh-cn/script.lua
@@ -45,6 +45,7 @@ DIAG_DIFFERENT_REQUIRES = '使用了不同的名字 require 了同一个文件
DIAG_REDUNDANT_RETURN = '冗余返回。'
DIAG_AWAIT_IN_SYNC = '只能在标记为异步的函数中调用异步函数。'
DIAG_NOT_YIELDABLE = '此函数的第 {} 个参数没有被标记为可让出,但是传入了异步函数。(使用 `---@param name async fun()` 来标记为可让出)'
+DIAG_DISCARD_RETURNS = '不能丢弃此函数的返回值。'
DIAG_CIRCLE_DOC_CLASS = '循环继承的类。'
DIAG_DOC_FIELD_NO_CLASS = '字段必须定义在类之后。'
diff --git a/main.lua b/main.lua
index ab7c8e83..4fa302ac 100644
--- a/main.lua
+++ b/main.lua
@@ -56,6 +56,6 @@ require 'tracy'
xpcall(dofile, log.debug, (ROOT / 'debugger.lua'):string())
-local service = require 'service'
+local _, service = xpcall(require, log.error, 'service')
service.start()
diff --git a/meta/template/basic.lua b/meta/template/basic.lua
index 5665dc59..6c3f7d46 100644
--- a/meta/template/basic.lua
+++ b/meta/template/basic.lua
@@ -57,11 +57,13 @@ _G = {}
---#DES 'getfenv'
---@param f? function
---@return table
+---@nodiscard
function getfenv(f) end
---#DES 'getmetatable'
---@param object any
---@return table metatable
+---@nodiscard
function getmetatable(object) end
---#DES 'ipairs'
@@ -83,6 +85,7 @@ function ipairs(t) end
---@param chunkname? string
---@return function
---@return string error_message
+---@nodiscard
function load(func, chunkname) end
---#else
---#DES 'load>5.2'
@@ -92,6 +95,7 @@ function load(func, chunkname) end
---@param env? table
---@return function
---@return string error_message
+---@nodiscard
function load(chunk, chunkname, mode, env) end
---#end
@@ -100,6 +104,7 @@ function load(chunk, chunkname, mode, env) end
---@param filename? string
---@return function
---@return string error_message
+---@nodiscard
function loadfile(filename) end
---#else
---#DES 'loadfile'
@@ -108,6 +113,7 @@ function loadfile(filename) end
---@param env? table
---@return function
---@return string error_message
+---@nodiscard
function loadfile(filename, mode, env) end
---#end
@@ -117,6 +123,7 @@ function loadfile(filename, mode, env) end
---@param chunkname? string
---@return function
---@return string error_message
+---@nodiscard
function loadstring(text, chunkname) end
---@version 5.1
@@ -130,6 +137,7 @@ function module(name, ...) end
---@param index? K
---@return K
---@return V
+---@nodiscard
function next(table, index) end
---#DES 'pairs'
@@ -154,17 +162,20 @@ function print(...) end
---@param v1 any
---@param v2 any
---@return boolean
+---@nodiscard
function rawequal(v1, v2) end
---#DES 'rawget'
---@param table table
---@param index any
---@return any
+---@nodiscard
function rawget(table, index) end
---#DES 'rawlen'
---@param v table|string
---@return integer len
+---@nodiscard
function rawlen(v) end
---#DES 'rawset'
@@ -177,6 +188,7 @@ function rawset(table, index, value) end
---#DES 'select'
---@param index integer|'"#"'
---@return any
+---@nodiscard
function select(index, ...) end
---@version 5.1
@@ -196,11 +208,13 @@ function setmetatable(table, metatable) end
---@param e string|number
---@param base? integer
---@return number?
+---@nodiscard
function tonumber(e, base) end
---#DES 'tostring'
---@param v any
---@return string
+---@nodiscard
function tostring(v) end
---@alias type
@@ -216,6 +230,7 @@ function tostring(v) end
---#DES 'type'
---@param v any
---@return type type
+---@nodiscard
function type(v) end
---#DES '_VERSION'
@@ -258,4 +273,5 @@ function xpcall(f, msgh, arg1, ...) end
---@param list table
---@param i? integer
---@param j? integer
+---@nodiscard
function unpack(list, i, j) end
diff --git a/meta/template/bit.lua b/meta/template/bit.lua
index d7cfd302..57bf6d31 100644
--- a/meta/template/bit.lua
+++ b/meta/template/bit.lua
@@ -7,62 +7,74 @@ bit = {}
---@param x integer
---@return integer y
+---@nodiscard
function bit.tobit(x) end
---@param x integer
---@param n? integer
---@return integer y
+---@nodiscard
function bit.tohex(x, n) end
---@param x integer
---@return integer y
+---@nodiscard
function bit.bnot(x) end
---@param x integer
---@param x2 integer
---@vararg integer
---@return integer y
+---@nodiscard
function bit.bor(x, x2, ...) end
---@param x integer
---@param x2 integer
---@vararg integer
---@return integer y
+---@nodiscard
function bit.band(x, x2, ...) end
---@param x integer
---@param x2 integer
---@vararg integer
---@return integer y
+---@nodiscard
function bit.bxor(x, x2, ...) end
---@param x integer
---@param n integer
---@return integer y
+---@nodiscard
function bit.lshift(x, n) end
---@param x integer
---@param n integer
---@return integer y
+---@nodiscard
function bit.rshift(x, n) end
---@param x integer
---@param n integer
---@return integer y
+---@nodiscard
function bit.arshift(x, n) end
---@param x integer
---@param n integer
---@return integer y
+---@nodiscard
function bit.rol(x, n) end
---@param x integer
---@param n integer
---@return integer y
+---@nodiscard
function bit.ror(x, n) end
---@param x integer
---@return integer y
+---@nodiscard
function bit.bswap(x) end
return bit
diff --git a/meta/template/bit32.lua b/meta/template/bit32.lua
index 85bd04f1..bcb39c66 100644
--- a/meta/template/bit32.lua
+++ b/meta/template/bit32.lua
@@ -10,27 +10,33 @@ bit32 = {}
---@param x integer
---@param disp integer
---@return integer
+---@nodiscard
function bit32.arshift(x, disp) end
---#DES 'bit32.band'
---@return integer
+---@nodiscard
function bit32.band(...) end
---#DES 'bit32.bnot'
---@param x integer
---@return integer
+---@nodiscard
function bit32.bnot(x) end
---#DES 'bit32.bor'
---@return integer
+---@nodiscard
function bit32.bor(...) end
---#DES 'bit32.btest'
---@return boolean
+---@nodiscard
function bit32.btest(...) end
---#DES 'bit32.bxor'
---@return integer
+---@nodiscard
function bit32.bxor(...) end
---#DES 'bit32.extract'
@@ -38,6 +44,7 @@ function bit32.bxor(...) end
---@param field integer
---@param width? integer
---@return integer
+---@nodiscard
function bit32.extract(n, field, width) end
---#DES 'bit32.replace'
@@ -45,30 +52,35 @@ function bit32.extract(n, field, width) end
---@param v integer
---@param field integer
---@param width? integer
+---@nodiscard
function bit32.replace(n, v, field, width) end
---#DES 'bit32.lrotate'
---@param x integer
---@param distp integer
---@return integer
+---@nodiscard
function bit32.lrotate(x, distp) end
---#DES 'bit32.lshift'
---@param x integer
---@param distp integer
---@return integer
+---@nodiscard
function bit32.lshift(x, distp) end
---#DES 'bit32.rrotate'
---@param x integer
---@param distp integer
---@return integer
+---@nodiscard
function bit32.rrotate(x, distp) end
---#DES 'bit32.rshift'
---@param x integer
---@param distp integer
---@return integer
+---@nodiscard
function bit32.rshift(x, distp) end
return bit32
diff --git a/meta/template/coroutine.lua b/meta/template/coroutine.lua
index 7d8e2cb2..a9dd40cf 100644
--- a/meta/template/coroutine.lua
+++ b/meta/template/coroutine.lua
@@ -7,16 +7,19 @@ coroutine = {}
---#DES 'coroutine.create'
---@param f function
---@return thread
+---@nodiscard
function coroutine.create(f) end
---#if VERSION >= 5.4 then
---#DES 'coroutine.isyieldable>5.4'
---@param co? thread
---@return boolean
+---@nodiscard
function coroutine.isyieldable(co) end
---#else
---#DES 'coroutine.isyieldable'
---@return boolean
+---@nodiscard
function coroutine.isyieldable() end
---#end
@@ -38,6 +41,7 @@ function coroutine.resume(co, val1, ...) end
---#DES 'coroutine.running'
---@return thread running
---@return boolean ismain
+---@nodiscard
function coroutine.running() end
---#DES 'coroutine.status'
@@ -47,11 +51,13 @@ function coroutine.running() end
---| '"suspended"' # ---#DESTAIL 'costatus.suspended'
---| '"normal"' # ---#DESTAIL 'costatus.normal'
---| '"dead"' # ---#DESTAIL 'costatus.dead'
+---@nodiscard
function coroutine.status(co) end
---#DES 'coroutine.wrap'
---@param f function
---@return fun(...):...
+---@nodiscard
function coroutine.wrap(f) end
---#DES 'coroutine.yield'
diff --git a/meta/template/debug.lua b/meta/template/debug.lua
index 2c72263f..3f8a91a4 100644
--- a/meta/template/debug.lua
+++ b/meta/template/debug.lua
@@ -33,6 +33,7 @@ function debug.debug() end
---#DES 'debug.getfenv'
---@param o any
---@return table
+---@nodiscard
function debug.getfenv(o) end
---#DES 'debug.gethook'
@@ -40,6 +41,7 @@ function debug.getfenv(o) end
---@return function hook
---@return string mask
---@return integer count
+---@nodiscard
function debug.gethook(co) end
---@alias infowhat string
@@ -64,6 +66,7 @@ function debug.gethook(co) end
---@param f integer|function
---@param what? infowhat
---@return debuginfo
+---@nodiscard
function debug.getinfo(thread, f, what) end
---#if VERSION <= 5.1 and not JIT then
@@ -74,6 +77,7 @@ function debug.getinfo(thread, f, what) end
---@param index integer
---@return string name
---@return any value
+---@nodiscard
function debug.getlocal(thread, level, index) end
---#else
---#DES 'debug.getlocal>5.2'
@@ -83,16 +87,19 @@ function debug.getlocal(thread, level, index) end
---@param index integer
---@return string name
---@return any value
+---@nodiscard
function debug.getlocal(thread, f, index) end
---#end
---#DES 'debug.getmetatable'
---@param object any
---@return table metatable
+---@nodiscard
function debug.getmetatable(object) end
---#DES 'debug.getregistry'
---@return table
+---@nodiscard
function debug.getregistry() end
---#DES 'debug.getupvalue'
@@ -100,6 +107,7 @@ function debug.getregistry() end
---@param up integer
---@return string name
---@return any value
+---@nodiscard
function debug.getupvalue(f, up) end
---#if VERSION >= 5.4 then
@@ -108,11 +116,13 @@ function debug.getupvalue(f, up) end
---@param n integer
---@return any
---@return boolean
+---@nodiscard
function debug.getuservalue(u, n) end
---#elseif VERSION >= 5.2 or JIT then
---#DES 'debug.getuservalue<5.3'
---@param u userdata
---@return any
+---@nodiscard
function debug.getuservalue(u) end
---#end
@@ -187,6 +197,7 @@ function debug.setuservalue(udata, value) end
---@param message? any
---@param level? integer
---@return string message
+---@nodiscard
function debug.traceback(thread, message, level) end
---@version >5.2, JIT
@@ -194,6 +205,7 @@ function debug.traceback(thread, message, level) end
---@param f function
---@param n integer
---@return lightuserdata id
+---@nodiscard
function debug.upvalueid(f, n) end
---@version >5.2, JIT
diff --git a/meta/template/ffi.lua b/meta/template/ffi.lua
index 97dd4bc2..833232d4 100644
--- a/meta/template/ffi.lua
+++ b/meta/template/ffi.lua
@@ -26,21 +26,24 @@ function ffi.cdef(def) end
---@param name string
---@param global? boolean
---@return ffi.namespace* clib
+---@nodiscard
function ffi.load(name, global) end
---@param ct ffi.ct*
---@param nelem? integer
---@param init? any
---@return ffi.cdata* cdata
+---@nodiscard
function ffi.new(ct, nelem, init, ...) end
---@param nelem? integer
---@param init? any
---@return ffi.cdata* cdata
-function ctype(nelem, init, ...) end
+function ffi.ctype(nelem, init, ...) end
---@param ct ffi.ct*
---@return ffi.ctype* ctype
+---@nodiscard
function ffi.typeof(ct) end
---@param ct ffi.ct*
@@ -61,10 +64,12 @@ function ffi.gc(cdata, finalizer) end
---@param ct ffi.ct*
---@param nelem? integer
---@return integer|nil size
+---@nodiscard
function ffi.sizeof(ct, nelem) end
---@param ct ffi.ct*
---@return integer align
+---@nodiscard
function ffi.alignof(ct) end
---@param ct ffi.ct*
@@ -72,15 +77,18 @@ function ffi.alignof(ct) end
---@return integer ofs
---@return integer? bpos
---@return integer? bsize
+---@nodiscard
function ffi.offsetof(ct, field) end
---@param ct ffi.ct*
---@param obj any
---@return boolean status
+---@nodiscard
function ffi.istype(ct, obj) end
---@param newerr? integer
---@return integer err
+---@nodiscard
function ffi.errno(newerr) end
---@param ptr any
diff --git a/meta/template/io.lua b/meta/template/io.lua
index d31027af..1af572b6 100644
--- a/meta/template/io.lua
+++ b/meta/template/io.lua
@@ -50,6 +50,7 @@ function io.lines(filename, ...) end
---@param mode openmode
---@return file*?
---@return string? errmsg
+---@nodiscard
function io.open(filename, mode) end
---#DES 'io.output'
@@ -72,10 +73,12 @@ function io.popen(prog, mode) end
---@vararg readmode
---@return string|number
---@return ...
+---@nodiscard
function io.read(...) end
---#DES 'io.tmpfile'
---@return file*
+---@nodiscard
function io.tmpfile() end
---@alias filetype
@@ -86,6 +89,7 @@ function io.tmpfile() end
---#DES 'io.type'
---@param file file*
---@return filetype
+---@nodiscard
function io.type(file) end
---#DES 'io.write'
@@ -131,6 +135,7 @@ function file:lines(...) end
---#DES 'file:read'
---@vararg readmode
---@return string|number
+---@nodiscard
function file:read(...) end
---@alias seekwhence
diff --git a/meta/template/jit.lua b/meta/template/jit.lua
index f5571cb7..6397505e 100644
--- a/meta/template/jit.lua
+++ b/meta/template/jit.lua
@@ -27,6 +27,7 @@ function jit.flush(func, recursive) end
---@return boolean status
---@return ...
+---@nodiscard
function jit.status() end
return jit
diff --git a/meta/template/math.lua b/meta/template/math.lua
index e415bae6..67c76ff4 100644
--- a/meta/template/math.lua
+++ b/meta/template/math.lua
@@ -17,28 +17,33 @@ math = {}
---#DES 'math.abs'
---@param x number
---@return number
+---@nodiscard
function math.abs(x) end
---#DES 'math.acos'
---@param x number
---@return number
+---@nodiscard
function math.acos(x) end
---#DES 'math.asin'
---@param x number
---@return number
+---@nodiscard
function math.asin(x) end
---#if VERSION <= 5.2 then
---#DES 'math.atan<5.2'
---@param y number
---@return number
+---@nodiscard
function math.atan(y) end
---#else
---#DES 'math.atan>5.3'
---@param y number
---@param x? number
---@return number
+---@nodiscard
function math.atan(y, x) end
---#end
@@ -47,42 +52,50 @@ function math.atan(y, x) end
---@param y number
---@param x number
---@return number
+---@nodiscard
function math.atan2(y, x) end
---#DES 'math.ceil'
---@param x number
---@return integer
+---@nodiscard
function math.ceil(x) end
---#DES 'math.cos'
---@param x number
+---@nodiscard
function math.cos(x) end
---@version <5.2
---#DES 'math.cosh'
---@param x number
---@return number
+---@nodiscard
function math.cosh(x) end
---#DES 'math.deg'
---@param x number
---@return number
+---@nodiscard
function math.deg(x) end
---#DES 'math.exp'
---@param x number
---@return number
+---@nodiscard
function math.exp(x) end
---#DES 'math.floor'
---@param x number
---@return number
+---@nodiscard
function math.floor(x) end
---#DES 'math.fmod'
---@param x number
---@param y number
---@return number
+---@nodiscard
function math.fmod(x, y) end
---@version <5.2
@@ -90,6 +103,7 @@ function math.fmod(x, y) end
---@param x number
---@return number m
---@return number e
+---@nodiscard
function math.frexp(x) end
---@version <5.2
@@ -97,18 +111,21 @@ function math.frexp(x) end
---@param m number
---@param e number
---@return number
+---@nodiscard
function math.ldexp(m, e) end
---#if VERSION <= 5.1 and not JIT then
---#DES 'math.log<5.1'
---@param x number
---@return number
+---@nodiscard
function math.log(x) end
---#else
---#DES 'math.log>5.2'
---@param x number
---@param base? integer
---@return number
+---@nodiscard
function math.log(x, base) end
---#end
@@ -116,24 +133,28 @@ function math.log(x, base) end
---#DES 'math.log10'
---@param x number
---@return number
+---@nodiscard
function math.log10(x) end
---#DES 'math.max'
---@param x number
---@vararg number
---@return number
+---@nodiscard
function math.max(x, ...) end
---#DES 'math.min'
---@param x number
---@vararg number
---@return number
+---@nodiscard
function math.min(x, ...) end
---#DES 'math.modf'
---@param x number
---@return integer
---@return number
+---@nodiscard
function math.modf(x) end
---@version <5.2
@@ -141,11 +162,13 @@ function math.modf(x) end
---@param x number
---@param y number
---@return number
+---@nodiscard
function math.pow(x, y) end
---#DES 'math.rad'
---@param x number
---@return number
+---@nodiscard
function math.rad(x) end
---#DES 'math.random'
@@ -154,50 +177,59 @@ function math.rad(x) end
---@param m integer
---@param n integer
---@return integer
+---@nodiscard
function math.random(m, n) end
---#if VERSION >= 5.4 then
---#DES 'math.randomseed>5.4'
---@param x? integer
---@param y? integer
+---@nodiscard
function math.randomseed(x, y) end
---#else
---#DES 'math.randomseed<5.3'
---@param x integer
+---@nodiscard
function math.randomseed(x) end
---#end
---#DES 'math.sin'
---@param x number
---@return number
+---@nodiscard
function math.sin(x) end
---@version <5.2
---#DES 'math.sinh'
---@param x number
---@return number
+---@nodiscard
function math.sinh(x) end
---#DES 'math.sqrt'
---@param x number
---@return number
+---@nodiscard
function math.sqrt(x) end
---#DES 'math.tan'
---@param x number
---@return number
+---@nodiscard
function math.tan(x) end
---@version <5.2
---#DES 'math.tanh'
---@param x number
---@return number
+---@nodiscard
function math.tanh(x) end
---@version >5.3
---#DES 'math.tointeger'
---@param x number
---@return integer?
+---@nodiscard
function math.tointeger(x) end
---#DES 'math.type'
@@ -206,12 +238,14 @@ function math.tointeger(x) end
---| '"integer"'
---| '"float"'
---| 'nil'
+---@nodiscard
function math.type(x) end
---#DES 'math.ult'
---@param m integer
---@param n integer
---@return boolean
+---@nodiscard
function math.ult(m, n) end
return math
diff --git a/meta/template/os.lua b/meta/template/os.lua
index 4347076c..af9b3278 100644
--- a/meta/template/os.lua
+++ b/meta/template/os.lua
@@ -6,6 +6,7 @@ os = {}
---#DES 'os.clock'
---@return number
+---@nodiscard
function os.clock() end
---@class osdate
@@ -32,12 +33,14 @@ function os.clock() end
---@param format? string
---@param time? integer
---@return string|osdate
+---@nodiscard
function os.date(format, time) end
---#DES 'os.difftime'
---@param t2 integer
---@param t1 integer
---@return integer
+---@nodiscard
function os.difftime(t2, t1) end
---#DES 'os.execute'
@@ -67,6 +70,7 @@ function os.exit(code, close) end
---#DES 'os.getenv'
---@param varname string
---@return string
+---@nodiscard
function os.getenv(varname) end
---#DES 'os.remove'
@@ -99,10 +103,12 @@ function os.setlocale(locale, category) end
---#DES 'os.time'
---@param date? osdate
---@return integer
+---@nodiscard
function os.time(date) end
---#DES 'os.tmpname'
---@return string
+---@nodiscard
function os.tmpname() end
return os
diff --git a/meta/template/package.lua b/meta/template/package.lua
index 0b2c8c1b..5c08bbef 100644
--- a/meta/template/package.lua
+++ b/meta/template/package.lua
@@ -55,6 +55,7 @@ package.searchers = {}
---@param rep? string
---@return string? filename
---@return string? errmsg
+---@nodiscard
function package.searchpath(name, path, sep, rep) end
---#DES 'package.seeall'
diff --git a/meta/template/string.lua b/meta/template/string.lua
index c06570e8..97bae481 100644
--- a/meta/template/string.lua
+++ b/meta/template/string.lua
@@ -10,6 +10,7 @@ string = {}
---@param j? integer
---@return integer
---@return ...
+---@nodiscard
function string.byte(s, i, j) end
---#DES 'string.char'
@@ -17,12 +18,14 @@ function string.byte(s, i, j) end
---@vararg integer
---@return string
---@return ...
+---@nodiscard
function string.char(byte, ...) end
---#DES 'string.dump'
---@param f function
---@param strip? boolean
---@return string
+---@nodiscard
function string.dump(f, strip) end
---#DES 'string.find'
@@ -33,12 +36,14 @@ function string.dump(f, strip) end
---@return integer start
---@return integer end
---@return ... captured
+---@nodiscard
function string.find(s, pattern, init, plain) end
---#DES 'string.format'
---@param s string
---@vararg string
---@return string
+---@nodiscard
function string.format(s, ...) end
---#DES 'string.gmatch'
@@ -62,16 +67,19 @@ function string.gmatch(s, pattern, init) end
---@param n integer
---@return string
---@return integer count
+---@nodiscard
function string.gsub(s, pattern, repl, n) end
---#DES 'string.len'
---@param s string
---@return integer
+---@nodiscard
function string.len(s) end
---#DES 'string.lower'
---@param s string
---@return string
+---@nodiscard
function string.lower(s) end
---#DES 'string.match'
@@ -79,6 +87,7 @@ function string.lower(s) end
---@param pattern string
---@param init? integer
---@return string | number captured
+---@nodiscard
function string.match(s, pattern, init) end
---@version >5.3
@@ -88,12 +97,14 @@ function string.match(s, pattern, init) end
---@param v2? string
---@vararg string
---@return string binary
+---@nodiscard
function string.pack(fmt, v1, v2, ...) end
---@version >5.3
---#DES 'string.packsize'
---@param fmt string
---@return integer
+---@nodiscard
function string.packsize(fmt) end
---#if VERSION <= 5.1 and not JIT then
@@ -101,6 +112,7 @@ function string.packsize(fmt) end
---@param s string
---@param n integer
---@return string
+---@nodiscard
function string.rep(s, n) end
---#else
---#DES 'string.rep>5.2'
@@ -108,12 +120,14 @@ function string.rep(s, n) end
---@param n integer
---@param sep? string
---@return string
+---@nodiscard
function string.rep(s, n, sep) end
---#end
---#DES 'string.reverse'
---@param s string
---@return string
+---@nodiscard
function string.reverse(s) end
---#DES 'string.sub'
@@ -121,6 +135,7 @@ function string.reverse(s) end
---@param i integer
---@param j? integer
---@return string
+---@nodiscard
function string.sub(s, i, j) end
---@version >5.3
@@ -130,11 +145,13 @@ function string.sub(s, i, j) end
---@param pos? integer
---@return ...
---@return integer offset
+---@nodiscard
function string.unpack(fmt, s, pos) end
---#DES 'string.upper'
---@param s string
---@return string
+---@nodiscard
function string.upper(s) end
return string
diff --git a/meta/template/table.lua b/meta/template/table.lua
index 12d69c43..c55c3160 100644
--- a/meta/template/table.lua
+++ b/meta/template/table.lua
@@ -10,6 +10,7 @@ table = {}
---@param i? integer
---@param j? integer
---@return string
+---@nodiscard
function table.concat(list, sep, i, j) end
---#DES 'table.insert'
@@ -23,6 +24,7 @@ function table.insert(list, pos, value) end
---#DES 'table.maxn'
---@param table table
---@return integer
+---@nodiscard
function table.maxn(table) end
---@version >5.3
@@ -38,6 +40,7 @@ function table.move(a1, f, e, t, a2) end
---@version >5.2, JIT
---#DES 'table.pack'
---@return table
+---@nodiscard
function table.pack(...) end
---#DES 'table.remove'
@@ -56,6 +59,7 @@ function table.sort(list, comp) end
---@param list table
---@param i? integer
---@param j? integer
+---@nodiscard
function table.unpack(list, i, j) end
return table
diff --git a/meta/template/utf8.lua b/meta/template/utf8.lua
index 43ce9961..d3ff940e 100644
--- a/meta/template/utf8.lua
+++ b/meta/template/utf8.lua
@@ -12,6 +12,7 @@ utf8 = {}
---@param code integer
---@vararg integer
---@return string
+---@nodiscard
function utf8.char(code, ...) end
---#DES 'utf8.codes'
@@ -33,6 +34,7 @@ function utf8.codes(s, lax) end
---@param j? integer
---@return integer code
---@return ...
+---@nodiscard
function utf8.codepoint(s, i, j) end
---#else
---@param s string
@@ -41,6 +43,7 @@ function utf8.codepoint(s, i, j) end
---@param lax? boolean
---@return integer code
---@return ...
+---@nodiscard
function utf8.codepoint(s, i, j, lax) end
---#end
@@ -51,6 +54,7 @@ function utf8.codepoint(s, i, j, lax) end
---@param j? integer
---@return integer?
---@return integer? errpos
+---@nodiscard
function utf8.len(s, i, j) end
---#else
---@param s string
@@ -59,6 +63,7 @@ function utf8.len(s, i, j) end
---@param lax? boolean
---@return integer?
---@return integer? errpos
+---@nodiscard
function utf8.len(s, i, j, lax) end
---#end
@@ -67,6 +72,7 @@ function utf8.len(s, i, j, lax) end
---@param n integer
---@param i integer
---@return integer p
+---@nodiscard
function utf8.offset(s, n, i) end
return utf8
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)
diff --git a/test/completion/common.lua b/test/completion/common.lua
index 4cfd1872..73c6d7e6 100644
--- a/test/completion/common.lua
+++ b/test/completion/common.lua
@@ -2680,3 +2680,13 @@ end
kind = define.CompletionItemKind.Variable,
}
}
+
+TEST [[
+utf<??>'xxx'
+]]
+{
+ [1] = {
+ label = 'utf8',
+ kind = define.CompletionItemKind.Field,
+ }
+}
diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua
index 1d8c4018..96e9e16d 100644
--- a/test/diagnostics/init.lua
+++ b/test/diagnostics/init.lua
@@ -307,7 +307,7 @@ Instance = _G[InstanceName]
]]
TEST [[
-(''):sub(1, 2)
+local _ = (''):sub(1, 2)
]]
TEST [=[
@@ -432,7 +432,7 @@ f(1, 2, 3, 4)
]]
TEST [[
-next({}, 1, <!2!>)
+local _ = next({}, 1, <!2!>)
print(1, 2, 3, 4, 5)
]]
@@ -464,7 +464,7 @@ f(1, 2, 3)
]]
TEST [[
-<!unpack!>()
+local _ = <!unpack!>()
]]
TEST [[
@@ -1354,8 +1354,8 @@ f()
TEST [[
---@type file*
local f
-f:read '*a'
-f:read('*a')
+local _ = f:read '*a'
+local _ = f:read('*a')
]]
TEST [[
@@ -1391,55 +1391,40 @@ end
]]
TEST [[
----@param f async fun()
-function CB(f)
- <!f!>()
+local function f(cb)
+ cb()
end
-]]
-
-TEST [[
-local cb
-cb(function () ---@async
+<!f!>(function () ---@async
return nil
end)
]]
TEST [[
----@param f async fun()
-function CB(f)
- return f
+local function f(cb)
+ pcall(cb)
end
-CB(function () ---@async
+<!f!>(function () ---@async
return nil
end)
]]
TEST [[
-function CB(f)
- return f
+---@nodiscard
+local function f()
+ return 1
end
-<!CB!>(function () ---@async
- return nil
-end)
+<!f()!>
]]
-TEST [[
----@type fun(f: async fun())
-local cb
-
-cb(function () ---@async
- return nil
-end)
-]]
TEST [[
----@type fun(f: fun())
-local cb
+---@nodiscard
+local function f()
+ return 1
+end
-<!cb!>(function () ---@async
- return nil
-end)
+X = f()
]]