From b52a7fc3eaea93574626b8cf5e47f205dae2a428 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Wed, 9 Jan 2019 19:35:22 +0100 Subject: [PATCH] Exclude JSDoc @extends from 'super()' checks (#29308) * Exclude JSDoc @extends from 'super()' checks This fixes a similar problem as #29244 where JSDoc `@extends` * fix check 'super can only be referenced in a derived class' --- src/compiler/checker.ts | 6 ++-- ...ckSuperCallBeforeThisAccessing9.errors.txt | 22 ++++++++++++ ...checkSuperCallBeforeThisAccessing9.symbols | 31 ++++++++++++++++ .../checkSuperCallBeforeThisAccessing9.types | 35 +++++++++++++++++++ .../checkSuperCallBeforeThisAccessing9.ts | 21 +++++++++++ 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt 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 86822e24878..41f4d8bef68 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. @@ -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; } @@ -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.errors.txt b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt new file mode 100644 index 00000000000..5d67f88c847 --- /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 new file mode 100644 index 00000000000..f900a4986eb --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols @@ -0,0 +1,31 @@ +=== 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(); + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types new file mode 100644 index 00000000000..577256400b2 --- /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 : any + } +} diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts new file mode 100644 index 00000000000..a6b7102b2a5 --- /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