Skip to content

Commit db33196

Browse files
karankiriBoshen
andauthored
feat(parser): adds typescript rule for empty argument list (#13730)
Co-authored-by: Boshen <boshenc@gmail.com>
1 parent f5f37c4 commit db33196

File tree

11 files changed

+256
-92
lines changed

11 files changed

+256
-92
lines changed

crates/oxc_linter/src/rules/typescript/array_type.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,10 +1272,6 @@ const instance = new MyClass<number>(42);",
12721272
"type fooIntersection = Array<string & number>;",
12731273
Some(serde_json::json!([{"default":"array"}])),
12741274
),
1275-
("let x: Array;", Some(serde_json::json!([{"default":"array"}]))),
1276-
("let x: Array<>;", Some(serde_json::json!([{"default":"array"}]))),
1277-
("let x: Array;", Some(serde_json::json!([{"default":"array-simple"}]))),
1278-
("let x: Array<>;", Some(serde_json::json!([{"default":"array-simple"}]))),
12791275
(
12801276
"let x: Array<number> = [1] as number[];",
12811277
Some(serde_json::json!([{"default":"generic"}])),
@@ -1906,10 +1902,6 @@ export const test8 = testFn<Array<string>, number[]>([]);",
19061902
"type fooIntersection = (string & number)[];",
19071903
Some(serde_json::json!([{"default":"array"}])),
19081904
),
1909-
("let x: Array;", "let x: any[];", Some(serde_json::json!([{"default":"array"}]))),
1910-
("let x: Array<>;", "let x: any[];", Some(serde_json::json!([{"default":"array"}]))),
1911-
("let x: Array;", "let x: any[];", Some(serde_json::json!([{"default":"array-simple"}]))),
1912-
("let x: Array<>;", "let x: any[];", Some(serde_json::json!([{"default":"array-simple"}]))),
19131905
(
19141906
"let x: Array<number> = [1] as number[];",
19151907
"let x: Array<number> = [1] as Array<number>;",

crates/oxc_linter/src/snapshots/typescript_array_type.snap

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -541,34 +541,6 @@ source: crates/oxc_linter/src/tester.rs
541541
╰────
542542
help: Replace `Array<string & number>` with `(string & number)[]`.
543543

544-
⚠ typescript-eslint(array-type): Array type using 'Array<any>' is forbidden. Use 'any[]' instead.
545-
╭─[array_type.ts:1:8]
546-
1 │ let x: Array;
547-
· ─────
548-
╰────
549-
help: Replace `Array` with `any[]`.
550-
551-
⚠ typescript-eslint(array-type): Array type using 'Array<any>' is forbidden. Use 'any[]' instead.
552-
╭─[array_type.ts:1:8]
553-
1 │ let x: Array<>;
554-
· ───────
555-
╰────
556-
help: Replace `Array<>` with `any[]`.
557-
558-
⚠ typescript-eslint(array-type): Array type using 'Array<any>' is forbidden for simple types. Use 'any[]' instead.
559-
╭─[array_type.ts:1:8]
560-
1 │ let x: Array;
561-
· ─────
562-
╰────
563-
help: Replace `Array` with `any[]`.
564-
565-
⚠ typescript-eslint(array-type): Array type using 'Array<any>' is forbidden for simple types. Use 'any[]' instead.
566-
╭─[array_type.ts:1:8]
567-
1 │ let x: Array<>;
568-
· ───────
569-
╰────
570-
help: Replace `Array<>` with `any[]`.
571-
572544
⚠ typescript-eslint(array-type): Array type using 'number[]' is forbidden. Use 'Array<number>' instead.
573545
╭─[array_type.ts:1:31]
574546
1 │ let x: Array<number> = [1] as number[];

crates/oxc_parser/src/diagnostics.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,11 @@ pub fn ts_empty_type_parameter_list(span: Span) -> OxcDiagnostic {
412412
ts_error("1098", "Type parameter list cannot be empty.").with_label(span)
413413
}
414414

415+
#[cold]
416+
pub fn ts_empty_type_argument_list(span: Span) -> OxcDiagnostic {
417+
ts_error("1099", "Type argument list cannot be empty.").with_label(span)
418+
}
419+
415420
#[cold]
416421
pub fn unexpected_super(span: Span) -> OxcDiagnostic {
417422
OxcDiagnostic::error("'super' can only be used with function calls or in property accesses")

crates/oxc_parser/src/ts/types.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -818,9 +818,11 @@ impl<'a> ParserImpl<'a> {
818818
let (params, _) =
819819
self.parse_delimited_list(Kind::RAngle, Kind::Comma, Self::parse_ts_type);
820820
self.expect(Kind::RAngle);
821-
return Some(
822-
self.ast.alloc_ts_type_parameter_instantiation(self.end_span(span), params),
823-
);
821+
let span = self.end_span(span);
822+
if params.is_empty() {
823+
self.error(diagnostics::ts_empty_type_argument_list(span));
824+
}
825+
return Some(self.ast.alloc_ts_type_parameter_instantiation(span, params));
824826
}
825827
None
826828
}
@@ -834,9 +836,11 @@ impl<'a> ParserImpl<'a> {
834836
let (params, _) =
835837
self.parse_delimited_list(Kind::RAngle, Kind::Comma, Self::parse_ts_type);
836838
self.expect(Kind::RAngle);
837-
return Some(
838-
self.ast.alloc_ts_type_parameter_instantiation(self.end_span(span), params),
839-
);
839+
let span = self.end_span(span);
840+
if params.is_empty() {
841+
self.error(diagnostics::ts_empty_type_argument_list(span));
842+
}
843+
return Some(self.ast.alloc_ts_type_parameter_instantiation(span, params));
840844
}
841845
None
842846
}
@@ -859,7 +863,11 @@ impl<'a> ParserImpl<'a> {
859863
if !self.can_follow_type_arguments_in_expr() {
860864
return self.unexpected();
861865
}
862-
self.ast.alloc_ts_type_parameter_instantiation(self.end_span(span), params)
866+
let span = self.end_span(span);
867+
if params.is_empty() {
868+
self.error(diagnostics::ts_empty_type_argument_list(span));
869+
}
870+
self.ast.alloc_ts_type_parameter_instantiation(span, params)
863871
}
864872

