From c74efad46e72b6bd251e77e6838c379c0c725dfb Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Fri, 21 Apr 2023 02:06:38 +0300 Subject: [PATCH] fix(53645): JSDoc extends doesn't work with multiple lines (#53705) --- src/compiler/parser.ts | 2 + .../reference/extendsTag5.errors.txt | 65 +++++++++++++++++++ tests/baselines/reference/extendsTag5.symbols | 59 +++++++++++++++++ tests/baselines/reference/extendsTag5.types | 59 +++++++++++++++++ tests/cases/conformance/jsdoc/extendsTag5.ts | 49 ++++++++++++++ 5 files changed, 234 insertions(+) create mode 100644 tests/baselines/reference/extendsTag5.errors.txt create mode 100644 tests/baselines/reference/extendsTag5.symbols create mode 100644 tests/baselines/reference/extendsTag5.types create mode 100644 tests/cases/conformance/jsdoc/extendsTag5.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 64257c72039..b97245f84e0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -9244,7 +9244,9 @@ namespace Parser { const usedBrace = parseOptional(SyntaxKind.OpenBraceToken); const pos = getNodePos(); const expression = parsePropertyAccessEntityNameExpression(); + scanner.setInJSDocType(true); const typeArguments = tryParseTypeArguments(); + scanner.setInJSDocType(false); const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression }; const res = finishNode(node, pos); if (usedBrace) { diff --git a/tests/baselines/reference/extendsTag5.errors.txt b/tests/baselines/reference/extendsTag5.errors.txt new file mode 100644 index 00000000000..8c2c3e3e075 --- /dev/null +++ b/tests/baselines/reference/extendsTag5.errors.txt @@ -0,0 +1,65 @@ +/a.js(29,16): error TS2344: Type '{ a: string; b: string; }' does not satisfy the constraint 'Foo'. + Types of property 'b' are incompatible. + Type 'string' is not assignable to type 'boolean | string[]'. +/a.js(42,16): error TS2344: Type '{ a: string; b: string; }' does not satisfy the constraint 'Foo'. + Types of property 'b' are incompatible. + Type 'string' is not assignable to type 'boolean | string[]'. + + +==== /a.js (2 errors) ==== + /** + * @typedef {{ + * a: number | string; + * b: boolean | string[]; + * }} Foo + */ + + /** + * @template {Foo} T + */ + class A { + /** + * @param {T} a + */ + constructor(a) { + return a + } + } + + /** + * @extends {A<{ + * a: string, + * b: string[] + * }>} + */ + class B extends A {} + + /** + * @extends {A<{ + ~ + * a: string, + ~~~~~~~~~~~~~~~~~ + * b: string + ~~~~~~~~~~~~~~~~ + * }>} + ~~~~ +!!! error TS2344: Type '{ a: string; b: string; }' does not satisfy the constraint 'Foo'. +!!! error TS2344: Types of property 'b' are incompatible. +!!! error TS2344: Type 'string' is not assignable to type 'boolean | string[]'. + */ + class C extends A {} + + /** + * @extends {A<{a: string, b: string[]}>} + */ + class D extends A {} + + /** + * @extends {A<{a: string, b: string}>} + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type '{ a: string; b: string; }' does not satisfy the constraint 'Foo'. +!!! error TS2344: Types of property 'b' are incompatible. +!!! error TS2344: Type 'string' is not assignable to type 'boolean | string[]'. + */ + class E extends A {} + \ No newline at end of file diff --git a/tests/baselines/reference/extendsTag5.symbols b/tests/baselines/reference/extendsTag5.symbols new file mode 100644 index 00000000000..a130460ad99 --- /dev/null +++ b/tests/baselines/reference/extendsTag5.symbols @@ -0,0 +1,59 @@ +=== /a.js === +/** + * @typedef {{ +* a: number | string; +* b: boolean | string[]; +* }} Foo +*/ + +/** +* @template {Foo} T +*/ +class A { +>A : Symbol(A, Decl(a.js, 0, 0)) + + /** + * @param {T} a + */ + constructor(a) { +>a : Symbol(a, Decl(a.js, 14, 15)) + + return a +>a : Symbol(a, Decl(a.js, 14, 15)) + } +} + +/** +* @extends {A<{ +* a: string, +* b: string[] +* }>} +*/ +class B extends A {} +>B : Symbol(B, Decl(a.js, 17, 1)) +>A : Symbol(A, Decl(a.js, 0, 0)) + +/** + * @extends {A<{ + * a: string, + * b: string + * }>} + */ +class C extends A {} +>C : Symbol(C, Decl(a.js, 25, 20)) +>A : Symbol(A, Decl(a.js, 0, 0)) + +/** + * @extends {A<{a: string, b: string[]}>} + */ +class D extends A {} +>D : Symbol(D, Decl(a.js, 33, 20)) +>A : Symbol(A, Decl(a.js, 0, 0)) + +/** + * @extends {A<{a: string, b: string}>} + */ +class E extends A {} +>E : Symbol(E, Decl(a.js, 38, 20)) +>A : Symbol(A, Decl(a.js, 0, 0)) + diff --git a/tests/baselines/reference/extendsTag5.types b/tests/baselines/reference/extendsTag5.types new file mode 100644 index 00000000000..49541535c7f --- /dev/null +++ b/tests/baselines/reference/extendsTag5.types @@ -0,0 +1,59 @@ +=== /a.js === +/** + * @typedef {{ +* a: number | string; +* b: boolean | string[]; +* }} Foo +*/ + +/** +* @template {Foo} T +*/ +class A { +>A : A + + /** + * @param {T} a + */ + constructor(a) { +>a : T + + return a +>a : T + } +} + +/** +* @extends {A<{ +* a: string, +* b: string[] +* }>} +*/ +class B extends A {} +>B : B +>A : A<{ a: string; b: string[]; }> + +/** + * @extends {A<{ + * a: string, + * b: string + * }>} + */ +class C extends A {} +>C : C +>A : A<{ a: string; b: string; }> + +/** + * @extends {A<{a: string, b: string[]}>} + */ +class D extends A {} +>D : D +>A : A<{ a: string; b: string[]; }> + +/** + * @extends {A<{a: string, b: string}>} + */ +class E extends A {} +>E : E +>A : A<{ a: string; b: string; }> + diff --git a/tests/cases/conformance/jsdoc/extendsTag5.ts b/tests/cases/conformance/jsdoc/extendsTag5.ts new file mode 100644 index 00000000000..0f7157e9e8a --- /dev/null +++ b/tests/cases/conformance/jsdoc/extendsTag5.ts @@ -0,0 +1,49 @@ +// @checkJs: true +// @allowJs: true +// @noEmit: true +// @filename: /a.js + +/** + * @typedef {{ +* a: number | string; +* b: boolean | string[]; +* }} Foo +*/ + +/** +* @template {Foo} T +*/ +class A { + /** + * @param {T} a + */ + constructor(a) { + return a + } +} + +/** +* @extends {A<{ +* a: string, +* b: string[] +* }>} +*/ +class B extends A {} + +/** + * @extends {A<{ + * a: string, + * b: string + * }>} + */ +class C extends A {} + +/** + * @extends {A<{a: string, b: string[]}>} + */ +class D extends A {} + +/** + * @extends {A<{a: string, b: string}>} + */ +class E extends A {}