Skip to content

Commit 4fe9151

Browse files
authored
fix(parser): Handle JSDocUnknownType correctly (#10363)
Current behavior: ```ts type G<T> = T; type C1 = G<?>; // Parse failed 👀 ``` TS parses this as `TypeReference > JSDocUnknownType`. > REPL: https://www.typescriptlang.org/play/?noCheck=true#code/C4TwDgpgBA4gPAFQHxQLxQQbgFCklAYQEY1Y4B+JTIA > Parser: https://github.com/microsoft/TypeScript/blob/83dc0bb2ed91fe0815ab28dc3ff95fae7425e413/src/compiler/parser.ts#L3847 And also this PR fixes these: ```ts type X = [ 1?, // TSOptionalType ?1, // JSDocUnknownType 👀 ?1?, // JSDocUnknownType 👀 ?1!, // JSDocUnknownType 👀 ]; ``` to ```ts type X = [ 1?, // TSOptionalType ?1, // JSDocNullableType ?1?, // JSDocNullableType > JSDocNullableType ?1!, // JSDocNullableType > JSDocNonNullableType ]; ``` This will result in the same behavior as TS and ESLint-TS.
1 parent cc18238 commit 4fe9151

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

crates/oxc_parser/src/ts/types.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,20 +1318,18 @@ impl<'a> ParserImpl<'a> {
13181318
fn parse_js_doc_unknown_or_nullable_type(&mut self) -> Result<TSType<'a>> {
13191319
let span = self.start_span();
13201320
self.bump_any(); // bump `?`
1321-
let type_annotation = self.parse_ts_type()?;
1322-
let span = self.end_span(span);
13231321
if matches!(
13241322
self.cur_kind(),
13251323
Kind::Comma | Kind::RCurly | Kind::RParen | Kind::RAngle | Kind::Eq | Kind::Pipe
13261324
) {
1327-
Ok(self.ast.ts_type_js_doc_unknown_type(span))
1328-
} else {
1329-
Ok(self.ast.ts_type_js_doc_nullable_type(
1330-
span,
1331-
type_annotation,
1332-
/* postfix */ false,
1333-
))
1325+
return Ok(self.ast.ts_type_js_doc_unknown_type(self.end_span(span)));
13341326
}
1327+
let type_annotation = self.parse_ts_type()?;
1328+
Ok(self.ast.ts_type_js_doc_nullable_type(
1329+
self.end_span(span),
1330+
type_annotation,
1331+
/* postfix */ false,
1332+
))
13351333
}
13361334

13371335
fn parse_js_doc_non_nullable_type(&mut self) -> Result<TSType<'a>> {

tasks/coverage/snapshots/estree_typescript.snap

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
commit: 15392346
22

33
estree_typescript Summary:
4-
AST Parsed : 10618/10725 (99.00%)
4+
AST Parsed : 10619/10725 (99.01%)
55
Positive Passed: 8456/10725 (78.84%)
66
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/ClassDeclarationWithInvalidConstOnPropertyDeclaration.ts
77
A class member cannot have the 'const' keyword.
@@ -495,8 +495,7 @@ Mismatch: tasks/coverage/typescript/tests/cases/compiler/exportSpecifierReferenc
495495
Mismatch: tasks/coverage/typescript/tests/cases/compiler/exportSpecifierReferencingOuterDeclaration4.ts
496496
Mismatch: tasks/coverage/typescript/tests/cases/compiler/exportStarFromEmptyModule.ts
497497
Mismatch: tasks/coverage/typescript/tests/cases/compiler/exportedInterfaceInaccessibleInCallbackInModule.ts
498-
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/expressionWithJSDocTypeArguments.ts
499-
Unexpected token
498+
Mismatch: tasks/coverage/typescript/tests/cases/compiler/expressionWithJSDocTypeArguments.ts
500499
Mismatch: tasks/coverage/typescript/tests/cases/compiler/extendBaseClassBeforeItsDeclared.ts
501500
tasks/coverage/typescript/tests/cases/compiler/extendsUntypedModule.ts
502501
Unexpected estree file content error: 1 != 3

tasks/coverage/snapshots/parser_typescript.snap

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ commit: 15392346
33
parser_typescript Summary:
44
AST Parsed : 6522/6531 (99.86%)
55
Positive Passed: 6511/6531 (99.69%)
6-
Negative Passed: 1298/5754 (22.56%)
6+
Negative Passed: 1297/5754 (22.54%)
77
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration24.ts
88
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment7.ts
99
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment8.ts
@@ -815,6 +815,7 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/exportSpecif
815815
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/exportStarFromEmptyModule.ts
816816
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/exportedBlockScopedDeclarations.ts
817817
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/expr.ts
818+
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/expressionWithJSDocTypeArguments.ts
818819
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/extBaseClass2.ts
819820
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/extendAndImplementTheSameBaseType2.ts
820821
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/extendArray.ts
@@ -8107,14 +8108,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
81078108
╰────
81088109
help: Try insert a semicolon here
81098110

8110-
× Unexpected token
8111-
╭─[typescript/tests/cases/compiler/expressionWithJSDocTypeArguments.ts:9:21]
8112-
8 │
8113-
9 │ const WhatFoo = foo<?>;
8114-
· ─
8115-
10 │ const HuhFoo = foo<string?>;
8116-
╰────
8117-
81188111
× await expression not allowed in formal parameter
81198112
╭─[typescript/tests/cases/compiler/expressionsForbiddenInParameterInitializers.ts:1:35]
81208113
1 │ export async function foo({ foo = await import("./bar") }) {
@@ -10851,6 +10844,24 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
1085110844
╰────
1085210845
help: Did you mean to write 'number | null | undefined'?
1085310846

10847+
× TS(17020): '?' at the start of a type is not valid TypeScript syntax.
10848+
╭─[typescript/tests/cases/compiler/parseInvalidNullableTypes.ts:8:16]
10849+
7 │
10850+
8 │ function f4(a: ?string) {}
10851+
· ───────
10852+
9 │ function f5(a: ?number) {}
10853+
╰────
10854+
help: Did you mean to write 'string | null | undefined'?
10855+
10856+
× TS(17020): '?' at the start of a type is not valid TypeScript syntax.
10857+
╭─[typescript/tests/cases/compiler/parseInvalidNullableTypes.ts:9:16]
10858+
8 │ function f4(a: ?string) {}
10859+
9 │ function f5(a: ?number) {}
10860+
· ───────
10861+
10 │
10862+
╰────
10863+
help: Did you mean to write 'number | null | undefined'?
10864+
1085410865
× TS(17020): '?' at the start of a type is not valid TypeScript syntax.
1085510866
╭─[typescript/tests/cases/compiler/parseInvalidNullableTypes.ts:11:25]
1085610867
10 │
@@ -10869,6 +10880,15 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
1086910880
╰────
1087010881
help: Did you mean to write 'number | null | undefined'?
1087110882

10883+
× TS(17020): '?' at the start of a type is not valid TypeScript syntax.
10884+
╭─[typescript/tests/cases/compiler/parseInvalidNullableTypes.ts:19:10]
10885+
18 │ const c = 1 as ?any;
10886+
19 │ const d: ?number = 1;
10887+
· ───────
10888+
20 │
10889+
╰────
10890+
help: Did you mean to write 'number | null | undefined'?
10891+
1087210892
× TS(17019): '?' at the end of a type is not valid TypeScript syntax.
1087310893
╭─[typescript/tests/cases/compiler/parseInvalidNullableTypes.ts:21:8]
1087410894
20 │

0 commit comments

Comments
 (0)