Skip to content

Commit

Permalink
fix: bring back :line:col format in webpack errors (#716)
Browse files Browse the repository at this point in the history
Reimplements #489 so that file links with locations can be clicked in the terminal.
  • Loading branch information
robcrocombe authored May 1, 2022
1 parent d3f8f6a commit 4cc5346
Show file tree
Hide file tree
Showing 11 changed files with 37 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/formatter/webpack-formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function createWebpackFormatter(formatter: Formatter): Formatter {
if (issue.file) {
let location = chalk.bold(relativeToContext(issue.file, process.cwd()));
if (issue.location) {
location += ` ${chalk.green.bold(formatIssueLocation(issue.location))}`;
location += `:${chalk.green.bold(formatIssueLocation(issue.location))}`;
}

return [`${color(severity)} in ${location}`, formatter(issue), ''].join(os.EOL);
Expand Down
16 changes: 2 additions & 14 deletions src/issue/issue-location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,8 @@ function compareIssueLocations(locationA?: IssueLocation, locationB?: IssueLocat
);
}

function formatIssueLocation({ start, end }: IssueLocation) {
if (!end.line || start.line === end.line) {
// the same line
if (!end.column || start.column === end.column) {
// the same column
return `${start.line}:${start.column}`;
} else {
// different column
return `${start.line}:${start.column}-${end.column}`;
}
} else {
// different lines
return `${start.line}:${start.column}-${end.line}:${end.column}`;
}
function formatIssueLocation(location: IssueLocation) {
return `${location.start.line}:${location.start.column}`;
}

export { IssueLocation, compareIssueLocations, formatIssueLocation };
2 changes: 1 addition & 1 deletion src/issue/issue-webpack-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class IssueWebpackError extends webpack.WebpackError {
this.file = relativeToContext(issue.file, process.cwd());

if (issue.location) {
this.file += ` ${chalk.green.bold(formatIssueLocation(issue.location))}`;
this.file += `:${chalk.green.bold(formatIssueLocation(issue.location))}`;
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/e2e/type-script-context-option.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe('TypeScript Context Option', () => {
const errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ../src/model/User.ts 11:16-25',
'ERROR in ../src/model/User.ts:11:16',
"TS2339: Property 'firstName' does not exist on type 'User'.",
' 9 |',
' 10 | function getUserName(user: User): string {',
Expand All @@ -100,7 +100,7 @@ describe('TypeScript Context Option', () => {
' 14 | export { User, getUserName };',
].join('\n'),
[
'ERROR in ../src/model/User.ts 11:32-40',
'ERROR in ../src/model/User.ts:11:32',
"TS2339: Property 'lastName' does not exist on type 'User'.",
' 9 |',
' 10 | function getUserName(user: User): string {',
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/type-script-formatter-option.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ describe('TypeScript Formatter Option', () => {
const errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/model/User.ts 11:16-25',
'ERROR in ./src/model/User.ts:11:16',
"It is the custom issue statement - TS2339: Property 'firstName' does not exist on type 'User'.",
].join('\n'),
[
'ERROR in ./src/model/User.ts 11:32-40',
'ERROR in ./src/model/User.ts:11:32',
"It is the custom issue statement - TS2339: Property 'lastName' does not exist on type 'User'.",
].join('\n'),
]);
Expand Down
12 changes: 6 additions & 6 deletions test/e2e/type-script-pnp-support.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('TypeScript PnP Support', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/model/User.ts 11:16-25',
'ERROR in ./src/model/User.ts:11:16',
"TS2339: Property 'firstName' does not exist on type 'User'.",
' 9 |',
' 10 | function getUserName(user: User): string {',
Expand All @@ -45,7 +45,7 @@ describe('TypeScript PnP Support', () => {
' 14 | export { User, getUserName };',
].join('\n'),
[
'ERROR in ./src/model/User.ts 11:32-40',
'ERROR in ./src/model/User.ts:11:32',
"TS2339: Property 'lastName' does not exist on type 'User'.",
' 9 |',
' 10 | function getUserName(user: User): string {',
Expand All @@ -72,7 +72,7 @@ describe('TypeScript PnP Support', () => {
errors = await driver.waitForErrors();
expect(errors).toContain(
[
'ERROR in ./src/index.ts 1:23-39',
'ERROR in ./src/index.ts:1:23',
semver.satisfies(semver.minVersion(dependencies.typescript), '>=4.0.0')
? "TS2307: Cannot find module './authenticate' or its corresponding type declarations."
: "TS2307: Cannot find module './authenticate'.",
Expand Down Expand Up @@ -118,7 +118,7 @@ describe('TypeScript PnP Support', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/index.ts 34:12-16',
'ERROR in ./src/index.ts:34:12',
"TS2339: Property 'role' does not exist on type 'void'.",
' 32 | const user = await login(email, password);',
' 33 |',
Expand All @@ -129,7 +129,7 @@ describe('TypeScript PnP Support', () => {
' 37 | console.log(`Logged in as ${getUserName(user)}`);',
].join('\n'),
[
'ERROR in ./src/index.ts 35:45-49',
'ERROR in ./src/index.ts:35:45',
"TS2345: Argument of type 'void' is not assignable to parameter of type 'User'.",
' 33 |',
" 34 | if (user.role === 'admin') {",
Expand All @@ -140,7 +140,7 @@ describe('TypeScript PnP Support', () => {
' 38 | }',
].join('\n'),
[
'ERROR in ./src/index.ts 37:45-49',
'ERROR in ./src/index.ts:37:45',
"TS2345: Argument of type 'void' is not assignable to parameter of type 'User'.",
' 35 | console.log(`Logged in as ${getUserName(user)} [admin].`);',
' 36 | } else {',
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/type-script-solution-builder-api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('TypeScript SolutionBuilder API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./packages/shared/src/intersect.ts 2:41-49',
'ERROR in ./packages/shared/src/intersect.ts:2:41',
"TS2339: Property 'includes' does not exist on type 'T'.",
' 1 | function intersect<T>(arrayA: T[] = [], arrayB: T): T[] {',
' > 2 | return arrayA.filter((item) => arrayB.includes(item));',
Expand All @@ -55,7 +55,7 @@ describe('TypeScript SolutionBuilder API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./packages/client/src/index.ts 4:42-48',
'ERROR in ./packages/client/src/index.ts:4:42',
"TS2345: Argument of type 'T[]' is not assignable to parameter of type 'T'.",
semver.satisfies(semver.minVersion(typescript), '>=4.0.0')
? " 'T' could be instantiated with an arbitrary type which could be unrelated to 'T[]'."
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/type-script-vue-extension.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('TypeScript Vue Extension', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/component/LoggedIn.vue 27:23-34',
'ERROR in ./src/component/LoggedIn.vue:27:23',
"TS2304: Cannot find name 'getUserName'.",
' 25 | const user: User = this.user;',
' 26 |',
Expand Down Expand Up @@ -91,7 +91,7 @@ describe('TypeScript Vue Extension', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/component/LoggedIn.vue 27:31-40',
'ERROR in ./src/component/LoggedIn.vue:27:31',
"TS2339: Property 'firstName' does not exist on type 'User'.",
' 25 | const user: User = this.user;',
' 26 |',
Expand All @@ -102,7 +102,7 @@ describe('TypeScript Vue Extension', () => {
' 30 | async logout() {',
].join('\n'),
[
'ERROR in ./src/model/User.ts 11:16-25',
'ERROR in ./src/model/User.ts:11:16',
"TS2339: Property 'firstName' does not exist on type 'User'.",
' 9 |',
' 10 | function getUserName(user: User): string {',
Expand Down
26 changes: 13 additions & 13 deletions test/e2e/type-script-watch-api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('TypeScript Watch API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/index.ts 34:7-28',
'ERROR in ./src/index.ts:34:7',
`TS2367: This condition will always return 'false' since the types 'Role' and '"admin"' have no overlap.`,
' 32 | const user = await login(email, password);',
' 33 |',
Expand Down Expand Up @@ -74,7 +74,7 @@ describe('TypeScript Watch API', () => {
);
expect(errors).toEqual([
[
'ERROR in ./src/model/User.ts 1:22-30',
'ERROR in ./src/model/User.ts:1:22',
"TS2307: Cannot find module './Role' or its corresponding type declarations.",
" > 1 | import { Role } from './Role';",
' | ^^^^^^^^',
Expand All @@ -94,7 +94,7 @@ describe('TypeScript Watch API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/index.ts 34:7-31',
'ERROR in ./src/index.ts:34:7',
"TS2367: This condition will always return 'false' since the types 'Role' and '\"provider\"' have no overlap.",
' 32 | const user = await login(email, password);',
' 33 |',
Expand Down Expand Up @@ -135,7 +135,7 @@ describe('TypeScript Watch API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/index.ts 34:7-28',
'ERROR in ./src/index.ts:34:7',
`TS2367: This condition will always return 'false' since the types 'Role' and '"admin"' have no overlap.`,
' 32 | const user = await login(email, password);',
' 33 |',
Expand Down Expand Up @@ -177,7 +177,7 @@ describe('TypeScript Watch API', () => {
);
expect(errors).toEqual([
[
'ERROR in ./src/model/User.ts 1:22-30',
'ERROR in ./src/model/User.ts:1:22',
"TS2307: Cannot find module './Role' or its corresponding type declarations.",
" > 1 | import { Role } from './Role';",
' | ^^^^^^^^',
Expand All @@ -197,7 +197,7 @@ describe('TypeScript Watch API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/index.ts 34:7-31',
'ERROR in ./src/index.ts:34:7',
"TS2367: This condition will always return 'false' since the types 'Role' and '\"provider\"' have no overlap.",
' 32 | const user = await login(email, password);',
' 33 |',
Expand Down Expand Up @@ -241,7 +241,7 @@ describe('TypeScript Watch API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/model/User.ts 11:16-25',
'ERROR in ./src/model/User.ts:11:16',
"TS2339: Property 'firstName' does not exist on type 'User'.",
' 9 |',
' 10 | function getUserName(user: User): string {',
Expand All @@ -252,7 +252,7 @@ describe('TypeScript Watch API', () => {
' 14 | export { User, getUserName };',
].join('\n'),
[
'ERROR in ./src/model/User.ts 11:32-40',
'ERROR in ./src/model/User.ts:11:32',
"TS2339: Property 'lastName' does not exist on type 'User'.",
' 9 |',
' 10 | function getUserName(user: User): string {',
Expand All @@ -279,7 +279,7 @@ describe('TypeScript Watch API', () => {
errors = await driver.waitForErrors();
expect(errors).toContain(
[
'ERROR in ./src/index.ts 1:23-39',
'ERROR in ./src/index.ts:1:23',
semver.satisfies(semver.minVersion(dependencies.typescript), '>=4.0.0')
? "TS2307: Cannot find module './authenticate' or its corresponding type declarations."
: "TS2307: Cannot find module './authenticate'.",
Expand Down Expand Up @@ -325,7 +325,7 @@ describe('TypeScript Watch API', () => {
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in ./src/index.ts 34:12-16',
'ERROR in ./src/index.ts:34:12',
"TS2339: Property 'role' does not exist on type 'void'.",
' 32 | const user = await login(email, password);',
' 33 |',
Expand All @@ -336,7 +336,7 @@ describe('TypeScript Watch API', () => {
' 37 | console.log(`Logged in as ${getUserName(user)}`);',
].join('\n'),
[
'ERROR in ./src/index.ts 35:45-49',
'ERROR in ./src/index.ts:35:45',
"TS2345: Argument of type 'void' is not assignable to parameter of type 'User'.",
' 33 |',
" 34 | if (user.role === 'admin') {",
Expand All @@ -347,7 +347,7 @@ describe('TypeScript Watch API', () => {
' 38 | }',
].join('\n'),
[
'ERROR in ./src/index.ts 37:45-49',
'ERROR in ./src/index.ts:37:45',
"TS2345: Argument of type 'void' is not assignable to parameter of type 'User'.",
' 35 | console.log(`Logged in as ${getUserName(user)} [admin].`);',
' 36 | } else {',
Expand Down Expand Up @@ -457,7 +457,7 @@ describe('TypeScript Watch API', () => {

expect(await driver.waitForErrors()).toEqual([
[
'ERROR in ./src/model/User.ts 12:47-59',
'ERROR in ./src/model/User.ts:12:47',
"TS2339: Property 'organization' does not exist on type 'User'.",
' 10 |',
' 11 | function getUserName(user: User): string {',
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/webpack-production-build.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe('Webpack Production Build', () => {
// first error is from the webpack module resolution
expect.anything(),
[
'ERROR in ./src/authenticate.ts 1:22-36',
'ERROR in ./src/authenticate.ts:1:22',
"TS2307: Cannot find module './model/User' or its corresponding type declarations.",
" > 1 | import { User } from './model/User';",
' | ^^^^^^^^^^^^^^',
Expand All @@ -96,7 +96,7 @@ describe('Webpack Production Build', () => {
" 4 | const response = await fetch('/login', {",
].join('\n'),
[
'ERROR in ./src/index.ts 2:29-43',
'ERROR in ./src/index.ts:2:29',
"TS2307: Cannot find module './model/User' or its corresponding type declarations.",
" 1 | import { login } from './authenticate';",
" > 2 | import { getUserName } from './model/User';",
Expand Down
6 changes: 3 additions & 3 deletions test/unit/formatter/webpack-formatter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ describe('formatter/webpack-formatter', () => {
});

it('formats location', () => {
expect(formatter(issue)).toContain(' 1:7-16');
expect(formatter(issue)).toContain(':1:7');
expect(
formatter({
...issue,
location: { start: { line: 1, column: 7 }, end: { line: 10, column: 16 } },
})
).toContain(' 1:7-10:16');
).toContain(':1:7');
});

it('formats issue header like webpack', () => {
expect(formatter(issue)).toEqual(
[`ERROR in ./some/file.ts 1:7-16`, 'TS123: Some issue content', ''].join(os.EOL)
[`ERROR in ./some/file.ts:1:7`, 'TS123: Some issue content', ''].join(os.EOL)
);
});
});

0 comments on commit 4cc5346

Please sign in to comment.