Skip to content

Commit d2bcaea

Browse files
authored
Throw errors for invalid TSEmptyBodyFunctionExpression node (#12982)
1 parent 1bec824 commit d2bcaea

File tree

6 files changed

+195
-10
lines changed

6 files changed

+195
-10
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#### Stop parsing invalid code (#12982 by @fisker)
2+
3+
<!-- prettier-ignore -->
4+
```tsx
5+
// Input
6+
const object = ({ methodName() });
7+
8+
// Prettier stable
9+
const object = { methodName(); };
10+
11+
// Prettier main
12+
SyntaxError: Unexpected token. (1:29)
13+
> 1 | const object = ({ methodName() });
14+
| ^^
15+
```

src/language-js/parse/postprocess/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const isTypeCastComment = require("../../utils/is-type-cast-comment.js");
66
const getLast = require("../../../utils/get-last.js");
77
const visitNode = require("./visit-node.js");
88
const { throwErrorForInvalidNodes } = require("./typescript.js");
9+
const throwSyntaxError = require("./throw-syntax-error.js");
910

1011
function postprocess(ast, options) {
1112
if (
@@ -102,6 +103,20 @@ function postprocess(ast, options) {
102103
};
103104
}
104105
break;
106+
case "ObjectExpression":
107+
// #12963
108+
if (options.parser === "typescript") {
109+
const invalidProperty = node.properties.find(
110+
(property) =>
111+
property.type === "Property" &&
112+
property.value.type === "TSEmptyBodyFunctionExpression"
113+
);
114+
if (invalidProperty) {
115+
throwSyntaxError(invalidProperty.value, "Unexpected token.");
116+
}
117+
}
118+
break;
119+
105120
case "SequenceExpression": {
106121
// Babel (unlike other parsers) includes spaces and comments in the range. Let's unify this.
107122
const lastExpression = getLast(node.expressions);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"use strict";
2+
const createError = require("../../../common/parser-create-error.js");
3+
4+
function throwSyntaxError(node, message) {
5+
const { start, end } = node.loc;
6+
throw createError(message, {
7+
start: { line: start.line, column: start.column + 1 },
8+
end: { line: end.line, column: end.column + 1 },
9+
});
10+
}
11+
12+
module.exports = throwSyntaxError;

src/language-js/parse/postprocess/typescript.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
"use strict";
22

3-
const createError = require("../../../common/parser-create-error.js");
43
const visitNode = require("./visit-node.js");
5-
6-
function throwSyntaxError(node, message) {
7-
const { start, end } = node.loc;
8-
throw createError(message, {
9-
start: { line: start.line, column: start.column + 1 },
10-
end: { line: end.line, column: end.column + 1 },
11-
});
12-
}
4+
const throwSyntaxError = require("./throw-syntax-error.js");
135

146
// Invalid decorators are removed since `@typescript-eslint/typescript-estree` v4
157
// https://github.com/typescript-eslint/typescript-eslint/pull/2375
@@ -73,6 +65,7 @@ function throwErrorForInvalidNodes(ast, options) {
7365
if (esTreeNode !== node) {
7466
return;
7567
}
68+
7669
throwErrorForInvalidDecorator(tsNode, esTreeNode, tsNodeToESTreeNodeMap);
7770
throwErrorForInvalidAbstractProperty(tsNode, esTreeNode);
7871
});

tests/format/misc/errors/invalid/__snapshots__/jsfmt.spec.js.snap

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,92 +156,236 @@ exports[`snippet: #1 [typescript] format 1`] = `
156156
| ^"
157157
`;
158158
159+
exports[`snippet: #2 [acorn] format 1`] = `
160+
"Unexpected token (1:13)
161+
> 1 | ({ method() })
162+
| ^"
163+
`;
164+
159165
exports[`snippet: #2 [babel] format 1`] = `
166+
"Unexpected token, expected "{" (1:13)
167+
> 1 | ({ method() })
168+
| ^"
169+
`;
170+
171+
exports[`snippet: #2 [babel] format 2`] = `
160172
"Invalid parenthesized assignment pattern. (1:1)
161173
> 1 | (a = 1) = 2
162174
| ^"
163175
`;
164176
165177
exports[`snippet: #2 [babel-flow] format 1`] = `
178+
"Unexpected token, expected "{" (1:13)
179+
> 1 | ({ method() })
180+
| ^"
181+
`;
182+
183+
exports[`snippet: #2 [babel-flow] format 2`] = `
166184
"Invalid parenthesized assignment pattern. (1:1)
167185
> 1 | (a = 1) = 2
168186
| ^"
169187
`;
170188
171189
exports[`snippet: #2 [babel-ts] format 1`] = `
190+
"Unexpected token, expected "{" (1:13)
191+
> 1 | ({ method() })
192+
| ^"
193+
`;
194+
195+
exports[`snippet: #2 [babel-ts] format 2`] = `
172196
"Invalid parenthesized assignment pattern. (1:1)
173197
> 1 | (a = 1) = 2
174198
| ^"
175199
`;
176200
201+
exports[`snippet: #2 [espree] format 1`] = `
202+
"Unexpected token } (1:13)
203+
> 1 | ({ method() })
204+
| ^"
205+
`;
206+
177207
exports[`snippet: #2 [flow] format 1`] = `
208+
"Unexpected token \`}\`, expected the token \`{\` (1:13)
209+
> 1 | ({ method() })
210+
| ^"
211+
`;
212+
213+
exports[`snippet: #2 [flow] format 2`] = `
178214
"Invalid left-hand side in assignment (1:2)
179215
> 1 | (a = 1) = 2
180216
| ^^^^^"
181217
`;
182218
183219
exports[`snippet: #2 [meriyah] format 1`] = `
220+
"Expected '{' (1:13)
221+
> 1 | ({ method() })
222+
| ^"
223+
`;
224+
225+
exports[`snippet: #2 [meriyah] format 2`] = `
184226
"Invalid left-hand side in assignment (1:9)
185227
> 1 | (a = 1) = 2
186228
| ^"
187229
`;
188230
231+
exports[`snippet: #2 [typescript] format 1`] = `
232+
"Unexpected token. (1:10)
233+
> 1 | ({ method() })
234+
| ^^"
235+
`;
236+
237+
exports[`snippet: #3 [acorn] format 1`] = `
238+
"Unexpected token (1:15)
239+
> 1 | ({ method({}) })
240+
| ^"
241+
`;
242+
189243
exports[`snippet: #3 [babel] format 1`] = `
244+
"Unexpected token, expected "{" (1:15)
245+
> 1 | ({ method({}) })
246+
| ^"
247+
`;
248+
249+
exports[`snippet: #3 [babel] format 2`] = `
190250
"Invalid parenthesized assignment pattern. (1:1)
191251
> 1 | (a += b) = 1
192252
| ^"
193253
`;
194254
195255
exports[`snippet: #3 [babel-flow] format 1`] = `
256+
"Unexpected token, expected "{" (1:15)
257+
> 1 | ({ method({}) })
258+
| ^"
259+
`;
260+
261+
exports[`snippet: #3 [babel-flow] format 2`] = `
196262
"Invalid parenthesized assignment pattern. (1:1)
197263
> 1 | (a += b) = 1
198264
| ^"
199265
`;
200266
201267
exports[`snippet: #3 [babel-ts] format 1`] = `
268+
"Unexpected token, expected "{" (1:15)
269+
> 1 | ({ method({}) })
270+
| ^"
271+
`;
272+
273+
exports[`snippet: #3 [babel-ts] format 2`] = `
202274
"Invalid parenthesized assignment pattern. (1:1)
203275
> 1 | (a += b) = 1
204276
| ^"
205277
`;
206278
279+
exports[`snippet: #3 [espree] format 1`] = `
280+
"Unexpected token } (1:15)
281+
> 1 | ({ method({}) })
282+
| ^"
283+
`;
284+
207285
exports[`snippet: #3 [flow] format 1`] = `
286+
"Unexpected token \`}\`, expected the token \`{\` (1:15)
287+
> 1 | ({ method({}) })
288+
| ^"
289+
`;
290+
291+
exports[`snippet: #3 [flow] format 2`] = `
208292
"Invalid left-hand side in assignment (1:2)
209293
> 1 | (a += b) = 1
210294
| ^^^^^^"
211295
`;
212296
213297
exports[`snippet: #3 [meriyah] format 1`] = `
298+
"Expected '{' (1:15)
299+
> 1 | ({ method({}) })
300+
| ^"
301+
`;
302+
303+
exports[`snippet: #3 [meriyah] format 2`] = `
214304
"Invalid left-hand side in assignment (1:10)
215305
> 1 | (a += b) = 1
216306
| ^"
217307
`;
218308
309+
exports[`snippet: #3 [typescript] format 1`] = `
310+
"Unexpected token. (1:10)
311+
> 1 | ({ method({}) })
312+
| ^^^^"
313+
`;
314+
315+
exports[`snippet: #4 [acorn] format 1`] = `
316+
"Unexpected token (1:23)
317+
> 1 | ({ method(parameter,) })
318+
| ^"
319+
`;
320+
219321
exports[`snippet: #4 [babel] format 1`] = `
322+
"Unexpected token, expected "{" (1:23)
323+
> 1 | ({ method(parameter,) })
324+
| ^"
325+
`;
326+
327+
exports[`snippet: #4 [babel] format 2`] = `
220328
"Invalid left-hand side in parenthesized expression. (1:2)
221329
> 1 | (a = b) += 1
222330
| ^"
223331
`;
224332
225333
exports[`snippet: #4 [babel-flow] format 1`] = `
334+
"Unexpected token, expected "{" (1:23)
335+
> 1 | ({ method(parameter,) })
336+
| ^"
337+
`;
338+
339+
exports[`snippet: #4 [babel-flow] format 2`] = `
226340
"Invalid left-hand side in parenthesized expression. (1:2)
227341
> 1 | (a = b) += 1
228342
| ^"
229343
`;
230344
231345
exports[`snippet: #4 [babel-ts] format 1`] = `
346+
"Unexpected token, expected "{" (1:23)
347+
> 1 | ({ method(parameter,) })
348+
| ^"
349+
`;
350+
351+
exports[`snippet: #4 [babel-ts] format 2`] = `
232352
"Invalid left-hand side in parenthesized expression. (1:2)
233353
> 1 | (a = b) += 1
234354
| ^"
235355
`;
236356
357+
exports[`snippet: #4 [espree] format 1`] = `
358+
"Unexpected token } (1:23)
359+
> 1 | ({ method(parameter,) })
360+
| ^"
361+
`;
362+
237363
exports[`snippet: #4 [flow] format 1`] = `
364+
"Unexpected token \`}\`, expected the token \`{\` (1:23)
365+
> 1 | ({ method(parameter,) })
366+
| ^"
367+
`;
368+
369+
exports[`snippet: #4 [flow] format 2`] = `
238370
"Invalid left-hand side in assignment (1:2)
239371
> 1 | (a = b) += 1
240372
| ^^^^^"
241373
`;
242374
243375
exports[`snippet: #4 [meriyah] format 1`] = `
376+
"Expected '{' (1:23)
377+
> 1 | ({ method(parameter,) })
378+
| ^"
379+
`;
380+
381+
exports[`snippet: #4 [meriyah] format 2`] = `
244382
"Invalid left-hand side in assignment (1:10)
245383
> 1 | (a = b) += 1
246384
| ^"
247385
`;
386+
387+
exports[`snippet: #4 [typescript] format 1`] = `
388+
"Unexpected token. (1:10)
389+
> 1 | ({ method(parameter,) })
390+
| ^^^^^^^^^^^^"
391+
`;

tests/format/misc/errors/invalid/jsfmt.spec.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
run_spec(
22
{
33
dirname: __dirname,
4-
snippets: ["for each (a in b) {}", "class switch() {}"],
4+
snippets: [
5+
"for each (a in b) {}",
6+
"class switch() {}",
7+
"({ method() })",
8+
"({ method({}) })",
9+
"({ method(parameter,) })",
10+
],
511
},
612
[
713
"babel",

0 commit comments

Comments
 (0)