From 9f25c279f8162098d7dfe000533bfbbb8702e024 Mon Sep 17 00:00:00 2001 From: "Wu, Zhenyu" Date: Thu, 19 Dec 2024 16:09:54 +0800 Subject: [PATCH] Exit 1 when check error --- script/cli/check.lua | 157 ++++++++++++------------ script/cli/check_worker.lua | 233 +++++++++++++++++++----------------- script/cli/init.lua | 8 +- 3 files changed, 206 insertions(+), 192 deletions(-) diff --git a/script/cli/check.lua b/script/cli/check.lua index c3aac0e3d..c9a23b02c 100644 --- a/script/cli/check.lua +++ b/script/cli/check.lua @@ -5,97 +5,104 @@ local json = require 'json' local jsonb = require 'json-beautify' local util = require 'utility' +local export = {} -local numThreads = tonumber(NUM_THREADS or 1) +function export.runCLI() + local numThreads = tonumber(NUM_THREADS or 1) -local exe -local minIndex = -1 -while arg[minIndex] do - exe = arg[minIndex] - minIndex = minIndex - 1 -end --- TODO: is this necessary? got it from the shell.lua helper in bee.lua tests -if platform.os == 'windows' and not exe:match('%.[eE][xX][eE]$') then - exe = exe..'.exe' -end + local exe + local minIndex = -1 + while arg[minIndex] do + exe = arg[minIndex] + minIndex = minIndex - 1 + end + -- TODO: is this necessary? got it from the shell.lua helper in bee.lua tests + if platform.os == 'windows' and not exe:match('%.[eE][xX][eE]$') then + exe = exe..'.exe' + end -local function logFileForThread(threadId) - return LOGPATH .. '/check-partial-' .. threadId .. '.json' -end + local function logFileForThread(threadId) + return LOGPATH .. '/check-partial-' .. threadId .. '.json' + end -local function buildArgs(threadId) - local args = {exe} - local skipNext = false - for i = 1, #arg do - local arg = arg[i] - -- --check needs to be transformed into --check_worker - if arg:lower():match('^%-%-check$') or arg:lower():match('^%-%-check=') then - args[#args + 1] = arg:gsub('%-%-%w*', '--check_worker') - -- --check_out_path needs to be removed if we have more than one thread - elseif arg:lower():match('%-%-check_out_path') and numThreads > 1 then - if not arg:match('%-%-%w*=') then - skipNext = true - end - else - if skipNext then - skipNext = false + local function buildArgs(threadId) + local args = {exe} + local skipNext = false + for i = 1, #arg do + local arg = arg[i] + -- --check needs to be transformed into --check_worker + if arg:lower():match('^%-%-check$') or arg:lower():match('^%-%-check=') then + args[#args + 1] = arg:gsub('%-%-%w*', '--check_worker') + -- --check_out_path needs to be removed if we have more than one thread + elseif arg:lower():match('%-%-check_out_path') and numThreads > 1 then + if not arg:match('%-%-%w*=') then + skipNext = true + end else - args[#args + 1] = arg + if skipNext then + skipNext = false + else + args[#args + 1] = arg + end end end + args[#args + 1] = '--thread_id' + args[#args + 1] = tostring(threadId) + if numThreads > 1 then + args[#args + 1] = '--quiet' + args[#args + 1] = '--check_out_path' + args[#args + 1] = logFileForThread(threadId) + end + return args end - args[#args + 1] = '--thread_id' - args[#args + 1] = tostring(threadId) + if numThreads > 1 then - args[#args + 1] = '--quiet' - args[#args + 1] = '--check_out_path' - args[#args + 1] = logFileForThread(threadId) + print(lang.script('CLI_CHECK_MULTIPLE_WORKERS', numThreads)) end - return args -end -if numThreads > 1 then - print(lang.script('CLI_CHECK_MULTIPLE_WORKERS', numThreads)) -end - -local procs = {} -for i = 1, numThreads do - local process, err = subprocess.spawn({buildArgs(i)}) - if err then - print(err) - end - if process then - procs[#procs + 1] = process + local procs = {} + for i = 1, numThreads do + local process, err = subprocess.spawn({buildArgs(i)}) + if err then + print(err) + end + if process then + procs[#procs + 1] = process + end end -end -for _, process in ipairs(procs) do - process:wait() -end + local checkPassed = true + for _, process in ipairs(procs) do + checkPassed = process:wait() == 0 and checkPassed + end -local outpath = CHECK_OUT_PATH -if outpath == nil then - outpath = LOGPATH .. '/check.json' -end + local outpath = CHECK_OUT_PATH + if outpath == nil then + outpath = LOGPATH .. '/check.json' + end -if numThreads > 1 then - local mergedResults = {} - local count = 0 - for i = 1, numThreads do - local result = json.decode(util.loadFile(logFileForThread(i)) or '[]') - for k, v in pairs(result) do - local entries = mergedResults[k] or {} - mergedResults[k] = entries - for _, entry in ipairs(v) do - entries[#entries + 1] = entry - count = count + 1 + if numThreads > 1 then + local mergedResults = {} + local count = 0 + for i = 1, numThreads do + local result = json.decode(util.loadFile(logFileForThread(i)) or '[]') + for k, v in pairs(result) do + local entries = mergedResults[k] or {} + mergedResults[k] = entries + for _, entry in ipairs(v) do + entries[#entries + 1] = entry + count = count + 1 + end end end + util.saveFile(outpath, jsonb.beautify(mergedResults)) + if count == 0 then + print(lang.script('CLI_CHECK_SUCCESS')) + else + print(lang.script('CLI_CHECK_RESULTS', count, outpath)) + end end - util.saveFile(outpath, jsonb.beautify(mergedResults)) - if count == 0 then - print(lang.script('CLI_CHECK_SUCCESS')) - else - print(lang.script('CLI_CHECK_RESULTS', count, outpath)) - end + return checkPassed and 0 or 1 end + +return export diff --git a/script/cli/check_worker.lua b/script/cli/check_worker.lua index 822c83dc6..a2e0bff11 100644 --- a/script/cli/check_worker.lua +++ b/script/cli/check_worker.lua @@ -15,145 +15,152 @@ local await = require 'await' require 'plugin' require 'vm' -lang(LOCALE) +local export = {} -local numThreads = tonumber(NUM_THREADS or 1) -local threadId = tonumber(THREAD_ID or 1) +function export.runCLI() + lang(LOCALE) -if type(CHECK_WORKER) ~= 'string' then - print(lang.script('CLI_CHECK_ERROR_TYPE', type(CHECK_WORKER))) - return -end + local numThreads = tonumber(NUM_THREADS or 1) + local threadId = tonumber(THREAD_ID or 1) -local rootPath = fs.absolute(fs.path(CHECK_WORKER)):string() -local rootUri = furi.encode(rootPath) -if not rootUri then - print(lang.script('CLI_CHECK_ERROR_URI', rootPath)) - return -end -rootUri = rootUri:gsub("/$", "") + if type(CHECK_WORKER) ~= 'string' then + print(lang.script('CLI_CHECK_ERROR_TYPE', type(CHECK_WORKER))) + return + end -if CHECKLEVEL then - if not define.DiagnosticSeverity[CHECKLEVEL] then - print(lang.script('CLI_CHECK_ERROR_LEVEL', 'Error, Warning, Information, Hint')) + local rootPath = fs.absolute(fs.path(CHECK_WORKER)):string() + local rootUri = furi.encode(rootPath) + if not rootUri then + print(lang.script('CLI_CHECK_ERROR_URI', rootPath)) return end -end -local checkLevel = define.DiagnosticSeverity[CHECKLEVEL] or define.DiagnosticSeverity.Warning + rootUri = rootUri:gsub("/$", "") -util.enableCloseFunction() + if CHECKLEVEL then + if not define.DiagnosticSeverity[CHECKLEVEL] then + print(lang.script('CLI_CHECK_ERROR_LEVEL', 'Error, Warning, Information, Hint')) + return + end + end + local checkLevel = define.DiagnosticSeverity[CHECKLEVEL] or define.DiagnosticSeverity.Warning -local lastClock = os.clock() -local results = {} + util.enableCloseFunction() -local function errorhandler(err) - print(err) - print(debug.traceback()) -end + local lastClock = os.clock() + local results = {} ----@async -xpcall(lclient.start, errorhandler, lclient, function (client) - await.disable() - client:registerFakers() + local function errorhandler(err) + print(err) + print(debug.traceback()) + end - client:initialize { - rootUri = rootUri, - } + ---@async + xpcall(lclient.start, errorhandler, lclient, function (client) + await.disable() + client:registerFakers() - client:register('textDocument/publishDiagnostics', function (params) - results[params.uri] = params.diagnostics - end) + client:initialize { + rootUri = rootUri, + } - if not QUIET then - io.write(lang.script('CLI_CHECK_INITING')) - end + client:register('textDocument/publishDiagnostics', function (params) + results[params.uri] = params.diagnostics + end) + + if not QUIET then + io.write(lang.script('CLI_CHECK_INITING')) + end - provider.updateConfig(rootUri) + provider.updateConfig(rootUri) - ws.awaitReady(rootUri) + ws.awaitReady(rootUri) - local disables = util.arrayToHash(config.get(rootUri, 'Lua.diagnostics.disable')) - for name, serverity in pairs(define.DiagnosticDefaultSeverity) do - serverity = config.get(rootUri, 'Lua.diagnostics.severity')[name] or serverity - if serverity:sub(-1) == '!' then - serverity = serverity:sub(1, -2) - end - if define.DiagnosticSeverity[serverity] > checkLevel then - disables[name] = true + local disables = util.arrayToHash(config.get(rootUri, 'Lua.diagnostics.disable')) + for name, serverity in pairs(define.DiagnosticDefaultSeverity) do + serverity = config.get(rootUri, 'Lua.diagnostics.severity')[name] or serverity + if serverity:sub(-1) == '!' then + serverity = serverity:sub(1, -2) + end + if define.DiagnosticSeverity[serverity] > checkLevel then + disables[name] = true + end end - end - config.set(rootUri, 'Lua.diagnostics.disable', util.getTableKeys(disables, true)) + config.set(rootUri, 'Lua.diagnostics.disable', util.getTableKeys(disables, true)) - -- 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 - if status == 'Any' or status == 'Any!' then - diagStatus[diag] = 'Opened!' + -- 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 + if status == 'Any' or status == 'Any!' then + diagStatus[diag] = 'Opened!' + end end - end - for diag, status in pairs(protoDiag.getDefaultStatus()) do - if status == 'Any' or status == 'Any!' then - diagStatus[diag] = 'Opened!' + for diag, status in pairs(protoDiag.getDefaultStatus()) do + if status == 'Any' or status == 'Any!' then + diagStatus[diag] = 'Opened!' + end end - end - config.set(rootUri, 'Lua.diagnostics.neededFileStatus', diagStatus) - - local uris = files.getChildFiles(rootUri) - local max = #uris - table.sort(uris) -- sort file list to ensure the work distribution order across multiple threads - for i, uri in ipairs(uris) do - if (i % numThreads + 1) == threadId then - files.open(uri) - diag.doDiagnostic(uri, true) - -- Print regularly but always print the last entry to ensure that logs written to files don't look incomplete. - if (os.clock() - lastClock > 0.2 or i == #uris) and not QUIET then - lastClock = os.clock() - client:update() - local output = '\x0D' - .. ('>'):rep(math.ceil(i / max * 20)) - .. ('='):rep(20 - math.ceil(i / max * 20)) - .. ' ' - .. ('0'):rep(#tostring(max) - #tostring(i)) - .. tostring(i) .. '/' .. tostring(max) - io.write(output) - local filesWithErrors = 0 - local errors = 0 - for _, diags in pairs(results) do - filesWithErrors = filesWithErrors + 1 - errors = errors + #diags + config.set(rootUri, 'Lua.diagnostics.neededFileStatus', diagStatus) + + local uris = files.getChildFiles(rootUri) + local max = #uris + table.sort(uris) -- sort file list to ensure the work distribution order across multiple threads + for i, uri in ipairs(uris) do + if (i % numThreads + 1) == threadId then + files.open(uri) + diag.doDiagnostic(uri, true) + -- Print regularly but always print the last entry to ensure that logs written to files don't look incomplete. + if (os.clock() - lastClock > 0.2 or i == #uris) and not QUIET then + lastClock = os.clock() + client:update() + local output = '\x0D' + .. ('>'):rep(math.ceil(i / max * 20)) + .. ('='):rep(20 - math.ceil(i / max * 20)) + .. ' ' + .. ('0'):rep(#tostring(max) - #tostring(i)) + .. tostring(i) .. '/' .. tostring(max) + io.write(output) + local filesWithErrors = 0 + local errors = 0 + for _, diags in pairs(results) do + filesWithErrors = filesWithErrors + 1 + errors = errors + #diags + end + if errors > 0 then + local errorDetails = ' [' .. lang.script('CLI_CHECK_PROGRESS', errors, filesWithErrors) .. ']' + io.write(errorDetails) + end + io.flush() end - if errors > 0 then - local errorDetails = ' [' .. lang.script('CLI_CHECK_PROGRESS', errors, filesWithErrors) .. ']' - io.write(errorDetails) - end - io.flush() end end + if not QUIET then + io.write('\x0D') + end + end) + + local count = 0 + for uri, result in pairs(results) do + count = count + #result + if #result == 0 then + results[uri] = nil + end end - if not QUIET then - io.write('\x0D') - end -end) -local count = 0 -for uri, result in pairs(results) do - count = count + #result - if #result == 0 then - results[uri] = nil + local outpath = CHECK_OUT_PATH + if outpath == nil then + outpath = LOGPATH .. '/check.json' end -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)) -local outpath = CHECK_OUT_PATH -if outpath == nil then - outpath = LOGPATH .. '/check.json' -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')) - else - print(lang.script('CLI_CHECK_RESULTS', count, outpath)) + if not QUIET then + if count == 0 then + print(lang.script('CLI_CHECK_SUCCESS')) + else + print(lang.script('CLI_CHECK_RESULTS', count, outpath)) + end end + return count == 0 and 0 or 1 end + +return export diff --git a/script/cli/init.lua b/script/cli/init.lua index 65e7e102a..37554123e 100644 --- a/script/cli/init.lua +++ b/script/cli/init.lua @@ -4,13 +4,13 @@ if _G['VERSION'] then end if _G['CHECK'] then - require 'cli.check' - os.exit(0, true) + local ret = require 'cli.check'.runCLI() + os.exit(ret, true) end if _G['CHECK_WORKER'] then - require 'cli.check_worker' - os.exit(0, true) + local ret = require 'cli.check_worker'.runCLI() + os.exit(ret or 0, true) end if _G['DOC_UPDATE'] then