-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: New error and warning messages
- Loading branch information
Showing
10 changed files
with
223 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,10 @@ | |
"browser": false | ||
}, | ||
|
||
"parserOptions": { | ||
"sourceType": "module" | ||
}, | ||
|
||
"plugins": [ | ||
"flowtype" | ||
], | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
src/utils/__test__/__snapshots__/error-helpers.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`#formatMessages Format ESLint Warnings 1`] = ` | ||
" [2m5:16[22m [33mwarning[39m React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead [2mreact/no-deprecated[22m | ||
[2m40:11[22m [33mwarning[39m No duplicate props allowed [2mreact/jsx-no-duplicate-props[22m | ||
[33mWhere:[39m ./thinking-in-react/src/components/filtered-product-table/filtered-product-table.js | ||
[2m16:11[22m [33mwarning[39m No duplicate props allowed [2mreact/jsx-no-duplicate-props[22m | ||
[33mWhere:[39m ./thinking-in-react/src/components/product-table/product-table.js" | ||
`; | ||
|
||
exports[`#formatMessages Format Syntax Error 1`] = ` | ||
"[31mError:[39m | ||
[2m|[22m Syntax Error: Unexpected token (20:7) | ||
[33mWhere:[39m ./thinking-in-react/src/components/product-table/product-table.js | ||
[0m [90m 18 | [39m [36mreturn[39m ( | ||
[90m 19 | [39m [33m<[39m[33mdiv[39m className[33m=[39m[32m\\"productTable\\"[39m[33m>[39m | ||
[31m[1m>[22m[39m[90m 20 | [39m [33m<<[39m[33mtable[39m[33m>[39m | ||
[90m | [39m [31m[1m^[22m[39m | ||
[90m 21 | [39m [33m<[39m[33mthead[39m[33m>[39m | ||
[90m 22 | [39m [33m<[39m[33mtr[39m[33m>[39m | ||
[90m 23 | [39m [33m<[39m[33mth[39m[33m>[39m[33mName[39m[33m<[39m[33m/[39m[33mth[39m[33m>[39m[0m" | ||
`; | ||
|
||
exports[`#formatMessages Unknown messages 1`] = ` | ||
Array [ | ||
"some", | ||
"custom", | ||
"messages", | ||
] | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,20 @@ | ||
test("adds 1 + 2 to equal 3", () => { | ||
expect(1 + 2).toBe(3); | ||
import syntaxErrorMock from "./mock-data/syntax-error.json"; | ||
import eslintWarningMock from "./mock-data/eslint-warning.json"; | ||
import { formatMessages } from "../error-helpers"; | ||
|
||
describe("#formatMessages", () => { | ||
test("Format Syntax Error", () => { | ||
const [error] = formatMessages(syntaxErrorMock); | ||
expect(error).toMatchSnapshot(); | ||
}); | ||
|
||
test("Format ESLint Warnings", () => { | ||
const warnings = formatMessages(eslintWarningMock).join("\n\n\n"); | ||
expect(warnings).toMatchSnapshot(); | ||
}); | ||
|
||
test("Unknown messages", () => { | ||
const messages = ["some", "custom", "messages"]; | ||
expect(formatMessages(messages)).toMatchSnapshot(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[ | ||
"./thinking-in-react/src/components/filtered-product-table/filtered-product-table.js\n\n\u001b[4m/Users/ssysoev/Development/aik-examples/thinking-in-react/src/components/filtered-product-table/filtered-product-table.js\u001b[24m\n \u001b[2m5:16\u001b[22m \u001b[33mwarning\u001b[39m React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead \u001b[2mreact/no-deprecated\u001b[22m\n \u001b[2m40:11\u001b[22m \u001b[33mwarning\u001b[39m No duplicate props allowed \u001b[2mreact/jsx-no-duplicate-props\u001b[22m\n\n\u001b[33m\u001b[1m✖ 2 problems (0 errors, 2 warnings)\n\u001b[22m\u001b[39m\n @ ./thinking-in-react/src/index.js 14:28-95\n @ ../aik/lib/webpack/assets/react-entry-point.js\n @ multi ../aik/~/webpack-dev-server/client?http://localhost:4444/ ../aik/~/webpack/hot/dev-server.js ../aik/lib/webpack/assets/react-entry-point.js", | ||
"./thinking-in-react/src/components/product-table/product-table.js\n\n\u001b[4m/Users/ssysoev/Development/aik-examples/thinking-in-react/src/components/product-table/product-table.js\u001b[24m\n \u001b[2m16:11\u001b[22m \u001b[33mwarning\u001b[39m No duplicate props allowed \u001b[2mreact/jsx-no-duplicate-props\u001b[22m\n\n\u001b[33m\u001b[1m✖ 1 problem (0 errors, 1 warning)\n\u001b[22m\u001b[39m\n @ ./thinking-in-react/src/components/filtered-product-table/filtered-product-table.js 27:20-69\n @ ./thinking-in-react/src/index.js\n @ ../aik/lib/webpack/assets/react-entry-point.js\n @ multi ../aik/~/webpack-dev-server/client?http://localhost:4444/ ../aik/~/webpack/hot/dev-server.js ../aik/lib/webpack/assets/react-entry-point.js" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[ | ||
"./thinking-in-react/src/components/product-table/product-table.js\n\n\u001b[4m/Users/ssysoev/Development/aik-examples/thinking-in-react/src/components/product-table/product-table.js\u001b[24m\n \u001b[2m20:8\u001b[22m \u001b[31merror\u001b[39m Parsing error: Unexpected token <\n\n\u001b[31m\u001b[1m✖ 1 problem (1 error, 0 warnings)\n\u001b[22m\u001b[39m\n @ ./thinking-in-react/src/components/filtered-product-table/filtered-product-table.js 27:20-69\n @ ./thinking-in-react/src/index.js\n @ ../aik/lib/webpack/assets/react-entry-point.js\n @ multi ../aik/~/webpack-dev-server/client?http://localhost:4444/ ../aik/~/webpack/hot/dev-server.js ../aik/lib/webpack/assets/react-entry-point.js", | ||
"./thinking-in-react/src/components/product-table/product-table.js\nModule build failed: SyntaxError: Unexpected token (20:7)\n\n\u001b[0m \u001b[90m 18 | \u001b[39m \u001b[36mreturn\u001b[39m (\n \u001b[90m 19 | \u001b[39m \u001b[33m<\u001b[39m\u001b[33mdiv\u001b[39m className\u001b[33m=\u001b[39m\u001b[32m\"productTable\"\u001b[39m\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 20 | \u001b[39m \u001b[33m<<\u001b[39m\u001b[33mtable\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m | \u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 21 | \u001b[39m \u001b[33m<\u001b[39m\u001b[33mthead\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 22 | \u001b[39m \u001b[33m<\u001b[39m\u001b[33mtr\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 23 | \u001b[39m \u001b[33m<\u001b[39m\u001b[33mth\u001b[39m\u001b[33m>\u001b[39m\u001b[33mName\u001b[39m\u001b[33m<\u001b[39m\u001b[33m/\u001b[39m\u001b[33mth\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\n @ ./thinking-in-react/src/components/filtered-product-table/filtered-product-table.js 27:20-69\n @ ./thinking-in-react/src/index.js\n @ ../aik/lib/webpack/assets/react-entry-point.js\n @ multi ../aik/~/webpack-dev-server/client?http://localhost:4444/ ../aik/~/webpack/hot/dev-server.js ../aik/lib/webpack/assets/react-entry-point.js" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,118 @@ | ||
/* @flow */ | ||
|
||
import chalk from "chalk"; | ||
|
||
const SYNTAX_ERROR_LABEL = "SyntaxError:"; | ||
const SYNTAX_ERROR_LABEL_HUMAN_FRIENDLY = "Syntax Error:"; | ||
const ESLINT_PARSE_ERROR = "Parsing error:"; | ||
|
||
/** | ||
* Checks whether error is syntax error. | ||
*/ | ||
export function isLikelyASyntaxError(message: string): boolean { | ||
export function isSyntaxError(message: string): boolean { | ||
return ( | ||
message.indexOf(SYNTAX_ERROR_LABEL) !== -1 || | ||
message.indexOf(SYNTAX_ERROR_LABEL_HUMAN_FRIENDLY) !== -1 | ||
); | ||
} | ||
|
||
/** | ||
* Makes some common errors shorter. | ||
* Checks whether error is eslint rules warning. | ||
*/ | ||
export function formatMessage(message: string): string { | ||
return ( | ||
message | ||
// Babel syntax error | ||
.replace( | ||
"Module build failed: SyntaxError:", | ||
SYNTAX_ERROR_LABEL_HUMAN_FRIENDLY | ||
) | ||
// Webpack file not found error | ||
.replace( | ||
/Module not found: Error: Cannot resolve 'file' or 'directory'/, | ||
"Module not found:" | ||
) | ||
// Internal stacks are generally useless so we strip them | ||
.replace(/^\s*at\s((?!webpack:).)*:\d+:\d+[\s\)]*(\n|$)/gm, "") // at ... ...:x:y | ||
// Webpack loader names obscure CSS filenames | ||
.replace("./~/css-loader!./~/postcss-loader!", "") | ||
.replace(/\s@ multi .+/, "") | ||
export function isEslintWarning(message: string): boolean { | ||
return !!message.match(/\d\sproblem/) && !!message.match("warning"); | ||
} | ||
|
||
/** | ||
* Checks whether error is eslint parse error. | ||
*/ | ||
export function isEslintParseError(message: string): boolean { | ||
return !!message.match(ESLINT_PARSE_ERROR); | ||
} | ||
|
||
export function findMessagesToFormat(messages: string[]): string[] { | ||
return messages.filter(message => { | ||
if (isEslintParseError(message)) { | ||
return false; | ||
} | ||
|
||
return true; | ||
}); | ||
} | ||
|
||
export function isFileSnippetLine(line: string): boolean { | ||
return !!line.match(/\s+\|/); | ||
} | ||
|
||
export function isEslintWarningRuleLine(line: string): boolean { | ||
// console.log(line, !!line.match(/\d+:\d+(.+)warning/)); | ||
return !!line.match(/\d+:\d+(.+)warning/); | ||
} | ||
|
||
export function getLinePadding(line: string): number { | ||
return line.split("").findIndex(c => !!c.match(/\S/)); | ||
} | ||
|
||
export function removeLinePadding(padding: number, line: string): string { | ||
return line.substring(padding); | ||
} | ||
|
||
/** | ||
* Formats "Syntax Error" message. | ||
*/ | ||
export function formatSyntaxError(message: string): string { | ||
const messageByLine = message.split("\n"); | ||
const padding = getLinePadding(messageByLine[0]); | ||
const filePath = removeLinePadding(padding, messageByLine[0]); | ||
const error = removeLinePadding( | ||
padding, | ||
messageByLine[1].replace( | ||
"Module build failed: SyntaxError:", | ||
SYNTAX_ERROR_LABEL_HUMAN_FRIENDLY | ||
) | ||
); | ||
const snippet = messageByLine | ||
.filter(isFileSnippetLine) | ||
.map(removeLinePadding.bind(null, padding)); | ||
|
||
return `${chalk.red("Error:")} | ||
${chalk.dim("|")} ${error} | ||
${chalk.yellow("Where:")} ${filePath} | ||
${snippet.join("\n")}`; | ||
} | ||
|
||
/** | ||
* Formats "ESLint warning" message. | ||
*/ | ||
export function formatEslintWarning(message: string): string { | ||
const messageByLine = message.split("\n"); | ||
const padding = getLinePadding(messageByLine[0]); | ||
const filePath = removeLinePadding(padding, messageByLine[0]); | ||
const rule = messageByLine | ||
.filter(isEslintWarningRuleLine) | ||
.map(removeLinePadding.bind(null, padding + 2)); | ||
|
||
return `${rule.join("\n")} | ||
${chalk.yellow("Where:")} ${filePath}`; | ||
} | ||
|
||
/** | ||
* Beautifies error messages and warnings. | ||
*/ | ||
export function formatMessages(messages: string[]): string[] { | ||
return findMessagesToFormat(messages).map(message => { | ||
if (isSyntaxError(message)) { | ||
return formatSyntaxError(message); | ||
} | ||
|
||
if (isEslintWarning(message)) { | ||
return formatEslintWarning(message); | ||
} | ||
|
||
return message; | ||
}); | ||
} |
Oops, something went wrong.