From bb76aa7cd7616ae817a32815bc6d161d1284e543 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 29 Sep 2017 14:26:05 -0700 Subject: [PATCH] Fix bug: Report errors on `extends` expression in JS even if an `@augments` tag is present --- src/compiler/checker.ts | 6 ++++++ .../jsdocAugments_errorInExtendsExpression.errors.txt | 10 ++++++++++ .../jsdocAugments_errorInExtendsExpression.symbols | 8 ++++++++ .../jsdocAugments_errorInExtendsExpression.types | 10 ++++++++++ .../compiler/jsdocAugments_errorInExtendsExpression.ts | 8 ++++++++ 5 files changed, 42 insertions(+) create mode 100644 tests/baselines/reference/jsdocAugments_errorInExtendsExpression.errors.txt create mode 100644 tests/baselines/reference/jsdocAugments_errorInExtendsExpression.symbols create mode 100644 tests/baselines/reference/jsdocAugments_errorInExtendsExpression.types create mode 100644 tests/cases/compiler/jsdocAugments_errorInExtendsExpression.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f6aeec2f70420..9dcb536de83b8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4917,6 +4917,8 @@ namespace ts { */ function getBaseConstructorTypeOfClass(type: InterfaceType): Type { if (!type.resolvedBaseConstructorType) { + const decl = type.symbol.valueDeclaration; + const extended = getClassExtendsHeritageClauseElement(decl); const baseTypeNode = getBaseTypeNodeOfClass(type); if (!baseTypeNode) { return type.resolvedBaseConstructorType = undefinedType; @@ -4925,6 +4927,10 @@ namespace ts { return unknownType; } const baseConstructorType = checkExpression(baseTypeNode.expression); + if (extended && baseTypeNode !== extended) { + Debug.assert(!extended.typeArguments); // Because this is in a JS file, and baseTypeNode is in an @extends tag + checkExpression(extended.expression); + } if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection)) { // Resolving the members of a class requires us to resolve the base class of that class. // We force resolution here such that we catch circularities now. diff --git a/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.errors.txt b/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.errors.txt new file mode 100644 index 0000000000000..11a7311fc30c0 --- /dev/null +++ b/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.errors.txt @@ -0,0 +1,10 @@ +/a.js(3,17): error TS2304: Cannot find name 'err'. + + +==== /a.js (1 errors) ==== + class A {} + /** @augments A */ + class B extends err() {} + ~~~ +!!! error TS2304: Cannot find name 'err'. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.symbols b/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.symbols new file mode 100644 index 0000000000000..d78feca914380 --- /dev/null +++ b/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.symbols @@ -0,0 +1,8 @@ +=== /a.js === +class A {} +>A : Symbol(A, Decl(a.js, 0, 0)) + +/** @augments A */ +class B extends err() {} +>B : Symbol(B, Decl(a.js, 0, 10)) + diff --git a/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.types b/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.types new file mode 100644 index 0000000000000..1a0fa09d3cd3d --- /dev/null +++ b/tests/baselines/reference/jsdocAugments_errorInExtendsExpression.types @@ -0,0 +1,10 @@ +=== /a.js === +class A {} +>A : A + +/** @augments A */ +class B extends err() {} +>B : B +>err() : A +>err : any + diff --git a/tests/cases/compiler/jsdocAugments_errorInExtendsExpression.ts b/tests/cases/compiler/jsdocAugments_errorInExtendsExpression.ts new file mode 100644 index 0000000000000..2fba59d446107 --- /dev/null +++ b/tests/cases/compiler/jsdocAugments_errorInExtendsExpression.ts @@ -0,0 +1,8 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @Filename: /a.js +class A {} +/** @augments A */ +class B extends err() {}