Skip to content

Commit 5a77306

Browse files
authoredFeb 6, 2024
fix(es/parser): Set class property to abstract or override even in error states (#8610)
**Description:** Ensures that a class property with `abstract` or `override` is marked as such in the AST, even in error states.
1 parent 3ee12cf commit 5a77306

File tree

7 files changed

+459
-10
lines changed

7 files changed

+459
-10
lines changed
 

‎crates/swc_ecma_parser/src/parser/class_and_fn.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -622,9 +622,8 @@ impl<I: Tokens> Parser<I> {
622622
self.input.prev_span(),
623623
SyntaxError::TS1029("abstract".into(), "override".into()),
624624
);
625-
} else {
626-
is_abstract = true;
627625
}
626+
is_abstract = true;
628627
}
629628
"override" => {
630629
if is_override {
@@ -644,9 +643,8 @@ impl<I: Tokens> Parser<I> {
644643
);
645644
} else if !self.ctx().has_super_class {
646645
self.emit_err(self.input.prev_span(), SyntaxError::TS4112);
647-
} else {
648-
is_override = true;
649646
}
647+
is_override = true;
650648
}
651649
"readonly" => {
652650
let readonly_span = self.input.prev_span();

‎crates/swc_ecma_parser/tests/tsc/override1.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@
585585
"accessibility": null,
586586
"isAbstract": false,
587587
"isOptional": false,
588-
"isOverride": false
588+
"isOverride": true
589589
}
590590
],
591591
"superClass": null,
@@ -1328,7 +1328,7 @@
13281328
"accessibility": null,
13291329
"isAbstract": false,
13301330
"isOptional": false,
1331-
"isOverride": false
1331+
"isOverride": true
13321332
}
13331333
],
13341334
"superClass": null,

‎crates/swc_ecma_parser/tests/tsc/overrideWithoutNoImplicitOverride1.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"accessibility": null,
8686
"isAbstract": false,
8787
"isOptional": false,
88-
"isOverride": false
88+
"isOverride": true
8989
}
9090
],
9191
"superClass": null,
@@ -182,7 +182,7 @@
182182
"accessibility": null,
183183
"isAbstract": false,
184184
"isOptional": false,
185-
"isOverride": false
185+
"isOverride": true
186186
}
187187
],
188188
"superClass": null,

‎crates/swc_ecma_parser/tests/typescript/class/abstract/input.ts

+12
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,15 @@ export abstract class C {}
55
export default abstract class { }
66
export default abstract class C { }
77
// `abstract class` is not valid as an expression.
8+
9+
export abstract class C {
10+
abstract prop: number;
11+
abstract method(): void;
12+
}
13+
export class C {
14+
// should still have as abstract even though parent is not
15+
abstract prop: number;
16+
abstract method(): void;
17+
// should be abstract in spite of override in wrong place
18+
override abstract method(): string;
19+
}

‎crates/swc_ecma_parser/tests/typescript/class/abstract/input.ts.json

