From 92899675ecc11491e1fb4785544cc8d15a2cc045 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Tue, 8 Jan 2019 12:54:48 +0100 Subject: [PATCH 1/2] Exclude JSDoc @extends from 'super()' checks This fixes a similar problem as #29244 where JSDoc `@extends` --- src/compiler/checker.ts | 4 +-- ...checkSuperCallBeforeThisAccessing9.symbols | 32 +++++++++++++++++ .../checkSuperCallBeforeThisAccessing9.types | 35 +++++++++++++++++++ .../checkSuperCallBeforeThisAccessing9.ts | 21 +++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols create mode 100644 tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types create mode 100644 tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index de44e8bb37ca7..6c65b77cec326 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16625,7 +16625,7 @@ namespace ts { function checkThisBeforeSuper(node: Node, container: Node, diagnosticMessage: DiagnosticMessage) { const containingClassDecl = container.parent; - const baseTypeNode = getEffectiveBaseTypeNode(containingClassDecl); + const baseTypeNode = getClassExtendsHeritageElement(containingClassDecl); // If a containing class does not have extends clause or the class extends null // skip checking whether super statement is called before "this" accessing. @@ -23575,7 +23575,7 @@ namespace ts { // Constructors of classes with no extends clause may not contain super calls, whereas // constructors of derived classes must contain at least one super call somewhere in their function body. const containingClassDecl = node.parent; - if (getEffectiveBaseTypeNode(containingClassDecl)) { + if (getClassExtendsHeritageElement(containingClassDecl)) { captureLexicalThis(node.parent, containingClassDecl); const classExtendsNull = classDeclarationExtendsNull(containingClassDecl); const superCall = getSuperCallInConstructor(node); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols new file mode 100644 index 0000000000000..a50c8c529c9d7 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols @@ -0,0 +1,32 @@ +=== tests/cases/compiler/noSuperInJSDocExtends.js === +class Based { } +>Based : Symbol(Based, Decl(noSuperInJSDocExtends.js, 0, 0)) + +/** @extends {Based} */ +class Derived { +>Derived : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) + + constructor() { + this; +>this : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) + + this.x = 10; +>this.x : Symbol(Derived.x, Decl(noSuperInJSDocExtends.js, 4, 13)) +>this : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) +>x : Symbol(Derived.x, Decl(noSuperInJSDocExtends.js, 4, 13)) + + var that = this; +>that : Symbol(that, Decl(noSuperInJSDocExtends.js, 6, 11)) +>this : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) + } +} + +/** @extends {Based} */ +class Derived2 { +>Derived2 : Symbol(Derived2, Decl(noSuperInJSDocExtends.js, 8, 1)) + + constructor() { + super(); +>super : Symbol(Based, Decl(noSuperInJSDocExtends.js, 0, 0)) + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types new file mode 100644 index 0000000000000..c1fbf024937c1 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/noSuperInJSDocExtends.js === +class Based { } +>Based : Based + +/** @extends {Based} */ +class Derived { +>Derived : Derived + + constructor() { + this; +>this : this + + this.x = 10; +>this.x = 10 : 10 +>this.x : number +>this : this +>x : number +>10 : 10 + + var that = this; +>that : this +>this : this + } +} + +/** @extends {Based} */ +class Derived2 { +>Derived2 : Derived2 + + constructor() { + super(); +>super() : void +>super : typeof Based + } +} diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts new file mode 100644 index 0000000000000..a6b7102b2a566 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts @@ -0,0 +1,21 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @filename: noSuperInJSDocExtends.js +class Based { } +/** @extends {Based} */ +class Derived { + constructor() { + this; + this.x = 10; + var that = this; + } +} + +/** @extends {Based} */ +class Derived2 { + constructor() { + super(); + } +} \ No newline at end of file From 5f059f11fbd9cce125a0dfa1b3adead058205a19 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Tue, 8 Jan 2019 20:51:54 +0100 Subject: [PATCH 2/2] fix check 'super can only be referenced in a derived class' --- src/compiler/checker.ts | 2 +- ...ckSuperCallBeforeThisAccessing9.errors.txt | 22 +++++++++++++++++++ ...checkSuperCallBeforeThisAccessing9.symbols | 1 - .../checkSuperCallBeforeThisAccessing9.types | 2 +- 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6c65b77cec326..181940af6e2f1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16974,7 +16974,7 @@ namespace ts { // at this point the only legal case for parent is ClassLikeDeclaration const classLikeDeclaration = container.parent; - if (!getEffectiveBaseTypeNode(classLikeDeclaration)) { + if (!getClassExtendsHeritageElement(classLikeDeclaration)) { error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); return errorType; } diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt new file mode 100644 index 0000000000000..5d67f88c847b3 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt @@ -0,0 +1,22 @@ +tests/cases/compiler/noSuperInJSDocExtends.js(14,9): error TS2335: 'super' can only be referenced in a derived class. + + +==== tests/cases/compiler/noSuperInJSDocExtends.js (1 errors) ==== + class Based { } + /** @extends {Based} */ + class Derived { + constructor() { + this; + this.x = 10; + var that = this; + } + } + + /** @extends {Based} */ + class Derived2 { + constructor() { + super(); + ~~~~~ +!!! error TS2335: 'super' can only be referenced in a derived class. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols index a50c8c529c9d7..f900a4986eb0f 100644 --- a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols @@ -27,6 +27,5 @@ class Derived2 { constructor() { super(); ->super : Symbol(Based, Decl(noSuperInJSDocExtends.js, 0, 0)) } } diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types index c1fbf024937c1..577256400b2d7 100644 --- a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types @@ -30,6 +30,6 @@ class Derived2 { constructor() { super(); >super() : void ->super : typeof Based +>super : any } }