From f1c19699072675b17671634cf282c28caa6e7731 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Mar 2017 15:29:18 -0700 Subject: [PATCH 01/12] Allow extending from any Extending from any adds an index signature: [s: string]: any to both the instance and static sides of the class. --- src/compiler/checker.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4e55a1c46b564..128e5c86bdcc7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4617,7 +4617,7 @@ namespace ts { error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); return type.resolvedBaseConstructorType = unknownType; } - if (baseConstructorType !== unknownType && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { + if (baseConstructorType !== anyType && baseConstructorType !== unknownType && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType)); return type.resolvedBaseConstructorType = unknownType; } @@ -5076,8 +5076,10 @@ namespace ts { (type).declaredProperties = getNamedMembers(symbol.members); (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call")); (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new")); - (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); + (type).declaredStringIndexInfo = (getBaseConstructorTypeOfClass(type) === anyType) ? + createIndexInfo(anyType, /*isReadonly*/ false) : + getIndexInfoOfSymbol(symbol, IndexKind.String); } return type; } @@ -5371,6 +5373,7 @@ namespace ts { // Combinations of function, class, enum and module let members = emptySymbols; let constructSignatures: Signature[] = emptyArray; + let stringIndexInfo: IndexInfo = undefined; if (symbol.exports) { members = getExportsOfSymbol(symbol); } @@ -5385,9 +5388,12 @@ namespace ts { members = createSymbolTable(getNamedMembers(members)); addInheritedMembers(members, getPropertiesOfType(baseConstructorType)); } + else if (baseConstructorType === anyType) { + stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); + } } const numberIndexInfo = symbol.flags & SymbolFlags.Enum ? enumNumberIndexInfo : undefined; - setStructuredTypeMembers(type, members, emptyArray, constructSignatures, undefined, numberIndexInfo); + setStructuredTypeMembers(type, members, emptyArray, constructSignatures, stringIndexInfo, numberIndexInfo); // We resolve the members before computing the signatures because a signature may use // typeof with a qualified name expression that circularly references the type we are // in the process of resolving (see issue #6072). The temporarily empty signature list From 765ac7ccd1e1999715cc1f753d87564372bb6f7d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Mar 2017 16:09:33 -0700 Subject: [PATCH 02/12] Improve handling of any as a base type Also improve how the string indexer for any-inheriting types is added. --- src/compiler/checker.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 128e5c86bdcc7..717553e484831 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4649,7 +4649,7 @@ namespace ts { function resolveBaseTypesOfClass(type: InterfaceType): void { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; const baseConstructorType = getApparentType(getBaseConstructorTypeOfClass(type)); - if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection))) { + if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Any))) { return; } const baseTypeNode = getBaseTypeNodeOfClass(type); @@ -4662,6 +4662,9 @@ namespace ts { // type arguments in the same manner as a type reference to get the same error reporting experience. baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol); } + else if (baseConstructorType.flags & TypeFlags.Any) { + baseType = anyType; + } else { // The class derives from a "class-like" constructor function, check that we have at least one construct signature // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere @@ -4715,10 +4718,11 @@ namespace ts { return true; } - // A valid base type is any non-generic object type or intersection of non-generic + // A valid base type is `any`, any non-generic object type or intersection of non-generic // object types. function isValidBaseType(type: Type): boolean { - return type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive) && !isGenericMappedType(type) || + return !!(type.flags & TypeFlags.Any) || + type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive) && !isGenericMappedType(type) || type.flags & TypeFlags.Intersection && !forEach((type).types, t => !isValidBaseType(t)); } @@ -5077,9 +5081,7 @@ namespace ts { (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call")); (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new")); (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); - (type).declaredStringIndexInfo = (getBaseConstructorTypeOfClass(type) === anyType) ? - createIndexInfo(anyType, /*isReadonly*/ false) : - getIndexInfoOfSymbol(symbol, IndexKind.String); + (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); } return type; } @@ -5132,7 +5134,9 @@ namespace ts { addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType)); callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call)); constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct)); - stringIndexInfo = stringIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.String); + stringIndexInfo = stringIndexInfo || (instantiatedBaseType === anyType ? + createIndexInfo(anyType, /*isReadonly*/ false) : + getIndexInfoOfType(instantiatedBaseType, IndexKind.String)); numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.Number); } } From 650cc29219f85976812734e821de88bfccca1556 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Mar 2017 16:10:27 -0700 Subject: [PATCH 03/12] Test: extending from any --- tests/cases/compiler/extendFromAny.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/cases/compiler/extendFromAny.ts diff --git a/tests/cases/compiler/extendFromAny.ts b/tests/cases/compiler/extendFromAny.ts new file mode 100644 index 0000000000000..52ac544be361d --- /dev/null +++ b/tests/cases/compiler/extendFromAny.ts @@ -0,0 +1,11 @@ +declare var Base: any; +class C extends Base { + known = 1; + static sknown = 2; +} + +let c = new C(); +c.known.length; // error, 'real' has no 'length' property +C.sknown.length; // error, 'sreal' has no 'length' property +c.unknown.length; // ok, fake: any +C.sunknown.length; // ok: sfake: any From 3624417a32cae0ba351819c35bfb38ab1967f431 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Mar 2017 16:12:20 -0700 Subject: [PATCH 04/12] Update baselines --- .../reference/extendFromAny.errors.txt | 21 ++++++++++ tests/baselines/reference/extendFromAny.js | 40 +++++++++++++++++++ .../reference/extendsUntypedModule.errors.txt | 14 ------- .../reference/extendsUntypedModule.symbols | 8 ++++ .../reference/extendsUntypedModule.types | 8 ++++ .../reference/generatorTypeCheck40.errors.txt | 5 +-- .../reference/generatorTypeCheck55.errors.txt | 5 +-- .../reference/generatorTypeCheck60.errors.txt | 5 +-- .../parserGenericsInTypeContexts1.errors.txt | 5 ++- .../parserGenericsInTypeContexts2.errors.txt | 8 +++- .../reference/recursiveBaseCheck3.errors.txt | 7 +--- .../reference/recursiveBaseCheck4.errors.txt | 7 +--- .../reference/recursiveBaseCheck6.errors.txt | 7 +--- .../thisInInvalidContexts.errors.txt | 5 +-- ...InInvalidContextsExternalModule.errors.txt | 5 +-- 15 files changed, 99 insertions(+), 51 deletions(-) create mode 100644 tests/baselines/reference/extendFromAny.errors.txt create mode 100644 tests/baselines/reference/extendFromAny.js delete mode 100644 tests/baselines/reference/extendsUntypedModule.errors.txt create mode 100644 tests/baselines/reference/extendsUntypedModule.symbols create mode 100644 tests/baselines/reference/extendsUntypedModule.types diff --git a/tests/baselines/reference/extendFromAny.errors.txt b/tests/baselines/reference/extendFromAny.errors.txt new file mode 100644 index 0000000000000..2db3686cdda7d --- /dev/null +++ b/tests/baselines/reference/extendFromAny.errors.txt @@ -0,0 +1,21 @@ +tests/cases/compiler/extendFromAny.ts(8,9): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/compiler/extendFromAny.ts(9,10): error TS2339: Property 'length' does not exist on type 'number'. + + +==== tests/cases/compiler/extendFromAny.ts (2 errors) ==== + declare var Base: any; + class C extends Base { + known = 1; + static sknown = 2; + } + + let c = new C(); + c.known.length; // error, 'real' has no 'length' property + ~~~~~~ +!!! error TS2339: Property 'length' does not exist on type 'number'. + C.sknown.length; // error, 'sreal' has no 'length' property + ~~~~~~ +!!! error TS2339: Property 'length' does not exist on type 'number'. + c.unknown.length; // ok, fake: any + C.sunknown.length; // ok: sfake: any + \ No newline at end of file diff --git a/tests/baselines/reference/extendFromAny.js b/tests/baselines/reference/extendFromAny.js new file mode 100644 index 0000000000000..0d1954b4ef7e1 --- /dev/null +++ b/tests/baselines/reference/extendFromAny.js @@ -0,0 +1,40 @@ +//// [extendFromAny.ts] +declare var Base: any; +class C extends Base { + known = 1; + static sknown = 2; +} + +let c = new C(); +c.known.length; // error, 'real' has no 'length' property +C.sknown.length; // error, 'sreal' has no 'length' property +c.unknown.length; // ok, fake: any +C.sunknown.length; // ok: sfake: any + + +//// [extendFromAny.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.known = 1; + return _this; + } + return C; +}(Base)); +C.sknown = 2; +var c = new C(); +c.known.length; // error, 'real' has no 'length' property +C.sknown.length; // error, 'sreal' has no 'length' property +c.unknown.length; // ok, fake: any +C.sunknown.length; // ok: sfake: any diff --git a/tests/baselines/reference/extendsUntypedModule.errors.txt b/tests/baselines/reference/extendsUntypedModule.errors.txt deleted file mode 100644 index 9a1c423535261..0000000000000 --- a/tests/baselines/reference/extendsUntypedModule.errors.txt +++ /dev/null @@ -1,14 +0,0 @@ -/a.ts(2,17): error TS2507: Type 'any' is not a constructor function type. - - -==== /a.ts (1 errors) ==== - import Foo from "foo"; - class A extends Foo { } - ~~~ -!!! error TS2507: Type 'any' is not a constructor function type. - -==== /node_modules/foo/index.js (0 errors) ==== - // Test that extending an untyped module is an error, unlike extending unknownSymbol. - - This file is not read. - \ No newline at end of file diff --git a/tests/baselines/reference/extendsUntypedModule.symbols b/tests/baselines/reference/extendsUntypedModule.symbols new file mode 100644 index 0000000000000..9036963d7d303 --- /dev/null +++ b/tests/baselines/reference/extendsUntypedModule.symbols @@ -0,0 +1,8 @@ +=== /a.ts === +import Foo from "foo"; +>Foo : Symbol(Foo, Decl(a.ts, 0, 6)) + +class A extends Foo { } +>A : Symbol(A, Decl(a.ts, 0, 22)) +>Foo : Symbol(Foo, Decl(a.ts, 0, 6)) + diff --git a/tests/baselines/reference/extendsUntypedModule.types b/tests/baselines/reference/extendsUntypedModule.types new file mode 100644 index 0000000000000..50fa8b821b3eb --- /dev/null +++ b/tests/baselines/reference/extendsUntypedModule.types @@ -0,0 +1,8 @@ +=== /a.ts === +import Foo from "foo"; +>Foo : any + +class A extends Foo { } +>A : A +>Foo : any + diff --git a/tests/baselines/reference/generatorTypeCheck40.errors.txt b/tests/baselines/reference/generatorTypeCheck40.errors.txt index ba93862c8d538..3cc7c02fa7585 100644 --- a/tests/baselines/reference/generatorTypeCheck40.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck40.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts(2,21): error TS2507: Type 'any' is not a constructor function type. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts(2,22): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts (1 errors) ==== function* g() { class C extends (yield 0) { } - ~~~~~~~~~ -!!! error TS2507: Type 'any' is not a constructor function type. ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. } \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck55.errors.txt b/tests/baselines/reference/generatorTypeCheck55.errors.txt index 854c1801efddc..7856a0074ffde 100644 --- a/tests/baselines/reference/generatorTypeCheck55.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck55.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck55.ts(2,29): error TS2507: Type 'any' is not a constructor function type. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck55.ts(2,30): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck55.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck55.ts (1 errors) ==== function* g() { var x = class C extends (yield) {}; - ~~~~~~~ -!!! error TS2507: Type 'any' is not a constructor function type. ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. } \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck60.errors.txt b/tests/baselines/reference/generatorTypeCheck60.errors.txt index 5330cd186b704..6f7bf465804d6 100644 --- a/tests/baselines/reference/generatorTypeCheck60.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck60.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts(2,21): error TS2507: Type 'any' is not a constructor function type. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts(2,22): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts (1 errors) ==== function* g() { class C extends (yield) {}; - ~~~~~~~ -!!! error TS2507: Type 'any' is not a constructor function type. ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. } \ No newline at end of file diff --git a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt index 477cc3edcdc39..e3ede7cb30ec8 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,17): error TS2304: Cannot find name 'A'. +tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,19): error TS2304: Cannot find name 'T'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,33): error TS2304: Cannot find name 'B'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(4,9): error TS2315: Type 'C' is not generic. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(5,9): error TS2304: Cannot find name 'D'. @@ -9,10 +10,12 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(14,16): error TS2304: Cannot find name 'F'. -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (9 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (10 errors) ==== class C extends A implements B { ~ !!! error TS2304: Cannot find name 'A'. + ~ +!!! error TS2304: Cannot find name 'T'. ~ !!! error TS2304: Cannot find name 'B'. } diff --git a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt index f686b56bf89e2..aedc1d43b3e8f 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt @@ -1,4 +1,6 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,17): error TS2304: Cannot find name 'A'. +tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,19): error TS2304: Cannot find name 'X'. +tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,25): error TS2304: Cannot find name 'Y'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,45): error TS2304: Cannot find name 'B'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(4,9): error TS2315: Type 'C' is not generic. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(5,9): error TS2304: Cannot find name 'D'. @@ -9,10 +11,14 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(14,16): error TS2304: Cannot find name 'F'. -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (9 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (11 errors) ==== class C extends A, Y>> implements B, Y>> { ~ !!! error TS2304: Cannot find name 'A'. + ~ +!!! error TS2304: Cannot find name 'X'. + ~ +!!! error TS2304: Cannot find name 'Y'. ~ !!! error TS2304: Cannot find name 'B'. } diff --git a/tests/baselines/reference/recursiveBaseCheck3.errors.txt b/tests/baselines/reference/recursiveBaseCheck3.errors.txt index ba0ea669c55d1..827c9ed2e05e6 100644 --- a/tests/baselines/reference/recursiveBaseCheck3.errors.txt +++ b/tests/baselines/reference/recursiveBaseCheck3.errors.txt @@ -1,10 +1,9 @@ tests/cases/compiler/recursiveBaseCheck3.ts(1,7): error TS2506: 'A' is referenced directly or indirectly in its own base expression. tests/cases/compiler/recursiveBaseCheck3.ts(1,20): error TS2449: Class 'C' used before its declaration. tests/cases/compiler/recursiveBaseCheck3.ts(2,7): error TS2506: 'C' is referenced directly or indirectly in its own base expression. -tests/cases/compiler/recursiveBaseCheck3.ts(4,9): error TS2339: Property 'blah' does not exist on type 'C<{}>'. -==== tests/cases/compiler/recursiveBaseCheck3.ts (4 errors) ==== +==== tests/cases/compiler/recursiveBaseCheck3.ts (3 errors) ==== class A extends C { } ~ !!! error TS2506: 'A' is referenced directly or indirectly in its own base expression. @@ -14,6 +13,4 @@ tests/cases/compiler/recursiveBaseCheck3.ts(4,9): error TS2339: Property 'blah' ~ !!! error TS2506: 'C' is referenced directly or indirectly in its own base expression. - (new C).blah; - ~~~~ -!!! error TS2339: Property 'blah' does not exist on type 'C<{}>'. \ No newline at end of file + (new C).blah; \ No newline at end of file diff --git a/tests/baselines/reference/recursiveBaseCheck4.errors.txt b/tests/baselines/reference/recursiveBaseCheck4.errors.txt index 5616523d14e06..7c030cfc8abd2 100644 --- a/tests/baselines/reference/recursiveBaseCheck4.errors.txt +++ b/tests/baselines/reference/recursiveBaseCheck4.errors.txt @@ -1,11 +1,8 @@ tests/cases/compiler/recursiveBaseCheck4.ts(1,7): error TS2506: 'M' is referenced directly or indirectly in its own base expression. -tests/cases/compiler/recursiveBaseCheck4.ts(2,9): error TS2339: Property 'blah' does not exist on type 'M<{}>'. -==== tests/cases/compiler/recursiveBaseCheck4.ts (2 errors) ==== +==== tests/cases/compiler/recursiveBaseCheck4.ts (1 errors) ==== class M extends M { } ~ !!! error TS2506: 'M' is referenced directly or indirectly in its own base expression. - (new M).blah; - ~~~~ -!!! error TS2339: Property 'blah' does not exist on type 'M<{}>'. \ No newline at end of file + (new M).blah; \ No newline at end of file diff --git a/tests/baselines/reference/recursiveBaseCheck6.errors.txt b/tests/baselines/reference/recursiveBaseCheck6.errors.txt index 6d453da425fb1..2ff827fb091bc 100644 --- a/tests/baselines/reference/recursiveBaseCheck6.errors.txt +++ b/tests/baselines/reference/recursiveBaseCheck6.errors.txt @@ -1,11 +1,8 @@ tests/cases/compiler/recursiveBaseCheck6.ts(1,7): error TS2506: 'S18' is referenced directly or indirectly in its own base expression. -tests/cases/compiler/recursiveBaseCheck6.ts(2,13): error TS2339: Property 'blah' does not exist on type 'S18<{}>'. -==== tests/cases/compiler/recursiveBaseCheck6.ts (2 errors) ==== +==== tests/cases/compiler/recursiveBaseCheck6.ts (1 errors) ==== class S18 extends S18<{ S19: A; }>{ } ~~~ !!! error TS2506: 'S18' is referenced directly or indirectly in its own base expression. - (new S18()).blah; - ~~~~ -!!! error TS2339: Property 'blah' does not exist on type 'S18<{}>'. \ No newline at end of file + (new S18()).blah; \ No newline at end of file diff --git a/tests/baselines/reference/thisInInvalidContexts.errors.txt b/tests/baselines/reference/thisInInvalidContexts.errors.txt index d33260fa108df..3581d6d6f29bc 100644 --- a/tests/baselines/reference/thisInInvalidContexts.errors.txt +++ b/tests/baselines/reference/thisInInvalidContexts.errors.txt @@ -3,12 +3,11 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(14,15): tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(22,15): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(28,13): error TS2331: 'this' cannot be referenced in a module or namespace body. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(36,13): error TS2526: A 'this' type is available only in a non-static member of a class or interface. -tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(38,25): error TS2507: Type 'any' is not a constructor function type. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(44,9): error TS2332: 'this' cannot be referenced in current location. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(45,9): error TS2332: 'this' cannot be referenced in current location. -==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts (8 errors) ==== +==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts (7 errors) ==== //'this' in static member initializer class ErrClass1 { static t = this; // Error @@ -57,8 +56,6 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(45,9): !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. class ErrClass3 extends this { - ~~~~ -!!! error TS2507: Type 'any' is not a constructor function type. } diff --git a/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt b/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt index 8f84793a49fbb..f89b28978922a 100644 --- a/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt +++ b/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt @@ -3,12 +3,11 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalMod tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(22,15): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(28,13): error TS2331: 'this' cannot be referenced in a module or namespace body. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(36,13): error TS2526: A 'this' type is available only in a non-static member of a class or interface. -tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(38,25): error TS2507: Type 'any' is not a constructor function type. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(44,9): error TS2332: 'this' cannot be referenced in current location. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(45,9): error TS2332: 'this' cannot be referenced in current location. -==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts (8 errors) ==== +==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts (7 errors) ==== //'this' in static member initializer class ErrClass1 { static t = this; // Error @@ -57,8 +56,6 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalMod !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. class ErrClass3 extends this { - ~~~~ -!!! error TS2507: Type 'any' is not a constructor function type. } From 41eabbc3d932c4125533291743051b71b7532b85 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Mar 2017 16:14:15 -0700 Subject: [PATCH 05/12] Re-swap mistakenly swapped lines of code --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 717553e484831..1a1b5ebc97ae9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5080,8 +5080,8 @@ namespace ts { (type).declaredProperties = getNamedMembers(symbol.members); (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call")); (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new")); - (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); + (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); } return type; } From e09533d19d8210f8243612901c5bedd0ad8d278c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 5 Apr 2017 13:08:21 -0700 Subject: [PATCH 06/12] Update test comments to match property names --- .../baselines/reference/extendFromAny.errors.txt | 8 ++++---- tests/baselines/reference/extendFromAny.js | 16 ++++++++-------- tests/cases/compiler/extendFromAny.ts | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/baselines/reference/extendFromAny.errors.txt b/tests/baselines/reference/extendFromAny.errors.txt index 2db3686cdda7d..0a40edbaf7a08 100644 --- a/tests/baselines/reference/extendFromAny.errors.txt +++ b/tests/baselines/reference/extendFromAny.errors.txt @@ -10,12 +10,12 @@ tests/cases/compiler/extendFromAny.ts(9,10): error TS2339: Property 'length' doe } let c = new C(); - c.known.length; // error, 'real' has no 'length' property + c.known.length; // error, 'known' has no 'length' property ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. - C.sknown.length; // error, 'sreal' has no 'length' property + C.sknown.length; // error, 'sknown' has no 'length' property ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. - c.unknown.length; // ok, fake: any - C.sunknown.length; // ok: sfake: any + c.unknown.length; // ok, unknown: any + C.sunknown.length; // ok: sunknown: any \ No newline at end of file diff --git a/tests/baselines/reference/extendFromAny.js b/tests/baselines/reference/extendFromAny.js index 0d1954b4ef7e1..f2a7f945cc950 100644 --- a/tests/baselines/reference/extendFromAny.js +++ b/tests/baselines/reference/extendFromAny.js @@ -6,10 +6,10 @@ class C extends Base { } let c = new C(); -c.known.length; // error, 'real' has no 'length' property -C.sknown.length; // error, 'sreal' has no 'length' property -c.unknown.length; // ok, fake: any -C.sunknown.length; // ok: sfake: any +c.known.length; // error, 'known' has no 'length' property +C.sknown.length; // error, 'sknown' has no 'length' property +c.unknown.length; // ok, unknown: any +C.sunknown.length; // ok: sunknown: any //// [extendFromAny.js] @@ -34,7 +34,7 @@ var C = (function (_super) { }(Base)); C.sknown = 2; var c = new C(); -c.known.length; // error, 'real' has no 'length' property -C.sknown.length; // error, 'sreal' has no 'length' property -c.unknown.length; // ok, fake: any -C.sunknown.length; // ok: sfake: any +c.known.length; // error, 'known' has no 'length' property +C.sknown.length; // error, 'sknown' has no 'length' property +c.unknown.length; // ok, unknown: any +C.sunknown.length; // ok: sunknown: any diff --git a/tests/cases/compiler/extendFromAny.ts b/tests/cases/compiler/extendFromAny.ts index 52ac544be361d..b5b9a2e1b04ca 100644 --- a/tests/cases/compiler/extendFromAny.ts +++ b/tests/cases/compiler/extendFromAny.ts @@ -5,7 +5,7 @@ class C extends Base { } let c = new C(); -c.known.length; // error, 'real' has no 'length' property -C.sknown.length; // error, 'sreal' has no 'length' property -c.unknown.length; // ok, fake: any -C.sunknown.length; // ok: sfake: any +c.known.length; // error, 'known' has no 'length' property +C.sknown.length; // error, 'sknown' has no 'length' property +c.unknown.length; // ok, unknown: any +C.sunknown.length; // ok: sunknown: any From 7f6c49e23b78713113cf09e249bb826703c24efc Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 5 Apr 2017 14:09:12 -0700 Subject: [PATCH 07/12] Check TypeFlags.Any instead of anyType&unknownType --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1a1b5ebc97ae9..59e1db0e22781 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4617,7 +4617,7 @@ namespace ts { error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); return type.resolvedBaseConstructorType = unknownType; } - if (baseConstructorType !== anyType && baseConstructorType !== unknownType && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { + if (!(baseConstructorType.flags & TypeFlags.Any) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType)); return type.resolvedBaseConstructorType = unknownType; } From 75f1774cb4db90272dc9ce144437ce9529ac4f50 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 5 Apr 2017 14:41:11 -0700 Subject: [PATCH 08/12] A few changes requested by review comments --- src/compiler/checker.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 59e1db0e22781..f37aed732d12e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4595,7 +4595,8 @@ namespace ts { * The base constructor of a class can resolve to * * undefinedType if the class has no extends clause, * * unknownType if an error occurred during resolution of the extends expression, - * * nullType if the extends expression is the null value, or + * * nullType if the extends expression is the null value, + * * anyType if the extends expression has type any, or * * an object type with at least one construct signature. */ function getBaseConstructorTypeOfClass(type: InterfaceType): Type { @@ -4721,8 +4722,7 @@ namespace ts { // A valid base type is `any`, any non-generic object type or intersection of non-generic // object types. function isValidBaseType(type: Type): boolean { - return !!(type.flags & TypeFlags.Any) || - type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive) && !isGenericMappedType(type) || + return type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any) && !isGenericMappedType(type) || type.flags & TypeFlags.Intersection && !forEach((type).types, t => !isValidBaseType(t)); } @@ -5134,9 +5134,11 @@ namespace ts { addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType)); callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call)); constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct)); - stringIndexInfo = stringIndexInfo || (instantiatedBaseType === anyType ? - createIndexInfo(anyType, /*isReadonly*/ false) : - getIndexInfoOfType(instantiatedBaseType, IndexKind.String)); + if (!stringIndexInfo) { + stringIndexInfo = instantiatedBaseType === anyType ? + createIndexInfo(anyType, /*isReadonly*/ false) : + getIndexInfoOfType(instantiatedBaseType, IndexKind.String); + } numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.Number); } } From 7e3c0337cf857d233a639d5a5ab57cb929ac49ae Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 5 Apr 2017 14:51:50 -0700 Subject: [PATCH 09/12] Unknown bases return baseConstructorType, not anyType Returns several baselines to their original states. --- src/compiler/checker.ts | 2 +- .../reference/parserGenericsInTypeContexts1.errors.txt | 5 +---- .../reference/parserGenericsInTypeContexts2.errors.txt | 8 +------- tests/baselines/reference/recursiveBaseCheck3.errors.txt | 7 +++++-- tests/baselines/reference/recursiveBaseCheck4.errors.txt | 7 +++++-- tests/baselines/reference/recursiveBaseCheck6.errors.txt | 7 +++++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f37aed732d12e..409c83573caee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4664,7 +4664,7 @@ namespace ts { baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol); } else if (baseConstructorType.flags & TypeFlags.Any) { - baseType = anyType; + baseType = baseConstructorType; } else { // The class derives from a "class-like" constructor function, check that we have at least one construct signature diff --git a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt index e3ede7cb30ec8..477cc3edcdc39 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt @@ -1,5 +1,4 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,17): error TS2304: Cannot find name 'A'. -tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,19): error TS2304: Cannot find name 'T'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,33): error TS2304: Cannot find name 'B'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(4,9): error TS2315: Type 'C' is not generic. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(5,9): error TS2304: Cannot find name 'D'. @@ -10,12 +9,10 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(14,16): error TS2304: Cannot find name 'F'. -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (10 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (9 errors) ==== class C extends A implements B { ~ !!! error TS2304: Cannot find name 'A'. - ~ -!!! error TS2304: Cannot find name 'T'. ~ !!! error TS2304: Cannot find name 'B'. } diff --git a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt index aedc1d43b3e8f..f686b56bf89e2 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt @@ -1,6 +1,4 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,17): error TS2304: Cannot find name 'A'. -tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,19): error TS2304: Cannot find name 'X'. -tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,25): error TS2304: Cannot find name 'Y'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(1,45): error TS2304: Cannot find name 'B'. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(4,9): error TS2315: Type 'C' is not generic. tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(5,9): error TS2304: Cannot find name 'D'. @@ -11,14 +9,10 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts(14,16): error TS2304: Cannot find name 'F'. -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (11 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (9 errors) ==== class C extends A, Y>> implements B, Y>> { ~ !!! error TS2304: Cannot find name 'A'. - ~ -!!! error TS2304: Cannot find name 'X'. - ~ -!!! error TS2304: Cannot find name 'Y'. ~ !!! error TS2304: Cannot find name 'B'. } diff --git a/tests/baselines/reference/recursiveBaseCheck3.errors.txt b/tests/baselines/reference/recursiveBaseCheck3.errors.txt index 827c9ed2e05e6..ba0ea669c55d1 100644 --- a/tests/baselines/reference/recursiveBaseCheck3.errors.txt +++ b/tests/baselines/reference/recursiveBaseCheck3.errors.txt @@ -1,9 +1,10 @@ tests/cases/compiler/recursiveBaseCheck3.ts(1,7): error TS2506: 'A' is referenced directly or indirectly in its own base expression. tests/cases/compiler/recursiveBaseCheck3.ts(1,20): error TS2449: Class 'C' used before its declaration. tests/cases/compiler/recursiveBaseCheck3.ts(2,7): error TS2506: 'C' is referenced directly or indirectly in its own base expression. +tests/cases/compiler/recursiveBaseCheck3.ts(4,9): error TS2339: Property 'blah' does not exist on type 'C<{}>'. -==== tests/cases/compiler/recursiveBaseCheck3.ts (3 errors) ==== +==== tests/cases/compiler/recursiveBaseCheck3.ts (4 errors) ==== class A extends C { } ~ !!! error TS2506: 'A' is referenced directly or indirectly in its own base expression. @@ -13,4 +14,6 @@ tests/cases/compiler/recursiveBaseCheck3.ts(2,7): error TS2506: 'C' is reference ~ !!! error TS2506: 'C' is referenced directly or indirectly in its own base expression. - (new C).blah; \ No newline at end of file + (new C).blah; + ~~~~ +!!! error TS2339: Property 'blah' does not exist on type 'C<{}>'. \ No newline at end of file diff --git a/tests/baselines/reference/recursiveBaseCheck4.errors.txt b/tests/baselines/reference/recursiveBaseCheck4.errors.txt index 7c030cfc8abd2..5616523d14e06 100644 --- a/tests/baselines/reference/recursiveBaseCheck4.errors.txt +++ b/tests/baselines/reference/recursiveBaseCheck4.errors.txt @@ -1,8 +1,11 @@ tests/cases/compiler/recursiveBaseCheck4.ts(1,7): error TS2506: 'M' is referenced directly or indirectly in its own base expression. +tests/cases/compiler/recursiveBaseCheck4.ts(2,9): error TS2339: Property 'blah' does not exist on type 'M<{}>'. -==== tests/cases/compiler/recursiveBaseCheck4.ts (1 errors) ==== +==== tests/cases/compiler/recursiveBaseCheck4.ts (2 errors) ==== class M extends M { } ~ !!! error TS2506: 'M' is referenced directly or indirectly in its own base expression. - (new M).blah; \ No newline at end of file + (new M).blah; + ~~~~ +!!! error TS2339: Property 'blah' does not exist on type 'M<{}>'. \ No newline at end of file diff --git a/tests/baselines/reference/recursiveBaseCheck6.errors.txt b/tests/baselines/reference/recursiveBaseCheck6.errors.txt index 2ff827fb091bc..6d453da425fb1 100644 --- a/tests/baselines/reference/recursiveBaseCheck6.errors.txt +++ b/tests/baselines/reference/recursiveBaseCheck6.errors.txt @@ -1,8 +1,11 @@ tests/cases/compiler/recursiveBaseCheck6.ts(1,7): error TS2506: 'S18' is referenced directly or indirectly in its own base expression. +tests/cases/compiler/recursiveBaseCheck6.ts(2,13): error TS2339: Property 'blah' does not exist on type 'S18<{}>'. -==== tests/cases/compiler/recursiveBaseCheck6.ts (1 errors) ==== +==== tests/cases/compiler/recursiveBaseCheck6.ts (2 errors) ==== class S18 extends S18<{ S19: A; }>{ } ~~~ !!! error TS2506: 'S18' is referenced directly or indirectly in its own base expression. - (new S18()).blah; \ No newline at end of file + (new S18()).blah; + ~~~~ +!!! error TS2339: Property 'blah' does not exist on type 'S18<{}>'. \ No newline at end of file From 441e54ce00c564eda76a821277d23f37bf6fef02 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 5 Apr 2017 15:49:34 -0700 Subject: [PATCH 10/12] Update comment --- src/compiler/checker.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 409c83573caee..404767aee8bc3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1597,7 +1597,6 @@ namespace ts { } // Unlike a failed import, an untyped module produces a dummy symbol. // This is checked for by `isUntypedOrShorthandAmbientModuleSymbol`. - // This must be different than `unknownSymbol` because `getBaseConstructorTypeOfClass` won't fail for `unknownSymbol`. return untypedModuleSymbol; } From 90d5c299b0dac01b982a120904a5512db2721112 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 5 Apr 2017 16:01:04 -0700 Subject: [PATCH 11/12] Remove special symbol for untyped modules Extending symbols from untyped modules is no longer an error, so #12532 didn't get us anything except slightly better quick info. --- src/compiler/checker.ts | 17 ++++++----------- src/compiler/utilities.ts | 4 ++-- src/services/findAllReferences.ts | 2 +- tests/cases/fourslash/untypedModuleImport.ts | 2 +- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 404767aee8bc3..6e5168dc8a2a6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -203,8 +203,6 @@ namespace ts { const evolvingArrayTypes: EvolvingArrayType[] = []; const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown"); - const untypedModuleSymbol = createSymbol(SymbolFlags.ValueModule, ""); - untypedModuleSymbol.exports = createMap(); const resolvingSymbol = createSymbol(0, "__resolving__"); const anyType = createIntrinsicType(TypeFlags.Any, "any"); @@ -1253,7 +1251,7 @@ namespace ts { if (moduleSymbol) { let exportDefaultSymbol: Symbol; - if (isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol)) { + if (isShorthandAmbientModuleSymbol(moduleSymbol)) { exportDefaultSymbol = moduleSymbol; } else { @@ -1333,7 +1331,7 @@ namespace ts { if (targetSymbol) { const name = specifier.propertyName || specifier.name; if (name.text) { - if (isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol)) { + if (isShorthandAmbientModuleSymbol(moduleSymbol)) { return moduleSymbol; } @@ -1586,18 +1584,15 @@ namespace ts { if (isForAugmentation) { const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); - return undefined; } else if (noImplicitAny && moduleNotFoundError) { error(errorNode, Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, moduleReference, resolvedModule.resolvedFileName); - return undefined; } - // Unlike a failed import, an untyped module produces a dummy symbol. - // This is checked for by `isUntypedOrShorthandAmbientModuleSymbol`. - return untypedModuleSymbol; + // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first. + return undefined; } if (moduleNotFoundError) { @@ -4367,7 +4362,7 @@ namespace ts { function getTypeOfFuncClassEnumModule(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - if (symbol.flags & SymbolFlags.Module && isUntypedOrShorthandAmbientModuleSymbol(symbol)) { + if (symbol.flags & SymbolFlags.Module && isShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } else { @@ -22063,7 +22058,7 @@ namespace ts { function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean { let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); - if (!moduleSymbol || isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol)) { + if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) { // If the module is not found or is shorthand, assume that it may export a value. return true; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 33cb0d8f4898d..b79ca0df1442e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -439,8 +439,8 @@ namespace ts { } /** Given a symbol for a module, checks that it is either an untyped import or a shorthand ambient module. */ - export function isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { - return !moduleSymbol.declarations || isShorthandAmbientModule(moduleSymbol.valueDeclaration); + export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { + return isShorthandAmbientModule(moduleSymbol.valueDeclaration); } function isShorthandAmbientModule(node: Node): boolean { diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 5a471fb6f356c..5ef450b11f0de 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -187,7 +187,7 @@ namespace ts.FindAllReferences { return { symbol }; } - if (ts.isUntypedOrShorthandAmbientModuleSymbol(aliasedSymbol)) { + if (ts.isShorthandAmbientModuleSymbol(aliasedSymbol)) { return { symbol, shorthandModuleSymbol: aliasedSymbol }; } diff --git a/tests/cases/fourslash/untypedModuleImport.ts b/tests/cases/fourslash/untypedModuleImport.ts index 433c584e3cfcd..1854010d5b68f 100644 --- a/tests/cases/fourslash/untypedModuleImport.ts +++ b/tests/cases/fourslash/untypedModuleImport.ts @@ -12,7 +12,7 @@ verify.numberOfErrorsInCurrentFile(0); goTo.marker("fooModule"); verify.goToDefinitionIs([]); -verify.quickInfoIs("module "); +verify.quickInfoIs(""); verify.noReferences(); goTo.marker("foo"); From f635042255fd4e11b46e5fd38872d7c5b0e9c9ef Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 6 Apr 2017 09:02:18 -0700 Subject: [PATCH 12/12] Improve test and comments Test asserts that unused locals error works for untyped modules. Comment no longer claims to check for untyped modules. --- src/compiler/utilities.ts | 2 +- .../reference/extendsUntypedModule.errors.txt | 18 ++++++++++++++++++ .../reference/extendsUntypedModule.js | 7 ++++++- .../reference/extendsUntypedModule.symbols | 8 -------- .../reference/extendsUntypedModule.types | 8 -------- tests/cases/compiler/extendsUntypedModule.ts | 7 ++++++- 6 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 tests/baselines/reference/extendsUntypedModule.errors.txt delete mode 100644 tests/baselines/reference/extendsUntypedModule.symbols delete mode 100644 tests/baselines/reference/extendsUntypedModule.types diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b79ca0df1442e..da05ef2947e9b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -438,7 +438,7 @@ namespace ts { ((node).name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(node)); } - /** Given a symbol for a module, checks that it is either an untyped import or a shorthand ambient module. */ + /** Given a symbol for a module, checks that it is a shorthand ambient module. */ export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { return isShorthandAmbientModule(moduleSymbol.valueDeclaration); } diff --git a/tests/baselines/reference/extendsUntypedModule.errors.txt b/tests/baselines/reference/extendsUntypedModule.errors.txt new file mode 100644 index 0000000000000..4667f16b74a6e --- /dev/null +++ b/tests/baselines/reference/extendsUntypedModule.errors.txt @@ -0,0 +1,18 @@ +/a.ts(2,8): error TS6133: 'Bar' is declared but never used. + + +==== /a.ts (1 errors) ==== + import Foo from "foo"; + import Bar from "bar"; // error: unused + ~~~ +!!! error TS6133: 'Bar' is declared but never used. + export class A extends Foo { } + +==== /node_modules/foo/index.js (0 errors) ==== + // Test that extending an untyped module is an error, unlike extending unknownSymbol. + + This file is not read. + +==== /node_modules/bar/index.js (0 errors) ==== + Nor is this one. + \ No newline at end of file diff --git a/tests/baselines/reference/extendsUntypedModule.js b/tests/baselines/reference/extendsUntypedModule.js index f86ded7e6cb9f..5ccd7babe9890 100644 --- a/tests/baselines/reference/extendsUntypedModule.js +++ b/tests/baselines/reference/extendsUntypedModule.js @@ -5,9 +5,13 @@ This file is not read. +//// [index.js] +Nor is this one. + //// [a.ts] import Foo from "foo"; -class A extends Foo { } +import Bar from "bar"; // error: unused +export class A extends Foo { } //// [a.js] @@ -31,3 +35,4 @@ var A = (function (_super) { } return A; }(foo_1["default"])); +exports.A = A; diff --git a/tests/baselines/reference/extendsUntypedModule.symbols b/tests/baselines/reference/extendsUntypedModule.symbols deleted file mode 100644 index 9036963d7d303..0000000000000 --- a/tests/baselines/reference/extendsUntypedModule.symbols +++ /dev/null @@ -1,8 +0,0 @@ -=== /a.ts === -import Foo from "foo"; ->Foo : Symbol(Foo, Decl(a.ts, 0, 6)) - -class A extends Foo { } ->A : Symbol(A, Decl(a.ts, 0, 22)) ->Foo : Symbol(Foo, Decl(a.ts, 0, 6)) - diff --git a/tests/baselines/reference/extendsUntypedModule.types b/tests/baselines/reference/extendsUntypedModule.types deleted file mode 100644 index 50fa8b821b3eb..0000000000000 --- a/tests/baselines/reference/extendsUntypedModule.types +++ /dev/null @@ -1,8 +0,0 @@ -=== /a.ts === -import Foo from "foo"; ->Foo : any - -class A extends Foo { } ->A : A ->Foo : any - diff --git a/tests/cases/compiler/extendsUntypedModule.ts b/tests/cases/compiler/extendsUntypedModule.ts index 8eaf6b3833a83..0ebd9d0f72cf1 100644 --- a/tests/cases/compiler/extendsUntypedModule.ts +++ b/tests/cases/compiler/extendsUntypedModule.ts @@ -1,9 +1,14 @@ // Test that extending an untyped module is an error, unlike extending unknownSymbol. // @noImplicitReferences: true +// @noUnusedLocals: true // @Filename: /node_modules/foo/index.js This file is not read. +// @Filename: /node_modules/bar/index.js +Nor is this one. + // @Filename: /a.ts import Foo from "foo"; -class A extends Foo { } +import Bar from "bar"; // error: unused +export class A extends Foo { }