865873
fn can_follow_type_arguments_in_expr(&mut self) -> bool {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo<>()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
new Foo<>()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class Foo {property: Bar<> = 1}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const foo: Foo<> = 1

tasks/coverage/snapshots/parser_babel.snap

Lines changed: 97 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ commit: 41d96516
33
parser_babel Summary:
44
AST Parsed : 2407/2423 (99.34%)
55
Positive Passed: 2385/2423 (98.43%)
6-
Negative Passed: 1649/1755 (93.96%)
6+
Negative Passed: 1665/1755 (94.87%)
77
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-startindex-and-startline-specified-without-startcolumn/input.js
88

99
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/startline-and-startcolumn-specified/input.js
@@ -158,38 +158,6 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/ty
158158

159159
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/regression/keyword-qualified-type-disallowed-babel-7/input.ts
160160

161-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-function/input.ts
162-
163-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-function-babel-7/input.ts
164-
165-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-extends/input.ts
166-
167-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-extends-babel-7/input.ts
168-
169-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-implements/input.ts
170-
171-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-implements-babel-7/input.ts
172-
173-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-new/input.ts
174-
175-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-new-babel-7/input.ts
176-
177-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-superclass/input.ts
178-
179-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-superclass-babel-7/input.ts
180-
181-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-tsx/input.ts
182-
183-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-tsx-babel-7/input.ts
184-
185-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-import/input.ts
186-
187-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-import-babel-7/input.ts
188-
189-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-ref/input.ts
190-
191-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-ref-babel-7/input.ts
192-
193161
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/instantiation-expression-property-access/input.ts
194162

195163
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/type-arguments/instantiation-expression-property-access-babel-7/input.ts
@@ -14203,6 +14171,102 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
1420314171
· ──
1420414172
╰────
1420514173

14174+
× TS(1099): Type argument list cannot be empty.
14175+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-function/input.ts:1:4]
14176+
1 │ foo<>()
14177+
· ──
14178+
╰────
14179+
14180+
× TS(1099): Type argument list cannot be empty.
14181+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-function-babel-7/input.ts:1:4]
14182+
1 │ foo<>()
14183+
· ──
14184+
╰────
14185+
14186+
× TS(1099): Type argument list cannot be empty.
14187+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-extends/input.ts:1:22]
14188+
1 │ interface A extends B<> {}
14189+
· ──
14190+
╰────
14191+
14192+
× TS(1099): Type argument list cannot be empty.
14193+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-extends-babel-7/input.ts:1:22]
14194+
1 │ interface A extends B<> {}
14195+
· ──
14196+
╰────
14197+
14198+
× TS(1099): Type argument list cannot be empty.
14199+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-implements/input.ts:1:21]
14200+
1 │ class A implements B<> {}
14201+
· ──
14202+
╰────
14203+
14204+
× TS(1099): Type argument list cannot be empty.
14205+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-interface-implements-babel-7/input.ts:1:21]
14206+
1 │ class A implements B<> {}
14207+
· ──
14208+
╰────
14209+
14210+
× TS(1099): Type argument list cannot be empty.
14211+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-new/input.ts:1:6]
14212+
1 │ new A<>();
14213+
· ──
14214+
╰────
14215+
14216+
× TS(1099): Type argument list cannot be empty.
14217+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-new-babel-7/input.ts:1:6]
14218+
1 │ new A<>();
14219+
· ──
14220+
╰────
14221+
14222+
× TS(1099): Type argument list cannot be empty.
14223+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-superclass/input.ts:1:18]
14224+
1 │ class A extends B<> {}
14225+
· ──
14226+
╰────
14227+
14228+
× TS(1099): Type argument list cannot be empty.
14229+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-superclass-babel-7/input.ts:1:18]
14230+
1 │ class A extends B<> {}
14231+
· ──
14232+
╰────
14233+
14234+
× TS(1099): Type argument list cannot be empty.
14235+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-tsx/input.ts:1:14]
14236+
1 │ var a = <Comp<>></Comp>
14237+
· ──
14238+
╰────
14239+
14240+
× TS(1099): Type argument list cannot be empty.
14241+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-tsx-babel-7/input.ts:1:14]
14242+
1 │ var a = <Comp<>></Comp>
14243+
· ──
14244+
╰────
14245+
14246+
× TS(1099): Type argument list cannot be empty.
14247+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-import/input.ts:1:18]
14248+
1 │ let a: import("")<>;
14249+
· ──
14250+
╰────
14251+
14252+
× TS(1099): Type argument list cannot be empty.
14253+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-import-babel-7/input.ts:1:18]
14254+
1 │ let a: import("")<>;
14255+
· ──
14256+
╰────
14257+
14258+
× TS(1099): Type argument list cannot be empty.
14259+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-ref/input.ts:1:11]
14260+
1 │ let a: Foo<>;
14261+
· ──
14262+
╰────
14263+
14264+
× TS(1099): Type argument list cannot be empty.
14265+
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/empty-type-ref-babel-7/input.ts:1:11]
14266+
1 │ let a: Foo<>;
14267+
· ──
14268+
╰────
14269+
1420614270
× Expected a semicolon or an implicit semicolon after a statement, but found none
1420714271
╭─[babel/packages/babel-parser/test/fixtures/typescript/type-arguments/new-without-arguments-missing-semicolon/input.ts:1:9]
1420814272
1 │ new A<T> if (0);