+323-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "Module",
33
"span": {
44
"start": 1,
5-
"end": 200,
5+
"end": 562,
66
"ctxt": 0
77
},
88
"body": [
@@ -148,6 +148,328 @@
148148
"superTypeParams": null,
149149
"implements": []
150150
}
151+
},
152+
{
153+
"type": "ExportDeclaration",
154+
"span": {
155+
"start": 253,
156+
"end": 332,
157+
"ctxt": 0
158+
},
159+
"declaration": {
160+
"type": "ClassDeclaration",
161+
"identifier": {
162+
"type": "Identifier",
163+
"span": {
164+
"start": 275,
165+
"end": 276,
166+
"ctxt": 0
167+
},
168+
"value": "C",
169+
"optional": false
170+
},
171+
"declare": false,
172+
"span": {
173+
"start": 260,
174+
"end": 332,
175+
"ctxt": 0
176+
},
177+
"decorators": [],
178+
"body": [
179+
{
180+
"type": "ClassProperty",
181+
"span": {
182+
"start": 281,
183+
"end": 303,
184+
"ctxt": 0
185+
},
186+
"key": {
187+
"type": "Identifier",
188+
"span": {
189+
"start": 290,
190+
"end": 294,
191+
"ctxt": 0
192+
},
193+
"value": "prop",
194+
"optional": false
195+
},
196+
"value": null,
197+
"typeAnnotation": {
198+
"type": "TsTypeAnnotation",
199+
"span": {
200+
"start": 294,
201+
"end": 302,
202+
"ctxt": 0
203+
},
204+
"typeAnnotation": {
205+
"type": "TsKeywordType",
206+
"span": {
207+
"start": 296,
208+
"end": 302,
209+
"ctxt": 0
210+
},
211+
"kind": "number"
212+
}
213+
},
214+
"isStatic": false,
215+
"decorators": [],
216+
"accessibility": null,
217+
"isAbstract": true,
218+
"isOptional": false,
219+
"isOverride": false,
220+
"readonly": false,
221+
"declare": false,
222+
"definite": false
223+
},
224+
{
225+
"type": "ClassMethod",
226+
"span": {
227+
"start": 306,
228+
"end": 330,
229+
"ctxt": 0
230+
},
231+
"key": {
232+
"type": "Identifier",
233+
"span": {
234+
"start": 315,
235+
"end": 321,
236+
"ctxt": 0
237+
},
238+
"value": "method",
239+
"optional": false
240+
},
241+
"function": {
242+
"params": [],
243+
"decorators": [],
244+
"span": {
245+
"start": 306,
246+
"end": 330,
247+
"ctxt": 0
248+
},
249+
"body": null,
250+
"generator": false,
251+
"async": false,
252+
"typeParameters": null,
253+
"returnType": {
254+
"type": "TsTypeAnnotation",
255+
"span": {
256+
"start": 323,
257+
"end": 329,
258+
"ctxt": 0
259+
},
260+
"typeAnnotation": {
261+
"type": "TsKeywordType",
262+
"span": {
263+
"start": 325,
264+
"end": 329,
265+
"ctxt": 0
266+
},
267+
"kind": "void"
268+
}
269+
}
270+
},
271+
"kind": "method",
272+
"isStatic": false,
273+
"accessibility": null,
274+
"isAbstract": true,
275+
"isOptional": false,
276+
"isOverride": false
277+
}
278+
],
279+
"superClass": null,
280+
"isAbstract": true,
281+
"typeParams": null,
282+
"superTypeParams": null,
283+
"implements": []
284+
}
285+
},
286+
{
287+
"type": "ExportDeclaration",
288+
"span": {
289+
"start": 333,
290+
"end": 562,
291+
"ctxt": 0
292+
},
293+
"declaration": {
294+
"type": "ClassDeclaration",
295+
"identifier": {
296+
"type": "Identifier",
297+
"span": {
298+
"start": 346,
299+
"end": 347,
300+
"ctxt": 0
301+
},
302+
"value": "C",
303+
"optional": false
304+
},
305+
"declare": false,
306+
"span": {
307+
"start": 340,
308+
"end": 562,
309+
"ctxt": 0
310+
},
311+
"decorators": [],
312+
"body": [
313+
{
314+
"type": "ClassProperty",
315+
"span": {
316+
"start": 413,
317+
"end": 435,
318+
"ctxt": 0
319+
},
320+
"key": {
321+
"type": "Identifier",
322+
"span": {
323+
"start": 422,
324+
"end": 426,
325+
"ctxt": 0
326+
},
327+
"value": "prop",
328+
"optional": false
329+
},
330+
"value": null,
331+
"typeAnnotation": {
332+
"type": "TsTypeAnnotation",
333+
"span": {
334+
"start": 426,
335+
"end": 434,
336+
"ctxt": 0
337+
},
338+
"typeAnnotation": {
339+
"type": "TsKeywordType",
340+
"span": {
341+
"start": 428,
342+
"end": 434,
343+
"ctxt": 0
344+
},
345+
"kind": "number"
346+
}
347+
},
348+
"isStatic": false,
349+
"decorators": [],
350+
"accessibility": null,
351+
"isAbstract": true,
352+
"isOptional": false,
353+
"isOverride": false,
354+
"readonly": false,
355+
"declare": false,
356+
"definite": false
357+
},
358+
{
359+
"type": "ClassMethod",
360+
"span": {
361+
"start": 438,
362+
"end": 462,
363+
"ctxt": 0
364+
},
365+
"key": {
366+
"type": "Identifier",
367+
"span": {
368+
"start": 447,
369+
"end": 453,
370+
"ctxt": 0
371+
},
372+
"value": "method",
373+
"optional": false
374+
},
375+
"function": {
376+
"params": [],
377+
"decorators": [],
378+
"span": {
379+
"start": 438,
380+
"end": 462,
381+
"ctxt": 0
382+
},
383+
"body": null,
384+
"generator": false,
385+
"async": false,
386+
"typeParameters": null,
387+
"returnType": {
388+
"type": "TsTypeAnnotation",
389+
"span": {
390+
"start": 455,
391+
"end": 461,
392+
"ctxt": 0
393+
},
394+
"typeAnnotation": {
395+
"type": "TsKeywordType",
396+
"span": {
397+
"start": 457,
398+
"end": 461,
399+
"ctxt": 0
400+
},
401+
"kind": "void"
402+
}
403+
}
404+
},
405+
"kind": "method",
406+
"isStatic": false,
407+
"accessibility": null,
408+
"isAbstract": true,
409+
"isOptional": false,
410+
"isOverride": false
411+
},
412+
{
413+
"type": "ClassMethod",
414+
"span": {
415+
"start": 525,
416+
"end": 560,
417+
"ctxt": 0
418+
},
419+
"key": {
420+
"type": "Identifier",
421+
"span": {
422+
"start": 543,
423+
"end": 549,
424+
"ctxt": 0
425+
},
426+
"value": "method",
427+
"optional": false
428+
},
429+
"function": {
430+
"params": [],
431+
"decorators": [],
432+
"span": {
433+
"start": 525,
434+
"end": 560,
435+
"ctxt": 0
436+
},
437+
"body": null,
438+
"generator": false,
439+
"async": false,
440+
"typeParameters": null,
441+
"returnType": {
442+
"type": "TsTypeAnnotation",
443+
"span": {
444+
"start": 551,
445+
"end": 559,
446+
"ctxt": 0
447+
},
448+
"typeAnnotation": {
449+
"type": "TsKeywordType",
450+
"span": {
451+
"start": 553,
452+
"end": 559,
453+
"ctxt": 0
454+
},
455+
"kind": "string"
456+
}
457+
}
458+
},
459+
"kind": "method",
460+
"isStatic": false,
461+
"accessibility": null,
462+
"isAbstract": true,
463+
"isOptional": false,
464+
"isOverride": true
465+
}
466+
],
467+
"superClass": null,
468+
"isAbstract": false,
469+
"typeParams": null,
470+
"superTypeParams": null,
471+
"implements": []
472+
}
151473
}
152474
],
153475
"interpreter": null

