Skip to content

Commit 1545d8d

Browse files
committed
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.
1 parent 2a7cc44 commit 1545d8d

File tree

9 files changed

+156
-27
lines changed

9 files changed

+156
-27
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
cfgs[2] = {} -- only warns missing `b`
3131
```
3232
This enables the previous missing field check behavior before [#2970](https://github.com/LuaLS/lua-language-server/issues/2970)
33+
* `NEW` Added `--check_format=json|pretty` for use with `--check` to output diagnostics in a human readable format.
3334

3435
## 3.13.5
3536
`2024-12-20`

locale/en-us/script.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS =
648648
'Diagnosis completed, no problems found'
649649
CLI_CHECK_PROGRESS =
650650
'Found {} problems in {} files'
651-
CLI_CHECK_RESULTS =
651+
CLI_CHECK_RESULTS_OUTPATH =
652652
'Diagnosis complete, {} problems found, see {}'
653+
CLI_CHECK_RESULTS_PRETTY =
654+
'Diagnosis complete, {} problems found'
653655
CLI_CHECK_MULTIPLE_WORKERS =
654656
'Starting {} worker tasks, progress output will be disabled. This may take a few minutes.'
655657
CLI_DOC_INITING =

locale/ja-jp/script.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,8 +649,10 @@ CLI_CHECK_SUCCESS =
649649
'診断が完了しました。問題は見つかりませんでした'
650650
CLI_CHECK_PROGRESS =
651651
'{} ファイルに渡り、{} 個の問題が発見されました'
652-
CLI_CHECK_RESULTS =
652+
CLI_CHECK_RESULTS_OUTPATH =
653653
'診断が完了しました。{} 個の問題が発見されました。詳しくは {} をご確認ください'
654+
CLI_CHECK_RESULTS_PRETTY =
655+
'診断が完了しました。{} 個の問題が発見されました'
654656
CLI_CHECK_MULTIPLE_WORKERS =
655657
'{} 個のワーカータスクを開始しているため、進行状況の出力が無効になります。完了まで数分かかることがあります。'
656658
CLI_DOC_INITING =

locale/pt-br/script.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS =
648648
'Diagnóstico completo, nenhum problema encontrado'
649649
CLI_CHECK_PROGRESS = -- TODO: need translate!
650650
'Found {} problems in {} files'
651-
CLI_CHECK_RESULTS =
651+
CLI_CHECK_RESULTS_OUTPATH =
652652
'Diagnóstico completo, {} problemas encontrados, veja {}'
653+
CLI_CHECK_RESULTS_PRETTY =
654+
'Diagnóstico completo, {} problemas encontrados'
653655
CLI_CHECK_MULTIPLE_WORKERS = -- TODO: need translate!
654656
'Starting {} worker tasks, progress output will be disabled. This may take a few minutes.'
655657
CLI_DOC_INITING = -- TODO: need translate!

locale/zh-cn/script.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS =
648648
'诊断完成,没有发现问题'
649649
CLI_CHECK_PROGRESS =
650650
'检测到问题 {} 在文件 {} 中'
651-
CLI_CHECK_RESULTS =
651+
CLI_CHECK_RESULTS_OUTPATH =
652652
'诊断完成,共有 {} 个问题,请查看 {}'
653+
CLI_CHECK_RESULTS_PRETTY =
654+
'诊断完成,共有 {} 个问题'
653655
CLI_CHECK_MULTIPLE_WORKERS =
654656
'开启 {} 个工作任务,进度输出将会被禁用。这可能会花费几分钟。'
655657
CLI_DOC_INITING =

locale/zh-tw/script.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,10 @@ CLI_CHECK_SUCCESS =
648648
'診斷完成,沒有發現問題'
649649
CLI_CHECK_PROGRESS = -- TODO: need translate!
650650
'Found {} problems in {} files'
651-
CLI_CHECK_RESULTS =
651+
CLI_CHECK_RESULTS_OUTPATH =
652652
'診斷完成,共有 {} 個問題,請查看 {}'
653+
CLI_CHECK_RESULTS_PRETTY =
654+
'診斷完成,共有 {} 個問題'
653655
CLI_CHECK_MULTIPLE_WORKERS = -- TODO: need translate!
654656
'Starting {} worker tasks, progress output will be disabled. This may take a few minutes.'
655657
CLI_DOC_INITING = -- TODO: need translate!

script/cli/check.lua

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ local function logFileForThread(threadId)
1111
return LOGPATH .. '/check-partial-' .. threadId .. '.json'
1212
end
1313

14-
local function buildArgs(exe, numThreads, threadId)
14+
local function buildArgs(exe, numThreads, threadId, format, quiet)
1515
local args = {exe}
1616
local skipNext = false
1717
for i = 1, #arg do
@@ -35,7 +35,12 @@ local function buildArgs(exe, numThreads, threadId)
3535
args[#args + 1] = '--thread_id'
3636
args[#args + 1] = tostring(threadId)
3737
if numThreads > 1 then
38-
args[#args + 1] = '--quiet'
38+
if quiet then
39+
args[#args + 1] = '--quiet'
40+
end
41+
if format then
42+
args[#args + 1] = '--check_format=' .. format
43+
end
3944
args[#args + 1] = '--check_out_path'
4045
args[#args + 1] = logFileForThread(threadId)
4146
end
@@ -62,7 +67,7 @@ function export.runCLI()
6267

6368
local procs = {}
6469
for i = 1, numThreads do
65-
local process, err = subprocess.spawn({buildArgs(exe, numThreads, i)})
70+
local process, err = subprocess.spawn({buildArgs(exe, numThreads, i, CHECK_FORMAT, QUIET)})
6671
if err then
6772
print(err)
6873
end
@@ -76,11 +81,6 @@ function export.runCLI()
7681
checkPassed = process:wait() == 0 and checkPassed
7782
end
7883

79-
local outpath = CHECK_OUT_PATH
80-
if outpath == nil then
81-
outpath = LOGPATH .. '/check.json'
82-
end
83-
8484
if numThreads > 1 then
8585
local mergedResults = {}
8686
local count = 0
@@ -95,11 +95,22 @@ function export.runCLI()
9595
end
9696
end
9797
end
98-
util.saveFile(outpath, jsonb.beautify(mergedResults))
99-
if count == 0 then
100-
print(lang.script('CLI_CHECK_SUCCESS'))
101-
else
102-
print(lang.script('CLI_CHECK_RESULTS', count, outpath))
98+
99+
local outpath = nil
100+
101+
if CHECK_FORMAT == 'json' or CHECK_OUT_PATH then
102+
outpath = CHECK_OUT_PATH or LOGPATH .. '/check.json'
103+
util.saveFile(outpath, jsonb.beautify(mergedResults))
104+
end
105+
106+
if not QUIET then
107+
if count == 0 then
108+
print(lang.script('CLI_CHECK_SUCCESS'))
109+
elseif outpath then
110+
print(lang.script('CLI_CHECK_RESULTS_OUTPATH', count, outpath))
111+
else
112+
print(lang.script('CLI_CHECK_RESULTS_PRETTY', count))
113+
end
103114
end
104115
end
105116
return checkPassed and 0 or 1

script/cli/check_worker.lua

Lines changed: 113 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,100 @@ require 'vm'
1717

1818
local export = {}
1919

20+
local colors
21+
22+
if not os.getenv('NO_COLOR') then
23+
colors = {
24+
red = '\27[31m',
25+
green = '\27[32m',
26+
yellow = '\27[33m',
27+
blue = '\27[34m',
28+
magenta = '\27[35m',
29+
white = '\27[37m',
30+
grey = '\27[90m',
31+
reset = '\27[0m'
32+
}
33+
else
34+
colors = {
35+
red = '',
36+
green = '',
37+
yellow = '',
38+
blue = '',
39+
magenta = '',
40+
white = '',
41+
grey = '',
42+
reset = ''
43+
}
44+
end
45+
46+
--- @type table<DiagnosticSeverity, string>
47+
local severity_colors = {
48+
Error = colors.red,
49+
Warning = colors.yellow,
50+
Information = colors.white,
51+
Hint = colors.white,
52+
}
53+
54+
local severity_str = {} --- @type table<integer,DiagnosticSeverity>
55+
for k, v in pairs(define.DiagnosticSeverity) do
56+
severity_str[v] = k
57+
end
58+
59+
local pwd
60+
61+
---@param path string
62+
---@return string
63+
local function relpath(path)
64+
if not pwd then
65+
pwd = furi.decode(furi.encode(fs.current_path():string()))
66+
end
67+
if pwd and path:sub(1, #pwd) == pwd then
68+
path = path:sub(#pwd + 2)
69+
end
70+
return path
71+
end
72+
73+
local function report_pretty(uri, diags)
74+
local path = relpath(furi.decode(uri))
75+
76+
local lines = {} --- @type string[]
77+
pcall(function()
78+
for line in io.lines(path) do
79+
table.insert(lines, line)
80+
end
81+
end)
82+
83+
for _, d in ipairs(diags) do
84+
local rstart = d.range.start
85+
local rend = d.range['end']
86+
local severity = severity_str[d.severity]
87+
print(
88+
('%s%s:%s:%s%s [%s%s%s] %s %s(%s)%s'):format(
89+
colors.blue,
90+
path,
91+
rstart.line + 1, -- Use 1-based indexing
92+
rstart.character + 1, -- Use 1-based indexing
93+
colors.reset,
94+
severity_colors[severity],
95+
severity,
96+
colors.reset,
97+
d.message,
98+
colors.magenta,
99+
d.code,
100+
colors.reset
101+
)
102+
)
103+
if #lines > 0 then
104+
io.write(' ', lines[rstart.line + 1], '\n')
105+
io.write(' ', colors.grey, (' '):rep(rstart.character), '^')
106+
if rstart.line == rend.line then
107+
io.write(('^'):rep(rend.character - rstart.character - 1))
108+
end
109+
io.write(colors.reset, '\n')
110+
end
111+
end
112+
end
113+
20114
local function clear_line()
21115
-- Write out empty space to ensure that the previous lien is cleared.
22116
io.write('\x0D', (' '):rep(80), '\x0D')
@@ -86,6 +180,7 @@ function export.runCLI()
86180

87181
local numThreads = tonumber(NUM_THREADS or 1)
88182
local threadId = tonumber(THREAD_ID or 1)
183+
local quiet = QUIET or numThreads > 1
89184

90185
if type(CHECK_WORKER) ~= 'string' then
91186
print(lang.script('CLI_CHECK_ERROR_TYPE', type(CHECK_WORKER)))
@@ -127,9 +222,13 @@ function export.runCLI()
127222

128223
client:register('textDocument/publishDiagnostics', function (params)
129224
results[params.uri] = params.diagnostics
225+
if not QUIET and (CHECK_FORMAT == nil or CHECK_FORMAT == 'pretty') then
226+
clear_line()
227+
report_pretty(params.uri, params.diagnostics)
228+
end
130229
end)
131230

132-
if not QUIET then
231+
if not quiet then
133232
io.write(lang.script('CLI_CHECK_INITING'))
134233
end
135234

@@ -153,15 +252,15 @@ function export.runCLI()
153252
diag.doDiagnostic(uri, true)
154253
-- Print regularly but always print the last entry to ensure
155254
-- that logs written to files don't look incomplete.
156-
if not QUIET and (os.clock() - lastClock > 0.2 or i == #uris) then
255+
if not quiet and (os.clock() - lastClock > 0.2 or i == #uris) then
157256
lastClock = os.clock()
158257
client:update()
159258
report_progress(i, max, results)
160259
end
161260
end
162261
end
163-
if not QUIET then
164-
io.write('\x0D')
262+
if not quiet then
263+
clear_line()
165264
end
166265
end)
167266

@@ -173,16 +272,21 @@ function export.runCLI()
173272
end
174273
end
175274

176-
local outpath = CHECK_OUT_PATH or LOGPATH .. '/check.json'
275+
local outpath = nil
177276

178-
-- Always write result, even if it's empty to make sure no one accidentally looks at an old output after a successful run.
179-
util.saveFile(outpath, jsonb.beautify(results))
277+
if CHECK_FORMAT == 'json' or CHECK_OUT_PATH then
278+
outpath = CHECK_OUT_PATH or LOGPATH .. '/check.json'
279+
-- Always write result, even if it's empty to make sure no one accidentally looks at an old output after a successful run.
280+
util.saveFile(outpath, jsonb.beautify(results))
281+
end
180282

181-
if not QUIET then
283+
if not quiet then
182284
if count == 0 then
183285
print(lang.script('CLI_CHECK_SUCCESS'))
286+
elseif outpath then
287+
print(lang.script('CLI_CHECK_RESULTS_OUTPATH', count, outpath))
184288
else
185-
print(lang.script('CLI_CHECK_RESULTS', count, outpath))
289+
print(lang.script('CLI_CHECK_RESULTS_PRETTY', count))
186290
end
187291
end
188292
return count == 0 and 0 or 1

script/global.d.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ CHECKLEVEL = 'Warning'
6969
---@type string|nil
7070
CHECK_OUT_PATH = ''
7171

72+
---@type string | 'json' | 'pretty'
73+
CHECK_FORMAT = 'pretty'
74+
7275
---@type 'trace' | 'debug' | 'info' | 'warn' | 'error'
7376
LOGLEVEL = 'warn'
7477

0 commit comments

Comments
 (0)