tasks/coverage/snapshots/parser_misc.snap

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
parser_misc Summary:
22
AST Parsed : 49/49 (100.00%)
33
Positive Passed: 49/49 (100.00%)
4-
Negative Passed: 86/86 (100.00%)
4+
Negative Passed: 90/90 (100.00%)
55

66
× Cannot assign to 'arguments' in strict mode
77
╭─[misc/fail/arguments-eval.ts:1:10]
@@ -2833,6 +2833,30 @@ Negative Passed: 86/86 (100.00%)
28332833
17 │ };
28342834
╰────
28352835
2836+
× TS(1099): Type argument list cannot be empty.
2837+
╭─[misc/fail/oxc-13617-1.ts:1:4]
2838+
1 │ foo<>()
2839+
· ──
2840+
╰────
2841+
2842+
× TS(1099): Type argument list cannot be empty.
2843+
╭─[misc/fail/oxc-13617-2.ts:1:8]
2844+
1 │ new Foo<>()
2845+
· ──
2846+
╰────
2847+
2848+
× TS(1099): Type argument list cannot be empty.
2849+
╭─[misc/fail/oxc-13617-3.ts:1:25]
2850+
1 │ class Foo {property: Bar<> = 1}
2851+
· ──
2852+
╰────
2853+
2854+
× TS(1099): Type argument list cannot be empty.
2855+
╭─[misc/fail/oxc-13617-4.ts:1:15]
2856+
1 │ const foo: Foo<> = 1
2857+
· ──
2858+
╰────
2859+
28362860
× Unexpected token
28372861
╭─[misc/fail/oxc-169.js:2:1]
28382862
1 │ 1<(V=82<<t-j0<(V=$<LBI<(V=ut<I<(V=$<LBI<(V=uIV=82<<t-j0<(V=$<LBI<(V=ut<I<(V=$<LBI<(V<II>

0 commit comments

Comments
 (0)