‎crates/swc_ecma_parser/tests/typescript/class/override/input.ts

+6
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@ class C extends B {
22
override prop = 5;
33
override method() {
44
}
5+
}
6+
// even without an extends it should set is_override
7+
class C {
8+
override prop = 5;
9+
override method() {
10+
}
511
}

‎crates/swc_ecma_parser/tests/typescript/class/override/input.ts.json

+112-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "Script",
33
"span": {
44
"start": 1,
5-
"end": 69,
5+
"end": 181,
66
"ctxt": 0
77
},
88
"body": [
@@ -125,6 +125,117 @@
125125
"typeParams": null,
126126
"superTypeParams": null,
127127
"implements": []
128+
},
129+
{
130+
"type": "ClassDeclaration",
131+
"identifier": {
132+
"type": "Identifier",
133+
"span": {
134+
"start": 129,
135+
"end": 130,
136+
"ctxt": 0
137+
},
138+
"value": "C",
139+
"optional": false
140+
},
141+
"declare": false,
142+
"span": {
143+
"start": 123,
144+
"end": 181,
145+
"ctxt": 0
146+
},
147+
"decorators": [],
148+
"body": [
149+
{
150+
"type": "ClassProperty",
151+
"span": {
152+
"start": 135,
153+
"end": 153,
154+
"ctxt": 0
155+
},
156+
"key": {
157+
"type": "Identifier",
158+
"span": {
159+
"start": 144,
160+
"end": 148,
161+
"ctxt": 0
162+
},
163+
"value": "prop",
164+
"optional": false
165+
},
166+
"value": {
167+
"type": "NumericLiteral",
168+
"span": {
169+
"start": 151,
170+
"end": 152,
171+
"ctxt": 0
172+
},
173+
"value": 5.0,
174+
"raw": "5"
175+
},
176+
"typeAnnotation": null,
177+
"isStatic": false,
178+
"decorators": [],
179+
"accessibility": null,
180+
"isAbstract": false,
181+
"isOptional": false,
182+
"isOverride": true,
183+
"readonly": false,
184+
"declare": false,
185+
"definite": false
186+
},
187+
{
188+
"type": "ClassMethod",
189+
"span": {
190+
"start": 156,
191+
"end": 179,
192+
"ctxt": 0
193+
},
194+
"key": {
195+
"type": "Identifier",
196+
"span": {
197+
"start": 165,
198+
"end": 171,
199+
"ctxt": 0
200+
},
201+
"value": "method",
202+
"optional": false
203+
},
204+
"function": {
205+
"params": [],
206+
"decorators": [],
207+
"span": {
208+
"start": 156,
209+
"end": 179,
210+
"ctxt": 0
211+
},
212+
"body": {
213+
"type": "BlockStatement",
214+
"span": {
215+
"start": 174,
216+
"end": 179,
217+
"ctxt": 0
218+
},
219+
"stmts": []
220+
},
221+
"generator": false,
222+
"async": false,
223+
"typeParameters": null,
224+
"returnType": null
225+
},
226+
"kind": "method",
227+
"isStatic": false,
228+
"accessibility": null,
229+
"isAbstract": false,
230+
"isOptional": false,
231+
"isOverride": true
232+
}
233+
],
234+
"superClass": null,
235+
"isAbstract": false,
236+
"typeParams": null,
237+
"superTypeParams": null,
238+
"implements": []
128239
}
129240
],
130241
"interpreter": null

0 commit comments

Comments
 (0)
Please sign in to comment.