From 9b961d011f95a44f9d73443c1f597b78bcf60ac4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Jan 2025 14:29:04 +0000 Subject: [PATCH] feat: add --check_format=json|pretty Adds a new CLI option --check_format which accepts the values: 'json' (current behaviour), and a new 'pretty' value which prints a colorized human readable report to stdout, similar to common compilers and linters. Results are printed with color unless NO_COLOR is defined in the users environment, as per https://no-color.org. If --check_out_path is provided, then the results are always saved to file regardless of the --check_format value. --- changelog.md | 1 + locale/en-us/script.lua | 4 +- locale/ja-jp/script.lua | 4 +- locale/pt-br/script.lua | 4 +- locale/zh-cn/script.lua | 4 +- locale/zh-tw/script.lua | 4 +- script/cli/check_worker.lua | 120 ++++++++++++++++++++++++++++++++---- script/global.d.lua | 3 + 8 files changed, 128 insertions(+), 16 deletions(-) diff --git a/changelog.md b/changelog.md index 313cb53bf..89a2bf6fe 100644 --- a/changelog.md +++ b/changelog.md @@ -30,6 +30,7 @@ cfgs[2] = {} -- only warns missing `b` ``` This enables the previous missing field check behavior before [#2970](https://github.com/LuaLS/lua-language-server/issues/2970) +* `NEW` Added `--check_format=json|pretty` for use with `--check` to output diagnostics in a human readable format. ## 3.13.5 `2024-12-20` diff --git a/locale/en-us/script.lua b/locale/en-us/script.lua index 9c9163ae4..ee96900c7 100644 --- a/locale/en-us/script.lua +++ b/locale/en-us/script.lua @@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS = 'Diagnosis completed, no problems found' CLI_CHECK_PROGRESS = 'Found {} problems in {} files' -CLI_CHECK_RESULTS = +CLI_CHECK_RESULTS_OUTPATH = 'Diagnosis complete, {} problems found, see {}' +CLI_CHECK_RESULTS_PRETTY = +'Diagnosis complete, {} problems found' CLI_CHECK_MULTIPLE_WORKERS = 'Starting {} worker tasks, progress output will be disabled. This may take a few minutes.' CLI_DOC_INITING = diff --git a/locale/ja-jp/script.lua b/locale/ja-jp/script.lua index 3c0cd48d6..6e1819d98 100644 --- a/locale/ja-jp/script.lua +++ b/locale/ja-jp/script.lua @@ -649,8 +649,10 @@ CLI_CHECK_SUCCESS = '診断が完了しました。問題は見つかりませんでした' CLI_CHECK_PROGRESS = '{} ファイルに渡り、{} 個の問題が発見されました' -CLI_CHECK_RESULTS = +CLI_CHECK_RESULTS_OUTPATH = '診断が完了しました。{} 個の問題が発見されました。詳しくは {} をご確認ください' +CLI_CHECK_RESULTS_PRETTY = +'診断が完了しました。{} 個の問題が発見されました' CLI_CHECK_MULTIPLE_WORKERS = '{} 個のワーカータスクを開始しているため、進行状況の出力が無効になります。完了まで数分かかることがあります。' CLI_DOC_INITING = diff --git a/locale/pt-br/script.lua b/locale/pt-br/script.lua index e763fb6c4..73d459d75 100644 --- a/locale/pt-br/script.lua +++ b/locale/pt-br/script.lua @@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS = 'Diagnóstico completo, nenhum problema encontrado' CLI_CHECK_PROGRESS = -- TODO: need translate! 'Found {} problems in {} files' -CLI_CHECK_RESULTS = +CLI_CHECK_RESULTS_OUTPATH = 'Diagnóstico completo, {} problemas encontrados, veja {}' +CLI_CHECK_RESULTS_PRETTY = +'Diagnóstico completo, {} problemas encontrados' CLI_CHECK_MULTIPLE_WORKERS = -- TODO: need translate! 'Starting {} worker tasks, progress output will be disabled. This may take a few minutes.' CLI_DOC_INITING = -- TODO: need translate! diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua index 0b748d84f..22f16eaac 100644 --- a/locale/zh-cn/script.lua +++ b/locale/zh-cn/script.lua @@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS = '诊断完成,没有发现问题' CLI_CHECK_PROGRESS = '检测到问题 {} 在文件 {} 中' -CLI_CHECK_RESULTS = +CLI_CHECK_RESULTS_OUTPATH = '诊断完成,共有 {} 个问题,请查看 {}' +CLI_CHECK_RESULTS_PRETTY = +'诊断完成,共有 {} 个问题' CLI_CHECK_MULTIPLE_WORKERS = '开启 {} 个工作任务,进度输出将会被禁用。这可能会花费几分钟。' CLI_DOC_INITING = diff --git a/locale/zh-tw/script.lua b/locale/zh-tw/script.lua index 31e885208..090fb7ff0 100644 --- a/locale/zh-tw/script.lua +++ b/locale/zh-tw/script.lua @@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS = '診斷完成,沒有發現問題' CLI_CHECK_PROGRESS = -- TODO: need translate! 'Found {} problems in {} files' -CLI_CHECK_RESULTS = +CLI_CHECK_RESULTS_OUTPATH = '診斷完成,共有 {} 個問題,請查看 {}' +CLI_CHECK_RESULTS_PRETTY = +'診斷完成,共有 {} 個問題' CLI_CHECK_MULTIPLE_WORKERS = -- TODO: need translate! 'Starting {} worker tasks, progress output will be disabled. This may take a few minutes.' CLI_DOC_INITING = -- TODO: need translate! diff --git a/script/cli/check_worker.lua b/script/cli/check_worker.lua index a2e0bff11..d3aea85f4 100644 --- a/script/cli/check_worker.lua +++ b/script/cli/check_worker.lua @@ -17,6 +17,96 @@ require 'vm' local export = {} +local colors + +if not os.getenv('NO_COLOR') then + colors = { + red = '\27[31m', + green = '\27[32m', + yellow = '\27[33m', + blue = '\27[34m', + magenta = '\27[35m', + grey = '\27[90m', + reset = '\27[0m' + } +else + colors = { + red = '', + green = '', + yellow = '', + blue = '', + magenta = '', + grey = '', + reset = '' + } +end + +local severity_colors = { + [1] = colors.red, + [2] = colors.yellow, + [3] = colors.blue, + [4] = colors.green, +} + +local severity_str = { + [1] = 'error', + [2] = 'warning', + [3] = 'info', + [4] = 'hint' +} + +---@param path string +---@return string +local function relpath(path) + local pwd = os.getenv('PWD') + if pwd and path:sub(1, #pwd) == pwd then + path = path:sub(#pwd + 2) + end + return path +end + +local function report_pretty(results) + for f, diags in pairs(results) do + local path = relpath(f:match('^file://(.+)$') or f) + + local lines = {} --- @type string[] + pcall(function() + for line in io.lines(path) do + table.insert(lines, line) + end + end) + + for _, d in ipairs(diags) do + local rstart = d.range.start + local rend = d.range['end'] + print( + ('%s%s:%s:%s%s [%s%s%s] %s %s(%s)%s'):format( + colors.blue, + path, + rstart.line, + rstart.character, + colors.reset, + severity_colors[d.severity], + severity_str[d.severity], + colors.reset, + d.message, + colors.magenta, + d.code, + colors.reset + ) + ) + if #lines > 0 then + io.write(lines[rstart.line + 1], '\n') + io.write(colors.grey, (' '):rep(rstart.character), '^') + if rstart.line == rend.line then + io.write(('^'):rep(rend.character - rstart.character - 1)) + end + io.write(colors.reset, '\n') + end + end + end +end + function export.runCLI() lang(LOCALE) @@ -89,14 +179,14 @@ function export.runCLI() -- Downgrade file opened status to Opened for everything to avoid reporting during compilation on files that do not belong to this thread local diagStatus = config.get(rootUri, 'Lua.diagnostics.neededFileStatus') - for diag, status in pairs(diagStatus) do + for d, status in pairs(diagStatus) do if status == 'Any' or status == 'Any!' then - diagStatus[diag] = 'Opened!' + diagStatus[d] = 'Opened!' end end - for diag, status in pairs(protoDiag.getDefaultStatus()) do + for d, status in pairs(protoDiag.getDefaultStatus()) do if status == 'Any' or status == 'Any!' then - diagStatus[diag] = 'Opened!' + diagStatus[d] = 'Opened!' end end config.set(rootUri, 'Lua.diagnostics.neededFileStatus', diagStatus) @@ -134,7 +224,8 @@ function export.runCLI() end end if not QUIET then - io.write('\x0D') + -- Write out empty space to ensure that the progress bar is cleared. + io.write('\x0D', (' '):rep(80), '\x0D') end end) @@ -146,18 +237,25 @@ function export.runCLI() end end - local outpath = CHECK_OUT_PATH - if outpath == nil then - outpath = LOGPATH .. '/check.json' + local outpath = nil + + if CHECK_FORMAT == nil or CHECK_FORMAT == 'pretty' then + report_pretty(results) + end + + if CHECK_FORMAT == 'json' or CHECK_OUT_PATH then + outpath = CHECK_OUT_PATH or LOGPATH .. '/check.json' + -- Always write result, even if it's empty to make sure no one accidentally looks at an old output after a successful run. + util.saveFile(outpath, jsonb.beautify(results)) end - -- Always write result, even if it's empty to make sure no one accidentally looks at an old output after a successful run. - util.saveFile(outpath, jsonb.beautify(results)) if not QUIET then if count == 0 then print(lang.script('CLI_CHECK_SUCCESS')) + elseif outpath then + print(lang.script('CLI_CHECK_RESULTS_OUTPATH', count, outpath)) else - print(lang.script('CLI_CHECK_RESULTS', count, outpath)) + print(lang.script('CLI_CHECK_RESULTS_PRETTY', count)) end end return count == 0 and 0 or 1 diff --git a/script/global.d.lua b/script/global.d.lua index daac5f6c8..f4e4b336b 100644 --- a/script/global.d.lua +++ b/script/global.d.lua @@ -69,6 +69,9 @@ CHECKLEVEL = 'Warning' ---@type string|nil CHECK_OUT_PATH = '' +---@type string | 'json' | 'pretty' +CHECK_FORMAT = 'pretty' + ---@type 'trace' | 'debug' | 'info' | 'warn' | 'error' LOGLEVEL = 'warn'