Clean up error message printing in build and dev server.

This commit is contained in:
Dillon Kearns 2021-08-02 17:38:38 -07:00
parent 156f2ff26d
commit f2402899f6
7 changed files with 145 additions and 47 deletions

View File

@ -71,7 +71,7 @@ function initWorker(basePath) {
pagesReady(JSON.parse(message.data));
} else if (message.tag === "error") {
process.exitCode = 1;
console.error(restoreColor(message.data.errorsJson));
console.error(restoreColor(message.data));
buildNextPage(newWorker);
} else if (message.tag === "done") {
buildNextPage(newWorker);
@ -225,7 +225,7 @@ function runElmMake(elmEntrypointPath, outputPath, cwd) {
resolve();
} else {
process.exitCode = 1;
reject(restoreColor(JSON.parse(commandOutput).errors));
reject(restoreColor(JSON.parse(commandOutput)));
}
});
});

View File

@ -288,11 +288,10 @@ async function start(options) {
try {
await pendingCliCompile;
} catch (error) {
const parsedErrors = JSON.parse(error).errors;
console.log(restoreColor(JSON.parse(error)));
if (req.url.includes("content.json")) {
console.log("@@@1A");
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify(parsedErrors));
res.end(error);
} else {
res.writeHead(500, { "Content-Type": "text/html" });
res.end(errorHtml());
@ -335,10 +334,10 @@ async function start(options) {
},
function (error) {
console.log(restoreColor(error.errorsJson));
console.log(restoreColor(error));
if (req.url.includes("content.json")) {
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify(error.errorsJson));
res.end(JSON.stringify(error));
} else {
res.writeHead(500, { "Content-Type": "text/html" });
res.end(errorHtml());

View File

@ -9,6 +9,10 @@ const kleur = require("kleur");
*
* This function takes in the error title and the path to the file with the error and formats it like elm make's regular output
**/
/**
* @param {string} title
* @param {string} path
* */
const parseHeader = (title, path) =>
kleur.cyan(
`-- ${title.replace("-", " ")} --------------- ${path || ""}
@ -20,6 +24,9 @@ const parseHeader = (title, path) =>
*
* This function takes in the error message and makes sure that it has the proper formatting
**/
/**
* @param {Message} msg
* */
function parseMsg(msg) {
if (typeof msg === "string") {
return msg;
@ -36,19 +43,31 @@ function parseMsg(msg) {
}
}
/** @typedef {{problems: {title: string; message: unknown}[]; path: string}[]} Errors } */
/**
* parseMsg :: { errors: Array } -> String
*
* This function takes in the array of compiler errors and maps over them to generate a formatted compiler error
**/
const restoreColor = (errors) => {
/**
* @param {RootObject} error
* */
const restoreColor = (error) => {
try {
return errors
if (error.type === "compile-errors") {
return error.errors
.map(({ problems, path }) =>
problems.map(restoreProblem(path)).join("\n\n\n")
)
.join("\n\n\n\n\n");
} catch (error) {
} else if (error.type === "error") {
return restoreProblem(error.path)(error);
} else {
throw `Unexpected error ${JSON.stringify(error, null, 2)}`;
}
} catch (e) {
console.trace("Unexpected error format", e.toString());
return error.toString();
}
};
@ -59,8 +78,22 @@ const restoreColor = (errors) => {
* This function takes in the array of compiler errors and maps over them to generate a formatted compiler error
**/
const restoreProblem =
(path) =>
({ title, message }) =>
(/** @type {string} */ path) =>
(/** @type {{title:string; message: Message[]}} */ { title, message }) =>
[parseHeader(title, path), ...message.map(parseMsg)].join("");
module.exports = { restoreColor };
/** @typedef { CompilerError | ReportError } RootObject */
/** @typedef { { type: "compile-errors"; errors: Error_[]; } } CompilerError */
/** @typedef { { type: "error"; path: string; title: string; message: Message[]; } } ReportError */
/** @typedef { { line: number; column: number; } } Location */
/** @typedef { { start: Location; end: Location; } } Region */
/** @typedef { { title: string; region: Region; message: Message[]; } } Problem */
/** @typedef {string | {underline: boolean; color: string?; string: string}} Message */
/** @typedef { { path: string; name: string; problems: Problem[]; } } Error_ */

View File

@ -32,8 +32,12 @@ async function run({ mode, pathname }) {
throw `Unknown mode ${mode}`;
}
} catch (error) {
if (error.errorsJson) {
parentPort.postMessage({ tag: "error", data: error.errorsJson });
} else {
parentPort.postMessage({ tag: "error", data: error });
}
}
console.timeEnd(`${threadId} ${pathname}`);
}

View File

@ -31,11 +31,19 @@ async function handleEvent(sendContentJsonPort, evt) {
const elmJsResponse = await elmJsRequest;
thenApplyHmr(elmJsResponse);
} catch (errorJson) {
console.log({ errorJson });
if (typeof errorJson === "string") {
errorJson = JSON.parse(errorJson)
}
if (errorJson.type) {
showError(errorJson);
} else if (errorJson.length > 0) {
showError({
type: "compile-errors",
errors: errorJson,
});
} else {
showError(JSON.parse(errorJson.errorsJson.errors));
}
}
} else if (evt.data === "elm.js") {
showCompiling("");
@ -74,10 +82,13 @@ async function updateContentJsonWith(
hideCompiling("fast");
});
} catch (errorJson) {
showError({
type: "compile-errors",
errors: errorJson,
});
if (errorJson.type) {
showError(errorJson);
} else if (typeof errorJson === 'string') {
showError(JSON.parse(errorJson));
} else {
showError(errorJson);
}
}
});
}
@ -240,20 +251,35 @@ const consoleMsg = ({ error, style }, msg) => ({
const joinMessage = ({ error, style }) => [error.join("")].concat(style);
const parseConsoleErrors = (path) => ({ title, message }) =>
const parseConsoleErrors = (path) =>
/**
* @param {{ title: string; message: Message[]}} info
* */
(info) =>
joinMessage(
message.reduce(consoleMsg, {
error: [consoleHeader(title, path)],
info.message.reduce(consoleMsg, {
error: [consoleHeader(info.title, path)],
style: [styleColor("blue")],
})
);
const restoreColorConsole = ({ errors }) =>
errors.reduce(
/**
* @param {RootObject} error
* */
const restoreColorConsole = (error) => {
if (error.type === 'compile-errors' && error.errors) {
return error.errors.reduce(
(acc, { problems, path }) =>
acc.concat(problems.map(parseConsoleErrors(path))),
[]
);
} else if (error.type === 'error') {
return parseConsoleErrors(error.path)(error)
} else {
console.error(`Unknown error type ${error}`);
}
}
/*
|-------------------------------------------------------------------------------
@ -275,12 +301,23 @@ const htmlMsg = (acc, msg) =>
const parseHtmlErrors = (path) => ({ title, message }) =>
message.reduce(htmlMsg, htmlHeader(title, path));
const restoreColorHtml = ({ errors }) =>
errors.reduce(
const restoreColorHtml =
/**
* @param {RootObject} error
* */
(error) => {
if (error.type === 'compile-errors') {
return error.errors.reduce(
(acc, { problems, path }) =>
acc.concat(problems.map(parseHtmlErrors(path))),
[]
);
} else if (error.type === 'error') {
return parseHtmlErrors(error.path)(error);
} else {
throw new Error(`Unknown error type ${error}`);
}
}
/*
|-------------------------------------------------------------------------------
@ -291,6 +328,9 @@ const restoreColorHtml = ({ errors }) =>
var speed = 400;
var delay = 20;
/**
* @param {RootObject} error
*/
function showError(error) {
restoreColorConsole(error).forEach((error) => {
console.log.apply(this, error);
@ -575,3 +615,16 @@ function hideCompiling(velocity) {
}
}
}
/** @typedef { CompilerError | ReportError } RootObject */
/** @typedef { { type: "compile-errors"; errors: Error_[]; } } CompilerError */
/** @typedef { { type: "error"; path: string; title: string; message: Message[]; } } ReportError */
/** @typedef { { line: number; column: number; } } CodeLocation */
/** @typedef { { start: CodeLocation; end: CodeLocation; } } Region */
/** @typedef { { title: string; region: Region; message: Message[]; } } Problem */
/** @typedef {string | {underline: boolean; color: string?; string: string}} Message */
/** @typedef { { path: string; name: string; problems: Problem[]; } } Error_ */

View File

@ -34,13 +34,22 @@ banner title =
]
encode : BuildError -> Encode.Value
encode buildError =
encode : List BuildError -> Encode.Value
encode buildErrors =
Encode.object
[ ( "type", Encode.string "compile-errors" )
, ( "errors"
, Encode.list
(\buildError ->
Encode.object
[ ( "path", Encode.string buildError.path )
, ( "name", Encode.string buildError.title )
, ( "problems", Encode.list (messagesEncoder buildError.title) [ buildError.message ] )
]
)
buildErrors
)
]
messagesEncoder : String -> List Terminal.Text -> Encode.Value

View File

@ -38,7 +38,7 @@ errorCodec =
|> Codec.field "errorsJson"
identity
(Codec.build
(Json.Encode.list BuildError.encode)
BuildError.encode
(Decode.succeed [ { title = "TODO", message = [], fatal = True, path = "" } ])
)
|> Codec.buildObject