From a901930723b66b29ec3cfbc0f588406e3873384f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 15 Aug 2018 16:03:28 -0700 Subject: [PATCH 01/77] Ensure for-in loop variable is checked --- src/compiler/checker.ts | 4 +-- .../reference/capturedLetConstInLoop1.js | 22 +++++++++++++ .../reference/capturedLetConstInLoop1.symbols | 26 +++++++++++++++ .../reference/capturedLetConstInLoop1.types | 32 +++++++++++++++++++ .../cases/compiler/capturedLetConstInLoop1.ts | 10 ++++++ 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8f6b5aceb61..5cc1d0da6a9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18321,7 +18321,7 @@ namespace ts { return errorType; } - const indexType = isForInVariableForNumericPropertyNames(indexExpression) ? numberType : checkExpression(indexExpression); + const indexType = checkExpression(indexExpression); if (objectType === errorType || objectType === silentNeverType) { return objectType; @@ -18332,7 +18332,7 @@ namespace ts { return errorType; } - return checkIndexedAccessIndexType(getIndexedAccessType(objectType, indexType, node), node); + return checkIndexedAccessIndexType(getIndexedAccessType(objectType, isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType, node), node); } function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean { diff --git a/tests/baselines/reference/capturedLetConstInLoop1.js b/tests/baselines/reference/capturedLetConstInLoop1.js index e526092d082..3c064059cb0 100644 --- a/tests/baselines/reference/capturedLetConstInLoop1.js +++ b/tests/baselines/reference/capturedLetConstInLoop1.js @@ -111,6 +111,16 @@ for (const y = 0; y < 1;) { const x = 1; (function() { return x + y}); (() => x + y); +} + +// https://github.com/Microsoft/TypeScript/issues/20594 +declare const sobj: { [x: string]: any }; +for (let sx in sobj) { + (() => sobj[sx]); +} +declare const iobj: { [x: number]: any }; +for (let ix in iobj) { + (() => iobj[ix]); } //// [capturedLetConstInLoop1.js] @@ -270,3 +280,15 @@ var _loop_20 = function (y) { for (var y = 0; y < 1;) { _loop_20(y); } +var _loop_21 = function (sx) { + (function () { return sobj[sx]; }); +}; +for (var sx in sobj) { + _loop_21(sx); +} +var _loop_22 = function (ix) { + (function () { return iobj[ix]; }); +}; +for (var ix in iobj) { + _loop_22(ix); +} diff --git a/tests/baselines/reference/capturedLetConstInLoop1.symbols b/tests/baselines/reference/capturedLetConstInLoop1.symbols index 51e2d4c4112..afa7898a258 100644 --- a/tests/baselines/reference/capturedLetConstInLoop1.symbols +++ b/tests/baselines/reference/capturedLetConstInLoop1.symbols @@ -258,3 +258,29 @@ for (const y = 0; y < 1;) { >x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 109, 9)) >y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 108, 10)) } + +// https://github.com/Microsoft/TypeScript/issues/20594 +declare const sobj: { [x: string]: any }; +>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 115, 13)) +>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 115, 23)) + +for (let sx in sobj) { +>sx : Symbol(sx, Decl(capturedLetConstInLoop1.ts, 116, 8)) +>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 115, 13)) + + (() => sobj[sx]); +>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 115, 13)) +>sx : Symbol(sx, Decl(capturedLetConstInLoop1.ts, 116, 8)) +} +declare const iobj: { [x: number]: any }; +>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 119, 13)) +>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 119, 23)) + +for (let ix in iobj) { +>ix : Symbol(ix, Decl(capturedLetConstInLoop1.ts, 120, 8)) +>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 119, 13)) + + (() => iobj[ix]); +>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 119, 13)) +>ix : Symbol(ix, Decl(capturedLetConstInLoop1.ts, 120, 8)) +} diff --git a/tests/baselines/reference/capturedLetConstInLoop1.types b/tests/baselines/reference/capturedLetConstInLoop1.types index 45d4a1c9368..34ba101752b 100644 --- a/tests/baselines/reference/capturedLetConstInLoop1.types +++ b/tests/baselines/reference/capturedLetConstInLoop1.types @@ -426,3 +426,35 @@ for (const y = 0; y < 1;) { >x : 1 >y : 0 } + +// https://github.com/Microsoft/TypeScript/issues/20594 +declare const sobj: { [x: string]: any }; +>sobj : { [x: string]: any; } +>x : string + +for (let sx in sobj) { +>sx : string +>sobj : { [x: string]: any; } + + (() => sobj[sx]); +>(() => sobj[sx]) : () => any +>() => sobj[sx] : () => any +>sobj[sx] : any +>sobj : { [x: string]: any; } +>sx : string +} +declare const iobj: { [x: number]: any }; +>iobj : { [x: number]: any; } +>x : number + +for (let ix in iobj) { +>ix : string +>iobj : { [x: number]: any; } + + (() => iobj[ix]); +>(() => iobj[ix]) : () => any +>() => iobj[ix] : () => any +>iobj[ix] : any +>iobj : { [x: number]: any; } +>ix : string +} diff --git a/tests/cases/compiler/capturedLetConstInLoop1.ts b/tests/cases/compiler/capturedLetConstInLoop1.ts index bc731fdd35f..e4956fd16df 100644 --- a/tests/cases/compiler/capturedLetConstInLoop1.ts +++ b/tests/cases/compiler/capturedLetConstInLoop1.ts @@ -110,4 +110,14 @@ for (const y = 0; y < 1;) { const x = 1; (function() { return x + y}); (() => x + y); +} + +// https://github.com/Microsoft/TypeScript/issues/20594 +declare const sobj: { [x: string]: any }; +for (let sx in sobj) { + (() => sobj[sx]); +} +declare const iobj: { [x: number]: any }; +for (let ix in iobj) { + (() => iobj[ix]); } \ No newline at end of file From 44ada08e0204ed747e8bbab4c565c3588fb0119e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 12:41:31 -0700 Subject: [PATCH 02/77] Guard against infinite type instantiations and constraints --- src/compiler/checker.ts | 57 ++++++++++++++++++---------- src/compiler/diagnosticMessages.json | 4 -- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9bcd6708b22..d82844f55fe 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -53,7 +53,8 @@ namespace ts { let typeCount = 0; let symbolCount = 0; let enumCount = 0; - let symbolInstantiationDepth = 0; + let instantiationDepth = 0; + let constraintDepth = 0; const emptySymbols = createSymbolTable(); const identityMapper: (type: Type) => Type = identity; @@ -5295,22 +5296,14 @@ namespace ts { function getTypeOfInstantiatedSymbol(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - if (symbolInstantiationDepth === 100) { - error(symbol.valueDeclaration, Diagnostics.Generic_type_instantiation_is_excessively_deep_and_possibly_infinite); - links.type = errorType; + if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { + return links.type = errorType; } - else { - if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { - return links.type = errorType; - } - symbolInstantiationDepth++; - let type = instantiateType(getTypeOfSymbol(links.target!), links.mapper!); - symbolInstantiationDepth--; - if (!popTypeResolution()) { - type = reportCircularityError(symbol); - } - links.type = type; + let type = instantiateType(getTypeOfSymbol(links.target!), links.mapper!); + if (!popTypeResolution()) { + type = reportCircularityError(symbol); } + links.type = type; } return links.type; } @@ -7003,6 +6996,7 @@ namespace ts { * circularly references the type variable. */ function getResolvedBaseConstraint(type: InstantiableType | UnionOrIntersectionType): Type { + let nonTerminating = false; return type.resolvedBaseConstraint || (type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), type)); @@ -7011,8 +7005,18 @@ namespace ts { if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) { return circularConstraintType; } + if (constraintDepth === 50) { + // We have reached 50 recursive invocations of getImmediateBaseConstraint and there is a + // very high likelyhood we're dealing with an infinite generic type that perpetually generates + // new type identities as we descend into it. We stop the recursion here and mark this type + // and the outer types as having circular constraints. + nonTerminating = true; + return t.immediateBaseConstraint = noConstraintType; + } + constraintDepth++; let result = computeBaseConstraint(getSimplifiedType(t)); - if (!popTypeResolution()) { + constraintDepth--; + if (!popTypeResolution() || nonTerminating) { result = circularConstraintType; } t.immediateBaseConstraint = result || noConstraintType; @@ -10282,12 +10286,25 @@ namespace ts { return getConditionalType(root, mapper); } + function instantiateWithDepthCheck(type: Type, mapper: TypeMapper, instantiator: (type: Type, mapper: TypeMapper) => Type): Type { + if (instantiationDepth < 50) { + instantiationDepth++; + const result = instantiator(type, mapper); + instantiationDepth--; + return result; + } + // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing + // with a combination of infinite generic types that perpetually generate new type identities. We stop + // the recursion here by yielding the error type. + return errorType; + } + function instantiateType(type: Type, mapper: TypeMapper | undefined): Type; function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined; function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined { if (type && mapper && mapper !== identityMapper) { if (type.flags & TypeFlags.TypeParameter) { - return mapper(type); + return mapper(type); } if (type.flags & TypeFlags.Object) { if ((type).objectFlags & ObjectFlags.Anonymous) { @@ -10295,10 +10312,10 @@ namespace ts { // interface, in an object type literal, or in an object literal expression, we may need // to instantiate the type because it might reference a type parameter. return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ? - getAnonymousTypeInstantiation(type, mapper) : type; + instantiateWithDepthCheck(type, mapper, getAnonymousTypeInstantiation) : type; } if ((type).objectFlags & ObjectFlags.Mapped) { - return getAnonymousTypeInstantiation(type, mapper); + return instantiateWithDepthCheck(type, mapper, getAnonymousTypeInstantiation); } if ((type).objectFlags & ObjectFlags.Reference) { const typeArguments = (type).typeArguments; @@ -10323,7 +10340,7 @@ namespace ts { return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); } if (type.flags & TypeFlags.Conditional) { - return getConditionalTypeInstantiation(type, combineTypeMappers((type).mapper, mapper)); + return instantiateWithDepthCheck(type, combineTypeMappers((type).mapper, mapper), getConditionalTypeInstantiation); } if (type.flags & TypeFlags.Substitution) { return instantiateType((type).typeVariable, mapper); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6000c48de4d..32a07c0818d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1964,10 +1964,6 @@ "category": "Error", "code": 2549 }, - "Generic type instantiation is excessively deep and possibly infinite.": { - "category": "Error", - "code": 2550 - }, "Property '{0}' does not exist on type '{1}'. Did you mean '{2}'?": { "category": "Error", "code": 2551 From 6262ac8b3d5c3b50b26b4c88be545621de4a574c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 12:41:48 -0700 Subject: [PATCH 03/77] Add tests --- tests/cases/compiler/infiniteConstraints.ts | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/cases/compiler/infiniteConstraints.ts diff --git a/tests/cases/compiler/infiniteConstraints.ts b/tests/cases/compiler/infiniteConstraints.ts new file mode 100644 index 00000000000..70d3879da6b --- /dev/null +++ b/tests/cases/compiler/infiniteConstraints.ts @@ -0,0 +1,33 @@ +// @strict: true + +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + +type T1], { val: string }>["val"] }> = B; +type T2]["val"] }> = B; + +// Repros from #22950 + +type AProp = T + +declare function myBug< + T extends { [K in keyof T]: T[K] extends AProp ? U : never } +>(arg: T): T + +const out = myBug({obj1: {a: "test"}}) + +type Value = Record<"val", V>; +declare function value(val: V): Value; + +declare function ensureNoDuplicates< + T extends { + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ? never + : any + } +>(vals: T): void; + +const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); + +const shouldBeNoError = ensureNoDuplicates({main: value("test")}); + +const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); From a15fecdc52a9bbe16635ab222ec860d447f0d172 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 12:41:56 -0700 Subject: [PATCH 04/77] Accept new baselines --- .../reference/infiniteConstraints.errors.txt | 45 +++++++ .../reference/infiniteConstraints.js | 41 ++++++ .../reference/infiniteConstraints.symbols | 122 ++++++++++++++++++ .../reference/infiniteConstraints.types | 89 +++++++++++++ 4 files changed, 297 insertions(+) create mode 100644 tests/baselines/reference/infiniteConstraints.errors.txt create mode 100644 tests/baselines/reference/infiniteConstraints.js create mode 100644 tests/baselines/reference/infiniteConstraints.symbols create mode 100644 tests/baselines/reference/infiniteConstraints.types diff --git a/tests/baselines/reference/infiniteConstraints.errors.txt b/tests/baselines/reference/infiniteConstraints.errors.txt new file mode 100644 index 00000000000..108c3693783 --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.errors.txt @@ -0,0 +1,45 @@ +tests/cases/compiler/infiniteConstraints.ts(4,37): error TS2536: Type '"val"' cannot be used to index type 'B[Exclude]'. +tests/cases/compiler/infiniteConstraints.ts(31,42): error TS2345: Argument of type '{ main: Record<"val", "dup">; alternate: Record<"val", "dup">; }' is not assignable to parameter of type '{ main: never; alternate: never; }'. + Types of property 'main' are incompatible. + Type 'Record<"val", "dup">' is not assignable to type 'never'. + + +==== tests/cases/compiler/infiniteConstraints.ts (2 errors) ==== + // Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + + type T1], { val: string }>["val"] }> = B; + type T2]["val"] }> = B; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type '"val"' cannot be used to index type 'B[Exclude]'. + + // Repros from #22950 + + type AProp = T + + declare function myBug< + T extends { [K in keyof T]: T[K] extends AProp ? U : never } + >(arg: T): T + + const out = myBug({obj1: {a: "test"}}) + + type Value = Record<"val", V>; + declare function value(val: V): Value; + + declare function ensureNoDuplicates< + T extends { + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ? never + : any + } + >(vals: T): void; + + const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); + + const shouldBeNoError = ensureNoDuplicates({main: value("test")}); + + const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ main: Record<"val", "dup">; alternate: Record<"val", "dup">; }' is not assignable to parameter of type '{ main: never; alternate: never; }'. +!!! error TS2345: Types of property 'main' are incompatible. +!!! error TS2345: Type 'Record<"val", "dup">' is not assignable to type 'never'. + \ No newline at end of file diff --git a/tests/baselines/reference/infiniteConstraints.js b/tests/baselines/reference/infiniteConstraints.js new file mode 100644 index 00000000000..0ad3b676f14 --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.js @@ -0,0 +1,41 @@ +//// [infiniteConstraints.ts] +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + +type T1], { val: string }>["val"] }> = B; +type T2]["val"] }> = B; + +// Repros from #22950 + +type AProp = T + +declare function myBug< + T extends { [K in keyof T]: T[K] extends AProp ? U : never } +>(arg: T): T + +const out = myBug({obj1: {a: "test"}}) + +type Value = Record<"val", V>; +declare function value(val: V): Value; + +declare function ensureNoDuplicates< + T extends { + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ? never + : any + } +>(vals: T): void; + +const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); + +const shouldBeNoError = ensureNoDuplicates({main: value("test")}); + +const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); + + +//// [infiniteConstraints.js] +"use strict"; +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint +var out = myBug({ obj1: { a: "test" } }); +var noError = ensureNoDuplicates({ main: value("test"), alternate: value("test2") }); +var shouldBeNoError = ensureNoDuplicates({ main: value("test") }); +var shouldBeError = ensureNoDuplicates({ main: value("dup"), alternate: value("dup") }); diff --git a/tests/baselines/reference/infiniteConstraints.symbols b/tests/baselines/reference/infiniteConstraints.symbols new file mode 100644 index 00000000000..0f0d44c9f53 --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.symbols @@ -0,0 +1,122 @@ +=== tests/cases/compiler/infiniteConstraints.ts === +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + +type T1], { val: string }>["val"] }> = B; +>T1 : Symbol(T1, Decl(infiniteConstraints.ts, 0, 0)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 2, 21)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 2, 21)) +>val : Symbol(val, Decl(infiniteConstraints.ts, 2, 69)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) + +type T2]["val"] }> = B; +>T2 : Symbol(T2, Decl(infiniteConstraints.ts, 2, 99)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 3, 21)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 3, 21)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) + +// Repros from #22950 + +type AProp = T +>AProp : Symbol(AProp, Decl(infiniteConstraints.ts, 3, 73)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 7, 11)) +>a : Symbol(a, Decl(infiniteConstraints.ts, 7, 22)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 7, 11)) + +declare function myBug< +>myBug : Symbol(myBug, Decl(infiniteConstraints.ts, 7, 39)) + + T extends { [K in keyof T]: T[K] extends AProp ? U : never } +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 10, 15)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 10, 15)) +>AProp : Symbol(AProp, Decl(infiniteConstraints.ts, 3, 73)) +>U : Symbol(U, Decl(infiniteConstraints.ts, 10, 54)) +>U : Symbol(U, Decl(infiniteConstraints.ts, 10, 54)) + +>(arg: T): T +>arg : Symbol(arg, Decl(infiniteConstraints.ts, 11, 2)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) + +const out = myBug({obj1: {a: "test"}}) +>out : Symbol(out, Decl(infiniteConstraints.ts, 13, 5)) +>myBug : Symbol(myBug, Decl(infiniteConstraints.ts, 7, 39)) +>obj1 : Symbol(obj1, Decl(infiniteConstraints.ts, 13, 19)) +>a : Symbol(a, Decl(infiniteConstraints.ts, 13, 26)) + +type Value = Record<"val", V>; +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 15, 11)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 15, 11)) + +declare function value(val: V): Value; +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 16, 23)) +>val : Symbol(val, Decl(infiniteConstraints.ts, 16, 41)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 16, 23)) +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 16, 23)) + +declare function ensureNoDuplicates< +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) + + T extends { +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) + + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] +>K : Symbol(K, Decl(infiniteConstraints.ts, 20, 5)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 20, 5)) +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 20, 5)) +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) + + ? never + : any + } +>(vals: T): void; +>vals : Symbol(vals, Decl(infiniteConstraints.ts, 24, 2)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) + +const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); +>noError : Symbol(noError, Decl(infiniteConstraints.ts, 26, 5)) +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) +>main : Symbol(main, Decl(infiniteConstraints.ts, 26, 36)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) +>alternate : Symbol(alternate, Decl(infiniteConstraints.ts, 26, 56)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) + +const shouldBeNoError = ensureNoDuplicates({main: value("test")}); +>shouldBeNoError : Symbol(shouldBeNoError, Decl(infiniteConstraints.ts, 28, 5)) +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) +>main : Symbol(main, Decl(infiniteConstraints.ts, 28, 44)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) + +const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); +>shouldBeError : Symbol(shouldBeError, Decl(infiniteConstraints.ts, 30, 5)) +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) +>main : Symbol(main, Decl(infiniteConstraints.ts, 30, 42)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) +>alternate : Symbol(alternate, Decl(infiniteConstraints.ts, 30, 61)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) + diff --git a/tests/baselines/reference/infiniteConstraints.types b/tests/baselines/reference/infiniteConstraints.types new file mode 100644 index 00000000000..78fbc9becaa --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.types @@ -0,0 +1,89 @@ +=== tests/cases/compiler/infiniteConstraints.ts === +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + +type T1], { val: string }>["val"] }> = B; +>T1 : B +>val : string + +type T2]["val"] }> = B; +>T2 : B + +// Repros from #22950 + +type AProp = T +>AProp : T +>a : string + +declare function myBug< +>myBug : (arg: T) => T + + T extends { [K in keyof T]: T[K] extends AProp ? U : never } +>(arg: T): T +>arg : T + +const out = myBug({obj1: {a: "test"}}) +>out : { obj1: { a: string; }; } +>myBug({obj1: {a: "test"}}) : { obj1: { a: string; }; } +>myBug : (arg: T) => T +>{obj1: {a: "test"}} : { obj1: { a: string; }; } +>obj1 : { a: string; } +>{a: "test"} : { a: string; } +>a : string +>"test" : "test" + +type Value = Record<"val", V>; +>Value : Record<"val", V> + +declare function value(val: V): Value; +>value : (val: V) => Record<"val", V> +>val : V + +declare function ensureNoDuplicates< +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void + + T extends { + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ? never + : any + } +>(vals: T): void; +>vals : T + +const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); +>noError : void +>ensureNoDuplicates({main: value("test"), alternate: value("test2")}) : void +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void +>{main: value("test"), alternate: value("test2")} : { main: Record<"val", "test">; alternate: Record<"val", "test2">; } +>main : Record<"val", "test"> +>value("test") : Record<"val", "test"> +>value : (val: V) => Record<"val", V> +>"test" : "test" +>alternate : Record<"val", "test2"> +>value("test2") : Record<"val", "test2"> +>value : (val: V) => Record<"val", V> +>"test2" : "test2" + +const shouldBeNoError = ensureNoDuplicates({main: value("test")}); +>shouldBeNoError : void +>ensureNoDuplicates({main: value("test")}) : void +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void +>{main: value("test")} : { main: Record<"val", "test">; } +>main : Record<"val", "test"> +>value("test") : Record<"val", "test"> +>value : (val: V) => Record<"val", V> +>"test" : "test" + +const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); +>shouldBeError : any +>ensureNoDuplicates({main: value("dup"), alternate: value("dup")}) : any +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void +>{main: value("dup"), alternate: value("dup")} : { main: Record<"val", "dup">; alternate: Record<"val", "dup">; } +>main : Record<"val", "dup"> +>value("dup") : Record<"val", "dup"> +>value : (val: V) => Record<"val", V> +>"dup" : "dup" +>alternate : Record<"val", "dup"> +>value("dup") : Record<"val", "dup"> +>value : (val: V) => Record<"val", V> +>"dup" : "dup" + From 15eaba254b005f08831afa4004515c76812d64ca Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 16:04:11 -0700 Subject: [PATCH 05/77] Covariant inferences (other than never) preferred over contravariant --- src/compiler/checker.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26b93b19335..c9f70463db8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13638,10 +13638,11 @@ namespace ts { if (!inferredType) { const signature = context.signature; if (signature) { - if (inference.contraCandidates) { - // If we have contravariant inferences we find the best common subtype and treat - // that as a single covariant candidate. - inference.candidates = append(inference.candidates, getContravariantInference(inference)); + if (inference.contraCandidates && (!inference.candidates || inference.candidates.length === 1 && inference.candidates[0].flags & TypeFlags.Never)) { + // If we have contravariant inferences, but no covariant inferences or a single + // covariant inference of 'never', we find the best common subtype and treat that + // as a single covariant candidate. + inference.candidates = [getContravariantInference(inference)]; inference.contraCandidates = undefined; } if (inference.candidates) { From a0df1e35e9f37b0cbf9eee28aa0df1bd3da06e2d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 16:04:21 -0700 Subject: [PATCH 06/77] Accept new baselines --- tests/baselines/reference/strictFunctionTypes1.js | 6 +++--- tests/baselines/reference/strictFunctionTypes1.types | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/strictFunctionTypes1.js b/tests/baselines/reference/strictFunctionTypes1.js index 45d28f72501..94ee06f88f8 100644 --- a/tests/baselines/reference/strictFunctionTypes1.js +++ b/tests/baselines/reference/strictFunctionTypes1.js @@ -50,11 +50,11 @@ declare function fo(x: Object): void; declare function fs(x: string): void; declare function fx(f: (x: "def") => void): void; declare const x1: (x: string) => void; -declare const x2: string; -declare const x3: Object; +declare const x2 = "abc"; +declare const x3: string; declare const x4: Func; declare const never: never; declare const x10: string; -declare const x11: Object; +declare const x11: "def"; declare function foo(a: ReadonlyArray): T; declare let x: never; diff --git a/tests/baselines/reference/strictFunctionTypes1.types b/tests/baselines/reference/strictFunctionTypes1.types index 6a824d8ff7e..0a1a952c0b5 100644 --- a/tests/baselines/reference/strictFunctionTypes1.types +++ b/tests/baselines/reference/strictFunctionTypes1.types @@ -53,16 +53,16 @@ const x1 = f1(fo, fs); // (x: string) => void >fs : (x: string) => void const x2 = f2("abc", fo, fs); // "abc" ->x2 : string ->f2("abc", fo, fs) : string +>x2 : "abc" +>f2("abc", fo, fs) : "abc" >f2 : (obj: T, f1: (x: T) => void, f2: (x: T) => void) => T >"abc" : "abc" >fo : (x: Object) => void >fs : (x: string) => void const x3 = f3("abc", fo, fx); // "abc" | "def" ->x3 : Object ->f3("abc", fo, fx) : Object +>x3 : "def" | "abc" +>f3("abc", fo, fx) : "def" | "abc" >f3 : (obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void) => T >"abc" : "abc" >fo : (x: Object) => void @@ -87,8 +87,8 @@ const x10 = f2(never, fo, fs); // string >fs : (x: string) => void const x11 = f3(never, fo, fx); // "def" ->x11 : Object ->f3(never, fo, fx) : Object +>x11 : "def" +>f3(never, fo, fx) : "def" >f3 : (obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void) => T >never : never >fo : (x: Object) => void From 88f7759d6baf4bcd456b722c63caa18ac799463e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 16:21:25 -0700 Subject: [PATCH 07/77] Add tests --- tests/cases/compiler/strictFunctionTypes1.ts | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/cases/compiler/strictFunctionTypes1.ts b/tests/cases/compiler/strictFunctionTypes1.ts index ad8836fcf05..411aab812df 100644 --- a/tests/cases/compiler/strictFunctionTypes1.ts +++ b/tests/cases/compiler/strictFunctionTypes1.ts @@ -27,3 +27,27 @@ const x11 = f3(never, fo, fx); // "def" declare function foo(a: ReadonlyArray): T; let x = foo([]); // never + +// Modified repros from #26127 + +interface A { a: string } +interface B extends A { b: string } + +declare function acceptUnion(x: A | number): void; +declare function acceptA(x: A): void; + +declare let a: A; +declare let b: B; +declare let never: never; + +declare function coAndContra(value: T, func: (t: T) => void): T; + +const t1: A = coAndContra(a, acceptUnion); +const t2: B = coAndContra(b, acceptA); +const t3: A = coAndContra(never, acceptA); + +declare function coAndContraArray(value: T[], func: (t: T) => void): T[]; + +const t4: A[] = coAndContraArray([a], acceptUnion); +const t5: B[] = coAndContraArray([b], acceptA); +const t6: A[] = coAndContraArray([], acceptA); From 886a6d7473d3d13010dcaacad3c19916e467ed55 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 16:23:09 -0700 Subject: [PATCH 08/77] Fix test --- tests/cases/compiler/strictFunctionTypes1.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/compiler/strictFunctionTypes1.ts b/tests/cases/compiler/strictFunctionTypes1.ts index 411aab812df..19dbe37cb79 100644 --- a/tests/cases/compiler/strictFunctionTypes1.ts +++ b/tests/cases/compiler/strictFunctionTypes1.ts @@ -38,7 +38,6 @@ declare function acceptA(x: A): void; declare let a: A; declare let b: B; -declare let never: never; declare function coAndContra(value: T, func: (t: T) => void): T; From f182389c5ba9405b1d8f7ecadd652967e38160f9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 20 Aug 2018 16:23:21 -0700 Subject: [PATCH 09/77] Accept new baselines --- .../reference/strictFunctionTypes1.js | 47 ++++++++++ .../reference/strictFunctionTypes1.symbols | 90 +++++++++++++++++++ .../reference/strictFunctionTypes1.types | 78 ++++++++++++++++ 3 files changed, 215 insertions(+) diff --git a/tests/baselines/reference/strictFunctionTypes1.js b/tests/baselines/reference/strictFunctionTypes1.js index 94ee06f88f8..c12e56545f6 100644 --- a/tests/baselines/reference/strictFunctionTypes1.js +++ b/tests/baselines/reference/strictFunctionTypes1.js @@ -25,6 +25,29 @@ const x11 = f3(never, fo, fx); // "def" declare function foo(a: ReadonlyArray): T; let x = foo([]); // never + +// Modified repros from #26127 + +interface A { a: string } +interface B extends A { b: string } + +declare function acceptUnion(x: A | number): void; +declare function acceptA(x: A): void; + +declare let a: A; +declare let b: B; + +declare function coAndContra(value: T, func: (t: T) => void): T; + +const t1: A = coAndContra(a, acceptUnion); +const t2: B = coAndContra(b, acceptA); +const t3: A = coAndContra(never, acceptA); + +declare function coAndContraArray(value: T[], func: (t: T) => void): T[]; + +const t4: A[] = coAndContraArray([a], acceptUnion); +const t5: B[] = coAndContraArray([b], acceptA); +const t6: A[] = coAndContraArray([], acceptA); //// [strictFunctionTypes1.js] @@ -36,6 +59,12 @@ var x4 = f4(fo, fs); // Func var x10 = f2(never, fo, fs); // string var x11 = f3(never, fo, fx); // "def" var x = foo([]); // never +var t1 = coAndContra(a, acceptUnion); +var t2 = coAndContra(b, acceptA); +var t3 = coAndContra(never, acceptA); +var t4 = coAndContraArray([a], acceptUnion); +var t5 = coAndContraArray([b], acceptA); +var t6 = coAndContraArray([], acceptA); //// [strictFunctionTypes1.d.ts] @@ -58,3 +87,21 @@ declare const x10: string; declare const x11: "def"; declare function foo(a: ReadonlyArray): T; declare let x: never; +interface A { + a: string; +} +interface B extends A { + b: string; +} +declare function acceptUnion(x: A | number): void; +declare function acceptA(x: A): void; +declare let a: A; +declare let b: B; +declare function coAndContra(value: T, func: (t: T) => void): T; +declare const t1: A; +declare const t2: B; +declare const t3: A; +declare function coAndContraArray(value: T[], func: (t: T) => void): T[]; +declare const t4: A[]; +declare const t5: B[]; +declare const t6: A[]; diff --git a/tests/baselines/reference/strictFunctionTypes1.symbols b/tests/baselines/reference/strictFunctionTypes1.symbols index ed657495cc4..911c561094b 100644 --- a/tests/baselines/reference/strictFunctionTypes1.symbols +++ b/tests/baselines/reference/strictFunctionTypes1.symbols @@ -125,3 +125,93 @@ let x = foo([]); // never >x : Symbol(x, Decl(strictFunctionTypes1.ts, 25, 3)) >foo : Symbol(foo, Decl(strictFunctionTypes1.ts, 20, 30)) +// Modified repros from #26127 + +interface A { a: string } +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) +>a : Symbol(A.a, Decl(strictFunctionTypes1.ts, 29, 13)) + +interface B extends A { b: string } +>B : Symbol(B, Decl(strictFunctionTypes1.ts, 29, 25)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) +>b : Symbol(B.b, Decl(strictFunctionTypes1.ts, 30, 23)) + +declare function acceptUnion(x: A | number): void; +>acceptUnion : Symbol(acceptUnion, Decl(strictFunctionTypes1.ts, 30, 35)) +>x : Symbol(x, Decl(strictFunctionTypes1.ts, 32, 29)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) + +declare function acceptA(x: A): void; +>acceptA : Symbol(acceptA, Decl(strictFunctionTypes1.ts, 32, 50)) +>x : Symbol(x, Decl(strictFunctionTypes1.ts, 33, 25)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) + +declare let a: A; +>a : Symbol(a, Decl(strictFunctionTypes1.ts, 35, 11)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) + +declare let b: B; +>b : Symbol(b, Decl(strictFunctionTypes1.ts, 36, 11)) +>B : Symbol(B, Decl(strictFunctionTypes1.ts, 29, 25)) + +declare function coAndContra(value: T, func: (t: T) => void): T; +>coAndContra : Symbol(coAndContra, Decl(strictFunctionTypes1.ts, 36, 17)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 38, 29)) +>value : Symbol(value, Decl(strictFunctionTypes1.ts, 38, 32)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 38, 29)) +>func : Symbol(func, Decl(strictFunctionTypes1.ts, 38, 41)) +>t : Symbol(t, Decl(strictFunctionTypes1.ts, 38, 49)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 38, 29)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 38, 29)) + +const t1: A = coAndContra(a, acceptUnion); +>t1 : Symbol(t1, Decl(strictFunctionTypes1.ts, 40, 5)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) +>coAndContra : Symbol(coAndContra, Decl(strictFunctionTypes1.ts, 36, 17)) +>a : Symbol(a, Decl(strictFunctionTypes1.ts, 35, 11)) +>acceptUnion : Symbol(acceptUnion, Decl(strictFunctionTypes1.ts, 30, 35)) + +const t2: B = coAndContra(b, acceptA); +>t2 : Symbol(t2, Decl(strictFunctionTypes1.ts, 41, 5)) +>B : Symbol(B, Decl(strictFunctionTypes1.ts, 29, 25)) +>coAndContra : Symbol(coAndContra, Decl(strictFunctionTypes1.ts, 36, 17)) +>b : Symbol(b, Decl(strictFunctionTypes1.ts, 36, 11)) +>acceptA : Symbol(acceptA, Decl(strictFunctionTypes1.ts, 32, 50)) + +const t3: A = coAndContra(never, acceptA); +>t3 : Symbol(t3, Decl(strictFunctionTypes1.ts, 42, 5)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) +>coAndContra : Symbol(coAndContra, Decl(strictFunctionTypes1.ts, 36, 17)) +>never : Symbol(never, Decl(strictFunctionTypes1.ts, 17, 13)) +>acceptA : Symbol(acceptA, Decl(strictFunctionTypes1.ts, 32, 50)) + +declare function coAndContraArray(value: T[], func: (t: T) => void): T[]; +>coAndContraArray : Symbol(coAndContraArray, Decl(strictFunctionTypes1.ts, 42, 42)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 44, 34)) +>value : Symbol(value, Decl(strictFunctionTypes1.ts, 44, 37)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 44, 34)) +>func : Symbol(func, Decl(strictFunctionTypes1.ts, 44, 48)) +>t : Symbol(t, Decl(strictFunctionTypes1.ts, 44, 56)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 44, 34)) +>T : Symbol(T, Decl(strictFunctionTypes1.ts, 44, 34)) + +const t4: A[] = coAndContraArray([a], acceptUnion); +>t4 : Symbol(t4, Decl(strictFunctionTypes1.ts, 46, 5)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) +>coAndContraArray : Symbol(coAndContraArray, Decl(strictFunctionTypes1.ts, 42, 42)) +>a : Symbol(a, Decl(strictFunctionTypes1.ts, 35, 11)) +>acceptUnion : Symbol(acceptUnion, Decl(strictFunctionTypes1.ts, 30, 35)) + +const t5: B[] = coAndContraArray([b], acceptA); +>t5 : Symbol(t5, Decl(strictFunctionTypes1.ts, 47, 5)) +>B : Symbol(B, Decl(strictFunctionTypes1.ts, 29, 25)) +>coAndContraArray : Symbol(coAndContraArray, Decl(strictFunctionTypes1.ts, 42, 42)) +>b : Symbol(b, Decl(strictFunctionTypes1.ts, 36, 11)) +>acceptA : Symbol(acceptA, Decl(strictFunctionTypes1.ts, 32, 50)) + +const t6: A[] = coAndContraArray([], acceptA); +>t6 : Symbol(t6, Decl(strictFunctionTypes1.ts, 48, 5)) +>A : Symbol(A, Decl(strictFunctionTypes1.ts, 25, 16)) +>coAndContraArray : Symbol(coAndContraArray, Decl(strictFunctionTypes1.ts, 42, 42)) +>acceptA : Symbol(acceptA, Decl(strictFunctionTypes1.ts, 32, 50)) + diff --git a/tests/baselines/reference/strictFunctionTypes1.types b/tests/baselines/reference/strictFunctionTypes1.types index 0a1a952c0b5..058b066f4c5 100644 --- a/tests/baselines/reference/strictFunctionTypes1.types +++ b/tests/baselines/reference/strictFunctionTypes1.types @@ -106,3 +106,81 @@ let x = foo([]); // never >foo : (a: ReadonlyArray) => T >[] : never[] +// Modified repros from #26127 + +interface A { a: string } +>a : string + +interface B extends A { b: string } +>b : string + +declare function acceptUnion(x: A | number): void; +>acceptUnion : (x: number | A) => void +>x : number | A + +declare function acceptA(x: A): void; +>acceptA : (x: A) => void +>x : A + +declare let a: A; +>a : A + +declare let b: B; +>b : B + +declare function coAndContra(value: T, func: (t: T) => void): T; +>coAndContra : (value: T, func: (t: T) => void) => T +>value : T +>func : (t: T) => void +>t : T + +const t1: A = coAndContra(a, acceptUnion); +>t1 : A +>coAndContra(a, acceptUnion) : A +>coAndContra : (value: T, func: (t: T) => void) => T +>a : A +>acceptUnion : (x: number | A) => void + +const t2: B = coAndContra(b, acceptA); +>t2 : B +>coAndContra(b, acceptA) : B +>coAndContra : (value: T, func: (t: T) => void) => T +>b : B +>acceptA : (x: A) => void + +const t3: A = coAndContra(never, acceptA); +>t3 : A +>coAndContra(never, acceptA) : A +>coAndContra : (value: T, func: (t: T) => void) => T +>never : never +>acceptA : (x: A) => void + +declare function coAndContraArray(value: T[], func: (t: T) => void): T[]; +>coAndContraArray : (value: T[], func: (t: T) => void) => T[] +>value : T[] +>func : (t: T) => void +>t : T + +const t4: A[] = coAndContraArray([a], acceptUnion); +>t4 : A[] +>coAndContraArray([a], acceptUnion) : A[] +>coAndContraArray : (value: T[], func: (t: T) => void) => T[] +>[a] : A[] +>a : A +>acceptUnion : (x: number | A) => void + +const t5: B[] = coAndContraArray([b], acceptA); +>t5 : B[] +>coAndContraArray([b], acceptA) : B[] +>coAndContraArray : (value: T[], func: (t: T) => void) => T[] +>[b] : B[] +>b : B +>acceptA : (x: A) => void + +const t6: A[] = coAndContraArray([], acceptA); +>t6 : A[] +>coAndContraArray([], acceptA) : A[] +>coAndContraArray : (value: T[], func: (t: T) => void) => T[] +>[] : never[] +>acceptA : (x: A) => void + From 7c2644a6762efd2b1937bd406c346d3c67d75c52 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 21 Aug 2018 06:30:47 -0700 Subject: [PATCH 10/77] Perform depth check for all type instantiations --- src/compiler/checker.ts | 110 +++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b8dd117d6fd..5d2b0187eb0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10294,65 +10294,69 @@ namespace ts { return getConditionalType(root, mapper); } - function instantiateWithDepthCheck(type: Type, mapper: TypeMapper, instantiator: (type: Type, mapper: TypeMapper) => Type): Type { - if (instantiationDepth < 50) { - instantiationDepth++; - const result = instantiator(type, mapper); - instantiationDepth--; - return result; - } - // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing - // with a combination of infinite generic types that perpetually generate new type identities. We stop - // the recursion here by yielding the error type. - return errorType; - } - function instantiateType(type: Type, mapper: TypeMapper | undefined): Type; function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined; function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined { - if (type && mapper && mapper !== identityMapper) { - if (type.flags & TypeFlags.TypeParameter) { - return mapper(type); + if (!type || !mapper || mapper === identityMapper) { + return type; + } + if (instantiationDepth === 50) { + // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing + // with a combination of infinite generic types that perpetually generate new type identities. We stop + // the recursion here by yielding the error type. + return errorType; + } + instantiationDepth++; + const result = instantiateTypeWorker(type, mapper); + instantiationDepth--; + return result; + } + + function instantiateTypeWorker(type: Type, mapper: TypeMapper): Type { + const flags = type.flags; + if (flags & TypeFlags.TypeParameter) { + return mapper(type); + } + if (flags & TypeFlags.Object) { + const objectFlags = (type).objectFlags; + if (objectFlags & ObjectFlags.Anonymous) { + // If the anonymous type originates in a declaration of a function, method, class, or + // interface, in an object type literal, or in an object literal expression, we may need + // to instantiate the type because it might reference a type parameter. + return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ? + getAnonymousTypeInstantiation(type, mapper) : type; } - if (type.flags & TypeFlags.Object) { - if ((type).objectFlags & ObjectFlags.Anonymous) { - // If the anonymous type originates in a declaration of a function, method, class, or - // interface, in an object type literal, or in an object literal expression, we may need - // to instantiate the type because it might reference a type parameter. - return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ? - instantiateWithDepthCheck(type, mapper, getAnonymousTypeInstantiation) : type; - } - if ((type).objectFlags & ObjectFlags.Mapped) { - return instantiateWithDepthCheck(type, mapper, getAnonymousTypeInstantiation); - } - if ((type).objectFlags & ObjectFlags.Reference) { - const typeArguments = (type).typeArguments; - const newTypeArguments = instantiateTypes(typeArguments, mapper); - return newTypeArguments !== typeArguments ? createTypeReference((type).target, newTypeArguments) : type; - } + if (objectFlags & ObjectFlags.Mapped) { + return getAnonymousTypeInstantiation(type, mapper); } - if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) { - const types = (type).types; - const newTypes = instantiateTypes(types, mapper); - return newTypes !== types ? getUnionType(newTypes, UnionReduction.Literal, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; - } - if (type.flags & TypeFlags.Intersection) { - const types = (type).types; - const newTypes = instantiateTypes(types, mapper); - return newTypes !== types ? getIntersectionType(newTypes, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; - } - if (type.flags & TypeFlags.Index) { - return getIndexType(instantiateType((type).type, mapper)); - } - if (type.flags & TypeFlags.IndexedAccess) { - return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); - } - if (type.flags & TypeFlags.Conditional) { - return instantiateWithDepthCheck(type, combineTypeMappers((type).mapper, mapper), getConditionalTypeInstantiation); - } - if (type.flags & TypeFlags.Substitution) { - return instantiateType((type).typeVariable, mapper); + if (objectFlags & ObjectFlags.Reference) { + const typeArguments = (type).typeArguments; + const newTypeArguments = instantiateTypes(typeArguments, mapper); + return newTypeArguments !== typeArguments ? createTypeReference((type).target, newTypeArguments) : type; } + return type; + } + if (flags & TypeFlags.Union && !(flags & TypeFlags.Primitive)) { + const types = (type).types; + const newTypes = instantiateTypes(types, mapper); + return newTypes !== types ? getUnionType(newTypes, UnionReduction.Literal, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; + } + if (flags & TypeFlags.Intersection) { + const types = (type).types; + const newTypes = instantiateTypes(types, mapper); + return newTypes !== types ? getIntersectionType(newTypes, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; + } + if (flags & TypeFlags.Index) { + return getIndexType(instantiateType((type).type, mapper)); + } + if (flags & TypeFlags.IndexedAccess) { + return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); + } + if (flags & TypeFlags.Conditional) { + return getConditionalTypeInstantiation(type, combineTypeMappers((type).mapper, mapper)); + } + if (flags & TypeFlags.Substitution) { + return instantiateType((type).typeVariable, mapper); } return type; } From 17ee9231b7cd3cf27ee2d9d923bb4482cb798665 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 17 Aug 2018 14:05:05 -0700 Subject: [PATCH 11/77] Write first test with --build and --watch --- src/compiler/program.ts | 50 +++++++------- src/harness/virtualFileSystemWithWatch.ts | 14 +++- src/testRunner/tsconfig.json | 1 + src/testRunner/unittests/tsbuildWatchMode.ts | 69 +++++++++++++++++++ src/testRunner/unittests/tscWatchMode.ts | 25 ++++--- .../unittests/tsserverProjectSystem.ts | 6 +- .../reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 8 files changed, 123 insertions(+), 46 deletions(-) create mode 100644 src/testRunner/unittests/tsbuildWatchMode.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index abbc935cf65..1c7430e3300 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -66,20 +66,20 @@ namespace ts { mtime: Date; } - export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { + export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost { const existingDirectories = createMap(); function getCanonicalFileName(fileName: string): string { // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. // otherwise use toLowerCase as a canonical form. - return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined { let text: string | undefined; try { performance.mark("beforeIORead"); - text = sys.readFile(fileName, options.charset); + text = system.readFile(fileName, options.charset); performance.mark("afterIORead"); performance.measure("I/O Read", "beforeIORead", "afterIORead"); } @@ -97,7 +97,7 @@ namespace ts { if (existingDirectories.has(directoryPath)) { return true; } - if (sys.directoryExists(directoryPath)) { + if (system.directoryExists(directoryPath)) { existingDirectories.set(directoryPath, true); return true; } @@ -108,7 +108,7 @@ namespace ts { if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { const parentDirectory = getDirectoryPath(directoryPath); ensureDirectoriesExist(parentDirectory); - sys.createDirectory(directoryPath); + system.createDirectory(directoryPath); } } @@ -119,8 +119,8 @@ namespace ts { outputFingerprints = createMap(); } - const hash = sys.createHash!(data); // TODO: GH#18217 - const mtimeBefore = sys.getModifiedTime!(fileName); // TODO: GH#18217 + const hash = system.createHash!(data); // TODO: GH#18217 + const mtimeBefore = system.getModifiedTime!(fileName); // TODO: GH#18217 if (mtimeBefore) { const fingerprint = outputFingerprints.get(fileName); @@ -133,9 +133,9 @@ namespace ts { } } - sys.writeFile(fileName, data, writeByteOrderMark); + system.writeFile(fileName, data, writeByteOrderMark); - const mtimeAfter = sys.getModifiedTime!(fileName) || missingFileModifiedTime; // TODO: GH#18217 + const mtimeAfter = system.getModifiedTime!(fileName) || missingFileModifiedTime; // TODO: GH#18217 outputFingerprints.set(fileName, { hash, @@ -149,11 +149,11 @@ namespace ts { performance.mark("beforeIOWrite"); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); - if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) { + if (isWatchSet(options) && system.createHash && system.getModifiedTime) { writeFileIfUpdated(fileName, data, writeByteOrderMark); } else { - sys.writeFile(fileName, data, writeByteOrderMark); + system.writeFile(fileName, data, writeByteOrderMark); } performance.mark("afterIOWrite"); @@ -167,32 +167,32 @@ namespace ts { } function getDefaultLibLocation(): string { - return getDirectoryPath(normalizePath(sys.getExecutingFilePath())); + return getDirectoryPath(normalizePath(system.getExecutingFilePath())); } const newLine = getNewLineCharacter(options); - const realpath = sys.realpath && ((path: string) => sys.realpath!(path)); + const realpath = system.realpath && ((path: string) => system.realpath!(path)); return { getSourceFile, getDefaultLibLocation, getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)), writeFile, - getCurrentDirectory: memoize(() => sys.getCurrentDirectory()), - useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, + getCurrentDirectory: memoize(() => system.getCurrentDirectory()), + useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine, - fileExists: fileName => sys.fileExists(fileName), - readFile: fileName => sys.readFile(fileName), - trace: (s: string) => sys.write(s + newLine), - directoryExists: directoryName => sys.directoryExists(directoryName), - getEnvironmentVariable: name => sys.getEnvironmentVariable ? sys.getEnvironmentVariable(name) : "", - getDirectories: (path: string) => sys.getDirectories(path), + fileExists: fileName => system.fileExists(fileName), + readFile: fileName => system.readFile(fileName), + trace: (s: string) => system.write(s + newLine), + directoryExists: directoryName => system.directoryExists(directoryName), + getEnvironmentVariable: name => system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : "", + getDirectories: (path: string) => system.getDirectories(path), realpath, - readDirectory: (path, extensions, include, exclude, depth) => sys.readDirectory(path, extensions, include, exclude, depth), - getModifiedTime: sys.getModifiedTime && (path => sys.getModifiedTime!(path)), - setModifiedTime: sys.setModifiedTime && ((path, date) => sys.setModifiedTime!(path, date)), - deleteFile: sys.deleteFile && (path => sys.deleteFile!(path)) + readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth), + getModifiedTime: system.getModifiedTime && (path => system.getModifiedTime!(path)), + setModifiedTime: system.setModifiedTime && ((path, date) => system.setModifiedTime!(path, date)), + deleteFile: system.deleteFile && (path => system.deleteFile!(path)) }; } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 2a2ed4ef7dc..57fa33a84c2 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -620,14 +620,14 @@ interface Array {}` } } - removeFile(filePath: string) { + deleteFile(filePath: string) { const path = this.toFullPath(filePath); const currentEntry = this.fs.get(path) as FsFile; Debug.assert(isFsFile(currentEntry)); this.removeFileOrFolder(currentEntry, returnFalse); } - removeFolder(folderPath: string, recursive?: boolean) { + deleteFolder(folderPath: string, recursive?: boolean) { const path = this.toFullPath(folderPath); const currentEntry = this.fs.get(path) as FsFolder; Debug.assert(isFsFolder(currentEntry)); @@ -635,7 +635,7 @@ interface Array {}` const subEntries = currentEntry.entries.slice(); subEntries.forEach(fsEntry => { if (isFsFolder(fsEntry)) { - this.removeFolder(fsEntry.fullPath, recursive); + this.deleteFolder(fsEntry.fullPath, recursive); } else { this.removeFileOrFolder(fsEntry, returnFalse); @@ -766,6 +766,14 @@ interface Array {}` return (fsEntry && fsEntry.modifiedTime)!; // TODO: GH#18217 } + setModifiedTime(s: string, date: Date) { + const path = this.toFullPath(s); + const fsEntry = this.fs.get(path); + if (fsEntry) { + fsEntry.modifiedTime = date; + } + } + readFile(s: string): string | undefined { const fsEntry = this.getRealFile(this.toFullPath(s)); return fsEntry ? fsEntry.content : undefined; diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index 12c671f9cf0..fa7900f1ca3 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -80,6 +80,7 @@ "unittests/transform.ts", "unittests/transpile.ts", "unittests/tsbuild.ts", + "unittests/tsbuildWatchMode.ts", "unittests/tsconfigParsing.ts", "unittests/tscWatchMode.ts", "unittests/versionCache.ts", diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts new file mode 100644 index 00000000000..9f608180d03 --- /dev/null +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -0,0 +1,69 @@ +namespace ts.tscWatch { + export import libFile = TestFSWithWatch.libFile; + function createSolutionBuilder(host: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { + const compilerHost = createCompilerHost({}, /*setParentNodes*/ undefined, host); + const reportDiag = createDiagnosticReporter(host); + const report = (message: DiagnosticMessage, ...args: string[]) => reportDiag(createCompilerDiagnostic(message, ...args)); + const buildHost: BuildHost = { + error: report, + verbose: report, + message: report, + errorDiagnostic: d => reportDiag(d) + }; + return ts.createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions || { dry: false, force: false, verbose: false }, host); + } + + function createSolutionBuilderWithWatch(host: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { + const solutionBuilder = createSolutionBuilder(host, rootNames, defaultOptions); + solutionBuilder.buildAllProjects(); + solutionBuilder.startWatching(); + return solutionBuilder; + } + + describe("tsbuild-watch program updates", () => { + const projectsLocation = "/user/username/projects"; + const project = "sample1"; + const enum SubProject { + core = "core", + logic = "logic", + tests = "tests", + ui = "ui" + } + type ReadonlyFile = Readonly; + /** [tsconfig, index] | [tsconfig, index, anotherModule, someDecl] */ + type SubProjectFiles = [ReadonlyFile, ReadonlyFile] | [ReadonlyFile, ReadonlyFile, ReadonlyFile, ReadonlyFile]; + const root = Harness.IO.getWorkspaceRoot(); + function projectFile(subProject: SubProject, baseFileName: string): File { + return { + path: `${projectsLocation}/${project}/${subProject}/${baseFileName.toLowerCase()}`, + content: Harness.IO.readFile(`${root}/tests/projects/${project}/${subProject}/${baseFileName}`)! + }; + } + function subProjectFiles(subProject: SubProject, anotherModuleAndSomeDecl?: true): SubProjectFiles { + const tsconfig = projectFile(subProject, "tsconfig.json"); + const index = projectFile(subProject, "index.ts"); + if (!anotherModuleAndSomeDecl) { + return [tsconfig, index]; + } + const anotherModule = projectFile(SubProject.core, "anotherModule.ts"); + const someDecl = projectFile(SubProject.core, "some_decl.ts"); + return [tsconfig, index, anotherModule, someDecl]; + } + + const core = subProjectFiles(SubProject.core, /*anotherModuleAndSomeDecl*/ true); + const logic = subProjectFiles(SubProject.logic); + const tests = subProjectFiles(SubProject.tests); + const ui = subProjectFiles(SubProject.ui); + const allFiles: ReadonlyArray = [libFile, ...core, ...logic, ...tests, ...ui]; + const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path); + it("creates solution in watch mode", () => { + const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); + const originalWrite = host.write; + host.write = s => { console.log(s); originalWrite.call(host, s); }; + createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]); + checkWatchedFiles(host, testProjectExpectedWatchedFiles); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, emptyArray, /*recursive*/ true); // TODO: #26524 + }); + }); +} diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index d91559c72fc..51c0d888f0b 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -1,17 +1,16 @@ namespace ts.tscWatch { - import WatchedSystem = TestFSWithWatch.TestServerHost; - type File = TestFSWithWatch.File; - type SymLink = TestFSWithWatch.SymLink; - import createWatchedSystem = TestFSWithWatch.createWatchedSystem; - import checkArray = TestFSWithWatch.checkArray; - import libFile = TestFSWithWatch.libFile; - import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles; - import checkWatchedFilesDetailed = TestFSWithWatch.checkWatchedFilesDetailed; - import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories; - import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed; - import checkOutputContains = TestFSWithWatch.checkOutputContains; - import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain; - import Tsc_WatchDirectory = TestFSWithWatch.Tsc_WatchDirectory; + export import WatchedSystem = TestFSWithWatch.TestServerHost; + export type File = TestFSWithWatch.File; + export type SymLink = TestFSWithWatch.SymLink; + export import createWatchedSystem = TestFSWithWatch.createWatchedSystem; + export import checkArray = TestFSWithWatch.checkArray; + export import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles; + export import checkWatchedFilesDetailed = TestFSWithWatch.checkWatchedFilesDetailed; + export import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories; + export import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed; + export import checkOutputContains = TestFSWithWatch.checkOutputContains; + export import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain; + export import Tsc_WatchDirectory = TestFSWithWatch.Tsc_WatchDirectory; export function checkProgramActualFiles(program: Program, expectedFiles: string[]) { checkArray(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles); diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index b99a2d9fe99..5491d83965d 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -8257,7 +8257,7 @@ new C();` verifyProjectWithResolvedModule(session); - host.removeFolder(recognizersTextDist, /*recursive*/ true); + host.deleteFolder(recognizersTextDist, /*recursive*/ true); host.runQueuedTimeoutCallbacks(); verifyProjectWithUnresolvedModule(session); @@ -9173,7 +9173,7 @@ describe("Test Suite 1", () => { checkProjectActualFiles(project, expectedFilesWithUnitTest1); const navBarResultUnitTest1 = navBarFull(session, unitTest1); - host.removeFile(unitTest1.path); + host.deleteFile(unitTest1.path); host.checkTimeoutQueueLengthAndRun(2); checkProjectActualFiles(project, expectedFilesWithoutUnitTest1); @@ -9297,7 +9297,7 @@ export function Test2() { checkDeclarationFiles(bTs, session, [bDtsMap, bDts]); // Testing what happens if we delete the original sources. - host.removeFile(bTs.path); + host.deleteFile(bTs.path); openFilesForSession([userTs], session); const service = session.getProjectService(); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5e992f3847a..e41db162ae2 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4125,7 +4125,7 @@ declare namespace ts { declare namespace ts { function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined; function resolveTripleslashReference(moduleName: string, containingFile: string): string; - function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system?: System): CompilerHost; function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; interface FormatDiagnosticsHost { getCurrentDirectory(): string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 32761156558..fca9d26c306 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4125,7 +4125,7 @@ declare namespace ts { declare namespace ts { function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined; function resolveTripleslashReference(moduleName: string, containingFile: string): string; - function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system?: System): CompilerHost; function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; interface FormatDiagnosticsHost { getCurrentDirectory(): string; From d2240a40e19ecdb5b2547a2a6a58edb1852b0757 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 17 Aug 2018 15:24:37 -0700 Subject: [PATCH 12/77] Ger rid of unnecessary upto date host and functions pulled out --- src/compiler/tsbuild.ts | 373 +++++++++++++++++++--------------------- src/compiler/types.ts | 10 -- 2 files changed, 181 insertions(+), 202 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 966d795ed87..60f1d843e78 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -520,16 +520,6 @@ namespace ts { let context = createBuildContext(defaultOptions); const existingWatchersForWildcards = createMap(); - - const upToDateHost: UpToDateHost = { - fileExists: fileName => compilerHost.fileExists(fileName), - getModifiedTime: fileName => compilerHost.getModifiedTime!(fileName), - getUnchangedTime: fileName => context.unchangedOutputs.getValueOrUndefined(fileName), - getLastStatus: fileName => context.projectStatus.getValueOrUndefined(fileName), - setLastStatus: (fileName, status) => context.projectStatus.setValue(fileName, status), - parseConfigFile: configFilePath => configFileCache.parseConfigFile(configFilePath) - }; - return { buildAllProjects, getUpToDateStatus, @@ -611,7 +601,180 @@ namespace ts { } function getUpToDateStatus(project: ParsedCommandLine | undefined): UpToDateStatus { - return ts.getUpToDateStatus(upToDateHost, project); + if (project === undefined) { + return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; + } + + const prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath!); + if (prior !== undefined) { + return prior; + } + + const actual = getUpToDateStatusWorker(project); + context.projectStatus.setValue(project.options.configFilePath!, actual); + return actual; + } + + function getUpToDateStatusWorker(project: ParsedCommandLine): UpToDateStatus { + let newestInputFileName: string = undefined!; + let newestInputFileTime = minimumDate; + // Get timestamps of input files + for (const inputFile of project.fileNames) { + if (!compilerHost.fileExists(inputFile)) { + return { + type: UpToDateStatusType.Unbuildable, + reason: `${inputFile} does not exist` + }; + } + + const inputTime = compilerHost.getModifiedTime!(inputFile) || missingFileModifiedTime; + if (inputTime > newestInputFileTime) { + newestInputFileName = inputFile; + newestInputFileTime = inputTime; + } + } + + // Collect the expected outputs of this project + const outputs = getAllProjectOutputs(project); + + if (outputs.length === 0) { + return { + type: UpToDateStatusType.ContainerOnly + }; + } + + // Now see if all outputs are newer than the newest input + let oldestOutputFileName = "(none)"; + let oldestOutputFileTime = maximumDate; + let newestOutputFileName = "(none)"; + let newestOutputFileTime = minimumDate; + let missingOutputFileName: string | undefined; + let newestDeclarationFileContentChangedTime = minimumDate; + let isOutOfDateWithInputs = false; + for (const output of outputs) { + // Output is missing; can stop checking + // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status + if (!compilerHost.fileExists(output)) { + missingOutputFileName = output; + break; + } + + const outputTime = compilerHost.getModifiedTime!(output) || missingFileModifiedTime; + if (outputTime < oldestOutputFileTime) { + oldestOutputFileTime = outputTime; + oldestOutputFileName = output; + } + + // If an output is older than the newest input, we can stop checking + // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status + if (outputTime < newestInputFileTime) { + isOutOfDateWithInputs = true; + break; + } + + if (outputTime > newestOutputFileTime) { + newestOutputFileTime = outputTime; + newestOutputFileName = output; + } + + // Keep track of when the most recent time a .d.ts file was changed. + // In addition to file timestamps, we also keep track of when a .d.ts file + // had its file touched but not had its contents changed - this allows us + // to skip a downstream typecheck + if (isDeclarationFile(output)) { + const unchangedTime = context.unchangedOutputs.getValueOrUndefined(output); + if (unchangedTime !== undefined) { + newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime); + } + else { + const outputModifiedTime = compilerHost.getModifiedTime!(output) || missingFileModifiedTime; + newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime); + } + } + } + + let pseudoUpToDate = false; + let usesPrepend = false; + let upstreamChangedProject: string | undefined; + if (project.projectReferences) { + for (const ref of project.projectReferences) { + usesPrepend = usesPrepend || !!(ref.prepend); + const resolvedRef = resolveProjectReferencePath(compilerHost, ref); + const refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef)); + + // An upstream project is blocked + if (refStatus.type === UpToDateStatusType.Unbuildable) { + return { + type: UpToDateStatusType.UpstreamBlocked, + upstreamProjectName: ref.path + }; + } + + // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?) + if (refStatus.type !== UpToDateStatusType.UpToDate) { + return { + type: UpToDateStatusType.UpstreamOutOfDate, + upstreamProjectName: ref.path + }; + } + + // If the upstream project's newest file is older than our oldest output, we + // can't be out of date because of it + if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) { + continue; + } + + // If the upstream project has only change .d.ts files, and we've built + // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild + if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { + pseudoUpToDate = true; + upstreamChangedProject = ref.path; + continue; + } + + // We have an output older than an upstream output - we are out of date + Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here"); + return { + type: UpToDateStatusType.OutOfDateWithUpstream, + outOfDateOutputFileName: oldestOutputFileName, + newerProjectName: ref.path + }; + } + } + + if (missingOutputFileName !== undefined) { + return { + type: UpToDateStatusType.OutputMissing, + missingOutputFileName + }; + } + + if (isOutOfDateWithInputs) { + return { + type: UpToDateStatusType.OutOfDateWithSelf, + outOfDateOutputFileName: oldestOutputFileName, + newerInputFileName: newestInputFileName + }; + } + + if (usesPrepend && pseudoUpToDate) { + return { + type: UpToDateStatusType.OutOfDateWithUpstream, + outOfDateOutputFileName: oldestOutputFileName, + newerProjectName: upstreamChangedProject! + }; + } + + // Up to date + return { + type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate, + newestDeclarationFileContentChangedTime, + newestInputFileTime, + newestOutputFileTime, + newestInputFileName, + newestOutputFileName, + oldestOutputFileName + }; } function invalidateProject(configFileName: string) { @@ -1030,187 +1193,13 @@ namespace ts { } } - /** - * Gets the UpToDateStatus for a project - */ - export function getUpToDateStatus(host: UpToDateHost, project: ParsedCommandLine | undefined): UpToDateStatus { - if (project === undefined) { - return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; - } - - const prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath!) : undefined; - if (prior !== undefined) { - return prior; - } - - const actual = getUpToDateStatusWorker(host, project); - if (host.setLastStatus) { - host.setLastStatus(project.options.configFilePath!, actual); - } - - return actual; - } - - function getUpToDateStatusWorker(host: UpToDateHost, project: ParsedCommandLine): UpToDateStatus { - let newestInputFileName: string = undefined!; - let newestInputFileTime = minimumDate; - // Get timestamps of input files - for (const inputFile of project.fileNames) { - if (!host.fileExists(inputFile)) { - return { - type: UpToDateStatusType.Unbuildable, - reason: `${inputFile} does not exist` - }; - } - - const inputTime = host.getModifiedTime(inputFile) || missingFileModifiedTime; - if (inputTime > newestInputFileTime) { - newestInputFileName = inputFile; - newestInputFileTime = inputTime; - } - } - - // Collect the expected outputs of this project - const outputs = getAllProjectOutputs(project); - - if (outputs.length === 0) { - return { - type: UpToDateStatusType.ContainerOnly - }; - } - - // Now see if all outputs are newer than the newest input - let oldestOutputFileName = "(none)"; - let oldestOutputFileTime = maximumDate; - let newestOutputFileName = "(none)"; - let newestOutputFileTime = minimumDate; - let missingOutputFileName: string | undefined; - let newestDeclarationFileContentChangedTime = minimumDate; - let isOutOfDateWithInputs = false; - for (const output of outputs) { - // Output is missing; can stop checking - // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status - if (!host.fileExists(output)) { - missingOutputFileName = output; - break; - } - - const outputTime = host.getModifiedTime(output) || missingFileModifiedTime; - if (outputTime < oldestOutputFileTime) { - oldestOutputFileTime = outputTime; - oldestOutputFileName = output; - } - - // If an output is older than the newest input, we can stop checking - // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status - if (outputTime < newestInputFileTime) { - isOutOfDateWithInputs = true; - break; - } - - if (outputTime > newestOutputFileTime) { - newestOutputFileTime = outputTime; - newestOutputFileName = output; - } - - // Keep track of when the most recent time a .d.ts file was changed. - // In addition to file timestamps, we also keep track of when a .d.ts file - // had its file touched but not had its contents changed - this allows us - // to skip a downstream typecheck - if (isDeclarationFile(output)) { - const unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined; - if (unchangedTime !== undefined) { - newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime); - } - else { - const outputModifiedTime = host.getModifiedTime(output) || missingFileModifiedTime; - newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime); - } - } - } - - let pseudoUpToDate = false; - let usesPrepend = false; - let upstreamChangedProject: string | undefined; - if (project.projectReferences && host.parseConfigFile) { - for (const ref of project.projectReferences) { - usesPrepend = usesPrepend || !!(ref.prepend); - const resolvedRef = resolveProjectReferencePath(host, ref); - const refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef)); - - // An upstream project is blocked - if (refStatus.type === UpToDateStatusType.Unbuildable) { - return { - type: UpToDateStatusType.UpstreamBlocked, - upstreamProjectName: ref.path - }; - } - - // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?) - if (refStatus.type !== UpToDateStatusType.UpToDate) { - return { - type: UpToDateStatusType.UpstreamOutOfDate, - upstreamProjectName: ref.path - }; - } - - // If the upstream project's newest file is older than our oldest output, we - // can't be out of date because of it - if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) { - continue; - } - - // If the upstream project has only change .d.ts files, and we've built - // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild - if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { - pseudoUpToDate = true; - upstreamChangedProject = ref.path; - continue; - } - - // We have an output older than an upstream output - we are out of date - Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here"); - return { - type: UpToDateStatusType.OutOfDateWithUpstream, - outOfDateOutputFileName: oldestOutputFileName, - newerProjectName: ref.path - }; - } - } - - if (missingOutputFileName !== undefined) { - return { - type: UpToDateStatusType.OutputMissing, - missingOutputFileName - }; - } - - if (isOutOfDateWithInputs) { - return { - type: UpToDateStatusType.OutOfDateWithSelf, - outOfDateOutputFileName: oldestOutputFileName, - newerInputFileName: newestInputFileName - }; - } - - if (usesPrepend && pseudoUpToDate) { - return { - type: UpToDateStatusType.OutOfDateWithUpstream, - outOfDateOutputFileName: oldestOutputFileName, - newerProjectName: upstreamChangedProject! - }; - } - - // Up to date - return { - type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate, - newestDeclarationFileContentChangedTime, - newestInputFileTime, - newestOutputFileTime, - newestInputFileName, - newestOutputFileName, - oldestOutputFileName - }; + export interface UpToDateHost { + fileExists(fileName: string): boolean; + getModifiedTime(fileName: string): Date | undefined; + getUnchangedTime?(fileName: string): Date | undefined; + getLastStatus?(fileName: string): UpToDateStatus | undefined; + setLastStatus?(fileName: string, status: UpToDateStatus): void; + parseConfigFile?(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined; } export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4330a776d04..96129411db6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4715,16 +4715,6 @@ namespace ts { verticalTab = 0x0B, // \v } - /*@internal*/ - export interface UpToDateHost { - fileExists(fileName: string): boolean; - getModifiedTime(fileName: string): Date | undefined; - getUnchangedTime?(fileName: string): Date | undefined; - getLastStatus?(fileName: string): UpToDateStatus | undefined; - setLastStatus?(fileName: string, status: UpToDateStatus): void; - parseConfigFile?(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined; - } - export interface ModuleResolutionHost { // TODO: GH#18217 Optional methods frequently used as non-optional From 8e49fec80fda70e64a719d99fda3388161686f11 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 17 Aug 2018 16:42:59 -0700 Subject: [PATCH 13/77] Move perform build to tsc instead of tsbuild --- src/compiler/tsbuild.ts | 122 ---------------------------------------- src/tsc/tsc.ts | 122 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 122 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 60f1d843e78..87dcb0e2b57 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -385,128 +385,6 @@ namespace ts { }; } - const buildOpts: CommandLineOption[] = [ - { - name: "verbose", - shortName: "v", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Enable_verbose_logging, - type: "boolean" - }, - { - name: "dry", - shortName: "d", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, - type: "boolean" - }, - { - name: "force", - shortName: "f", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, - type: "boolean" - }, - { - name: "clean", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Delete_the_outputs_of_all_projects, - type: "boolean" - }, - { - name: "watch", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Watch_input_files, - type: "boolean" - } - ]; - - export function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined { - let verbose = false; - let dry = false; - let force = false; - let clean = false; - let watch = false; - - const projects: string[] = []; - for (const arg of args) { - switch (arg.toLowerCase()) { - case "-v": - case "--verbose": - verbose = true; - continue; - case "-d": - case "--dry": - dry = true; - continue; - case "-f": - case "--force": - force = true; - continue; - case "--clean": - clean = true; - continue; - case "--watch": - case "-w": - watch = true; - continue; - - case "--?": - case "-?": - case "--help": - printHelp(buildOpts, "--build "); - return ExitStatus.Success; - } - // Not a flag, parse as filename - addProject(arg); - } - - // Nonsensical combinations - if (clean && force) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; - } - if (clean && verbose) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; - } - if (clean && watch) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; - } - if (watch && dry) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; - } - - if (projects.length === 0) { - // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ." - addProject("."); - } - - const builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry, force, verbose }, system); - if (clean) { - return builder.cleanAllProjects(); - } - - if (watch) { - builder.buildAllProjects(); - builder.startWatching(); - return undefined; - } - - return builder.buildAllProjects(); - - function addProject(projectSpecification: string) { - const fileName = resolvePath(compilerHost.getCurrentDirectory(), projectSpecification); - const refPath = resolveProjectReferencePath(compilerHost, { path: fileName }); - if (!compilerHost.fileExists(refPath)) { - return buildHost.error(Diagnostics.File_0_does_not_exist, fileName); - } - projects.push(refPath); - } - } - /** * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but * can dynamically add/remove other projects based on changes on the rootNames' references diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index 97e239c8bca..f6f0db6e9aa 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -172,6 +172,128 @@ namespace ts { } } + const buildOpts: CommandLineOption[] = [ + { + name: "verbose", + shortName: "v", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Enable_verbose_logging, + type: "boolean" + }, + { + name: "dry", + shortName: "d", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, + type: "boolean" + }, + { + name: "force", + shortName: "f", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, + type: "boolean" + }, + { + name: "clean", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Delete_the_outputs_of_all_projects, + type: "boolean" + }, + { + name: "watch", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Watch_input_files, + type: "boolean" + } + ]; + + function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined { + let verbose = false; + let dry = false; + let force = false; + let clean = false; + let watch = false; + + const projects: string[] = []; + for (const arg of args) { + switch (arg.toLowerCase()) { + case "-v": + case "--verbose": + verbose = true; + continue; + case "-d": + case "--dry": + dry = true; + continue; + case "-f": + case "--force": + force = true; + continue; + case "--clean": + clean = true; + continue; + case "--watch": + case "-w": + watch = true; + continue; + + case "--?": + case "-?": + case "--help": + printHelp(buildOpts, "--build "); + return ExitStatus.Success; + } + // Not a flag, parse as filename + addProject(arg); + } + + // Nonsensical combinations + if (clean && force) { + buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"); + return ExitStatus.DiagnosticsPresent_OutputsSkipped; + } + if (clean && verbose) { + buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"); + return ExitStatus.DiagnosticsPresent_OutputsSkipped; + } + if (clean && watch) { + buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"); + return ExitStatus.DiagnosticsPresent_OutputsSkipped; + } + if (watch && dry) { + buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"); + return ExitStatus.DiagnosticsPresent_OutputsSkipped; + } + + if (projects.length === 0) { + // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ." + addProject("."); + } + + const builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry, force, verbose }, system); + if (clean) { + return builder.cleanAllProjects(); + } + + if (watch) { + builder.buildAllProjects(); + builder.startWatching(); + return undefined; + } + + return builder.buildAllProjects(); + + function addProject(projectSpecification: string) { + const fileName = resolvePath(compilerHost.getCurrentDirectory(), projectSpecification); + const refPath = resolveProjectReferencePath(compilerHost, { path: fileName }); + if (!compilerHost.fileExists(refPath)) { + return buildHost.error(Diagnostics.File_0_does_not_exist, fileName); + } + projects.push(refPath); + } + } + function performCompilation(rootNames: string[], projectReferences: ReadonlyArray | undefined, options: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray) { const host = createCompilerHost(options); enableStatistics(options); From 071d790dec9a679d089fd7b196b900b8e678fc33 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 17 Aug 2018 17:22:08 -0700 Subject: [PATCH 14/77] Unify tsbuild option parsing with command line options parsing --- src/compiler/commandLineParser.ts | 17 +-- src/compiler/diagnosticMessages.json | 5 + src/compiler/tsbuild.ts | 11 +- src/tsc/tsc.ts | 154 +++++++++++++-------------- 4 files changed, 99 insertions(+), 88 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 00920325721..f1dd4093956 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -815,10 +815,11 @@ namespace ts { } function getOptionNameMap(): OptionNameMap { - if (optionNameMapCache) { - return optionNameMapCache; - } + return optionNameMapCache || (optionNameMapCache = createOptionNameMap(optionDeclarations)); + } + /*@internal*/ + export function createOptionNameMap(optionDeclarations: ReadonlyArray): OptionNameMap { const optionNameMap = createMap(); const shortOptionNames = createMap(); forEach(optionDeclarations, option => { @@ -828,8 +829,7 @@ namespace ts { } }); - optionNameMapCache = { optionNameMap, shortOptionNames }; - return optionNameMapCache; + return { optionNameMap, shortOptionNames }; } /* @internal */ @@ -979,7 +979,12 @@ namespace ts { } /** @internal */ - export function getOptionFromName(optionName: string, allowShort = false): CommandLineOption | undefined { + export function getOptionFromName(optionName: string, allowShort?: boolean): CommandLineOption | undefined { + return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort); + } + + /*@internal*/ + export function getOptionDeclarationFromName(getOptionNameMap: () => OptionNameMap, optionName: string, allowShort = false): CommandLineOption | undefined { optionName = optionName.toLowerCase(); const { optionNameMap, shortOptionNames } = getOptionNameMap(); // Try to translate short option names to their full equivalents. diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6000c48de4d..6c517709f4f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2900,6 +2900,11 @@ "category": "Error", "code": 5071 }, + "Unknown build option '{0}'.": { + "category": "Error", + "code": 5072 + }, + "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 87dcb0e2b57..54737d470e7 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -47,10 +47,13 @@ namespace ts { dependencyMap: Mapper; } - interface BuildOptions { - dry: boolean; - force: boolean; - verbose: boolean; + export interface BuildOptions { + dry?: boolean; + force?: boolean; + verbose?: boolean; + /*@internal*/ clean?: boolean; + /*@internal*/ watch?: boolean; + /*@internal*/ help?: boolean; } enum BuildResultFlags { diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index f6f0db6e9aa..a863c684931 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -62,7 +62,7 @@ namespace ts { message: report, errorDiagnostic: d => reportDiag(d) }; - const result = performBuild(args.slice(1), createCompilerHost({}), buildHost, sys); + const result = performBuild(args.slice(1), createCompilerHost({}), buildHost); // undefined = in watch mode, do not exit if (result !== undefined) { return sys.exit(result); @@ -172,96 +172,94 @@ namespace ts { } } - const buildOpts: CommandLineOption[] = [ - { - name: "verbose", - shortName: "v", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Enable_verbose_logging, - type: "boolean" - }, - { - name: "dry", - shortName: "d", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, - type: "boolean" - }, - { - name: "force", - shortName: "f", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, - type: "boolean" - }, - { - name: "clean", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Delete_the_outputs_of_all_projects, - type: "boolean" - }, - { - name: "watch", - category: Diagnostics.Command_line_Options, - description: Diagnostics.Watch_input_files, - type: "boolean" - } - ]; - - function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined { - let verbose = false; - let dry = false; - let force = false; - let clean = false; - let watch = false; + function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost): number | undefined { + const buildOpts: CommandLineOption[] = [ + { + name: "help", + shortName: "h", + type: "boolean", + showInSimplifiedHelpView: true, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Print_this_message, + }, + { + name: "help", + shortName: "?", + type: "boolean" + }, + { + name: "verbose", + shortName: "v", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Enable_verbose_logging, + type: "boolean" + }, + { + name: "dry", + shortName: "d", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, + type: "boolean" + }, + { + name: "force", + shortName: "f", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, + type: "boolean" + }, + { + name: "clean", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Delete_the_outputs_of_all_projects, + type: "boolean" + }, + { + name: "watch", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Watch_input_files, + type: "boolean" + } + ]; + let buildOptionNameMap: OptionNameMap | undefined; + const returnBuildOptionNameMap = () => (buildOptionNameMap || (buildOptionNameMap = createOptionNameMap(buildOpts))); + const buildOptions: BuildOptions = {}; const projects: string[] = []; for (const arg of args) { - switch (arg.toLowerCase()) { - case "-v": - case "--verbose": - verbose = true; - continue; - case "-d": - case "--dry": - dry = true; - continue; - case "-f": - case "--force": - force = true; - continue; - case "--clean": - clean = true; - continue; - case "--watch": - case "-w": - watch = true; - continue; - - case "--?": - case "-?": - case "--help": - printHelp(buildOpts, "--build "); - return ExitStatus.Success; + if (arg.charCodeAt(0) === CharacterCodes.minus) { + const opt = getOptionDeclarationFromName(returnBuildOptionNameMap, arg.slice(arg.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true); + if (opt) { + buildOptions[opt.name as keyof BuildOptions] = true; + } + else { + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Unknown_build_option_0, arg)); + } } - // Not a flag, parse as filename - addProject(arg); + else { + // Not a flag, parse as filename + addProject(arg); + } + } + + if (buildOptions.help) { + printHelp(buildOpts, "--build "); return ExitStatus.Success; } // Nonsensical combinations - if (clean && force) { + if (buildOptions.clean && buildOptions.force) { buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } - if (clean && verbose) { + if (buildOptions.clean && buildOptions.verbose) { buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } - if (clean && watch) { + if (buildOptions.clean && buildOptions.watch) { buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } - if (watch && dry) { + if (buildOptions.watch && buildOptions.dry) { buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } @@ -271,12 +269,12 @@ namespace ts { addProject("."); } - const builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry, force, verbose }, system); - if (clean) { + const builder = createSolutionBuilder(compilerHost, buildHost, projects, buildOptions); + if (buildOptions.clean) { return builder.cleanAllProjects(); } - if (watch) { + if (buildOptions.watch) { builder.buildAllProjects(); builder.startWatching(); return undefined; From e20a7d851fe2e0843cc3648cf31daa2d28153a9f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 17 Aug 2018 17:27:19 -0700 Subject: [PATCH 15/77] Remove unnecessary usage of system and compilerHost --- src/tsc/tsc.ts | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index a863c684931..ff16a92f0fe 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -54,15 +54,7 @@ namespace ts { export function executeCommandLine(args: string[]): void { if (args.length > 0 && ((args[0].toLowerCase() === "--build") || (args[0].toLowerCase() === "-b"))) { - const reportDiag = createDiagnosticReporter(sys, defaultIsPretty()); - const report = (message: DiagnosticMessage, ...args: string[]) => reportDiag(createCompilerDiagnostic(message, ...args)); - const buildHost: BuildHost = { - error: report, - verbose: report, - message: report, - errorDiagnostic: d => reportDiag(d) - }; - const result = performBuild(args.slice(1), createCompilerHost({}), buildHost); + const result = performBuild(args.slice(1)); // undefined = in watch mode, do not exit if (result !== undefined) { return sys.exit(result); @@ -172,7 +164,7 @@ namespace ts { } } - function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost): number | undefined { + function performBuild(args: string[]): number | undefined { const buildOpts: CommandLineOption[] = [ { name: "help", @@ -243,24 +235,28 @@ namespace ts { } if (buildOptions.help) { - printHelp(buildOpts, "--build "); return ExitStatus.Success; + printHelp(buildOpts, "--build "); + return ExitStatus.Success; } + // Update to pretty if host supports it + updateReportDiagnostic({}); + // Nonsensical combinations if (buildOptions.clean && buildOptions.force) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force")); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } if (buildOptions.clean && buildOptions.verbose) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose")); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } if (buildOptions.clean && buildOptions.watch) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch")); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } if (buildOptions.watch && buildOptions.dry) { - buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry")); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } @@ -269,7 +265,15 @@ namespace ts { addProject("."); } - const builder = createSolutionBuilder(compilerHost, buildHost, projects, buildOptions); + const report = (message: DiagnosticMessage, ...args: string[]) => reportDiagnostic(createCompilerDiagnostic(message, ...args)); + const buildHost: BuildHost = { + error: report, + verbose: report, + message: report, + errorDiagnostic: d => reportDiagnostic(d) + }; + + const builder = createSolutionBuilder(createCompilerHost({}), buildHost, projects, buildOptions); if (buildOptions.clean) { return builder.cleanAllProjects(); } @@ -283,9 +287,9 @@ namespace ts { return builder.buildAllProjects(); function addProject(projectSpecification: string) { - const fileName = resolvePath(compilerHost.getCurrentDirectory(), projectSpecification); - const refPath = resolveProjectReferencePath(compilerHost, { path: fileName }); - if (!compilerHost.fileExists(refPath)) { + const fileName = resolvePath(sys.getCurrentDirectory(), projectSpecification); + const refPath = resolveProjectReferencePath(sys, { path: fileName }); + if (!sys.fileExists(refPath)) { return buildHost.error(Diagnostics.File_0_does_not_exist, fileName); } projects.push(refPath); From dade3365d6c2f121d18dda25d68b83a67723ae92 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 20 Aug 2018 11:13:24 -0700 Subject: [PATCH 16/77] Print version along with help when doing --build --- src/tsc/tsc.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index ff16a92f0fe..a2413d132bb 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -235,6 +235,7 @@ namespace ts { } if (buildOptions.help) { + printVersion(); printHelp(buildOpts, "--build "); return ExitStatus.Success; } From 0c4003e7351aa4d6f8e9285fc30905715485050d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 20 Aug 2018 11:47:39 -0700 Subject: [PATCH 17/77] Use SolutionBuilderHost instead of using compilerhost for solution builder --- src/compiler/program.ts | 5 +- src/compiler/tsbuild.ts | 73 +++++++++---------- src/compiler/types.ts | 4 - src/harness/fakes.ts | 2 +- src/testRunner/unittests/tsbuildWatchMode.ts | 8 +- src/tsc/tsc.ts | 7 +- .../reference/api/tsserverlibrary.d.ts | 3 - tests/baselines/reference/api/typescript.d.ts | 3 - 8 files changed, 47 insertions(+), 58 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 1c7430e3300..6ca29707cb9 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -189,10 +189,7 @@ namespace ts { getEnvironmentVariable: name => system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : "", getDirectories: (path: string) => system.getDirectories(path), realpath, - readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth), - getModifiedTime: system.getModifiedTime && (path => system.getModifiedTime!(path)), - setModifiedTime: system.setModifiedTime && ((path, date) => system.setModifiedTime!(path, date)), - deleteFile: system.deleteFile && (path => system.deleteFile!(path)) + readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth) }; } diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 54737d470e7..f0a81fe8b47 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -388,16 +388,27 @@ namespace ts { }; } + export interface SolutionBuilderHost extends CompilerHost { + getModifiedTime(fileName: string): Date | undefined; + setModifiedTime(fileName: string, date: Date): void; + deleteFile(fileName: string): void; + } + + export function createSolutionBuilderHost(system = sys) { + const host = createCompilerHost({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHost; + host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : () => undefined; + host.setModifiedTime = system.setModifiedTime ? (path, date) => system.setModifiedTime!(path, date) : noop; + host.deleteFile = system.deleteFile ? path => system.deleteFile!(path) : noop; + return host; + } + /** * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but * can dynamically add/remove other projects based on changes on the rootNames' references */ - export function createSolutionBuilder(compilerHost: CompilerHost, buildHost: BuildHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions, system?: System) { - if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) { - throw new Error("Host must support timestamp APIs"); - } + export function createSolutionBuilder(host: SolutionBuilderHost, buildHost: BuildHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions, system?: System) { - const configFileCache = createConfigFileCache(compilerHost); + const configFileCache = createConfigFileCache(host); let context = createBuildContext(defaultOptions); const existingWatchersForWildcards = createMap(); @@ -501,14 +512,14 @@ namespace ts { let newestInputFileTime = minimumDate; // Get timestamps of input files for (const inputFile of project.fileNames) { - if (!compilerHost.fileExists(inputFile)) { + if (!host.fileExists(inputFile)) { return { type: UpToDateStatusType.Unbuildable, reason: `${inputFile} does not exist` }; } - const inputTime = compilerHost.getModifiedTime!(inputFile) || missingFileModifiedTime; + const inputTime = host.getModifiedTime(inputFile) || missingFileModifiedTime; if (inputTime > newestInputFileTime) { newestInputFileName = inputFile; newestInputFileTime = inputTime; @@ -535,12 +546,12 @@ namespace ts { for (const output of outputs) { // Output is missing; can stop checking // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status - if (!compilerHost.fileExists(output)) { + if (!host.fileExists(output)) { missingOutputFileName = output; break; } - const outputTime = compilerHost.getModifiedTime!(output) || missingFileModifiedTime; + const outputTime = host.getModifiedTime(output) || missingFileModifiedTime; if (outputTime < oldestOutputFileTime) { oldestOutputFileTime = outputTime; oldestOutputFileName = output; @@ -568,7 +579,7 @@ namespace ts { newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime); } else { - const outputModifiedTime = compilerHost.getModifiedTime!(output) || missingFileModifiedTime; + const outputModifiedTime = host.getModifiedTime(output) || missingFileModifiedTime; newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime); } } @@ -580,7 +591,7 @@ namespace ts { if (project.projectReferences) { for (const ref of project.projectReferences) { usesPrepend = usesPrepend || !!(ref.prepend); - const resolvedRef = resolveProjectReferencePath(compilerHost, ref); + const resolvedRef = resolveProjectReferencePath(host, ref); const refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef)); // An upstream project is blocked @@ -809,7 +820,7 @@ namespace ts { const programOptions: CreateProgramOptions = { projectReferences: configFile.projectReferences, - host: compilerHost, + host, rootNames: configFile.fileNames, options: configFile.options }; @@ -858,18 +869,18 @@ namespace ts { program.emit(/*targetSourceFile*/ undefined, (fileName, content, writeBom, onError) => { let priorChangeTime: Date | undefined; - if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) { - if (compilerHost.readFile(fileName) === content) { + if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) { + if (host.readFile(fileName) === content) { // Check for unchanged .d.ts files resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged; - priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName); + priorChangeTime = host.getModifiedTime(fileName); } else { anyDtsChanged = true; } } - compilerHost.writeFile(fileName, content, writeBom, onError, emptyArray); + host.writeFile(fileName, content, writeBom, onError, emptyArray); if (priorChangeTime !== undefined) { newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime); context.unchangedOutputs.setValue(fileName, priorChangeTime); @@ -898,10 +909,10 @@ namespace ts { let priorNewestUpdateTime = minimumDate; for (const file of outputs) { if (isDeclarationFile(file)) { - priorNewestUpdateTime = newer(priorNewestUpdateTime, compilerHost.getModifiedTime!(file) || missingFileModifiedTime); + priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || missingFileModifiedTime); } - compilerHost.setModifiedTime!(file, now); + host.setModifiedTime(file, now); } context.projectStatus.setValue(proj.options.configFilePath!, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); @@ -924,7 +935,7 @@ namespace ts { } const outputs = getAllProjectOutputs(parsed); for (const output of outputs) { - if (compilerHost.fileExists(output)) { + if (host.fileExists(output)) { filesToDelete.push(output); } } @@ -958,25 +969,20 @@ namespace ts { return ExitStatus.Success; } - // Do this check later to allow --clean --dry to function even if the host can't delete files - if (!compilerHost.deleteFile) { - throw new Error("Host does not support deleting files"); - } - for (const output of filesToDelete) { - compilerHost.deleteFile(output); + host.deleteFile(output); } return ExitStatus.Success; } function resolveProjectName(name: string): ResolvedConfigFileName | undefined { - const fullPath = resolvePath(compilerHost.getCurrentDirectory(), name); - if (compilerHost.fileExists(fullPath)) { + const fullPath = resolvePath(host.getCurrentDirectory(), name); + if (host.fileExists(fullPath)) { return fullPath as ResolvedConfigFileName; } const fullPathWithTsconfig = combinePaths(fullPath, "tsconfig.json"); - if (compilerHost.fileExists(fullPathWithTsconfig)) { + if (host.fileExists(fullPathWithTsconfig)) { return fullPathWithTsconfig as ResolvedConfigFileName; } buildHost.error(Diagnostics.File_0_not_found, relName(fullPath)); @@ -1058,7 +1064,7 @@ namespace ts { } function relName(path: string): string { - return convertToRelativePath(path, compilerHost.getCurrentDirectory(), f => compilerHost.getCanonicalFileName(f)); + return convertToRelativePath(path, host.getCurrentDirectory(), f => host.getCanonicalFileName(f)); } function reportVerbose(message: DiagnosticMessage, ...args: string[]) { @@ -1074,15 +1080,6 @@ namespace ts { } } - export interface UpToDateHost { - fileExists(fileName: string): boolean; - getModifiedTime(fileName: string): Date | undefined; - getUnchangedTime?(fileName: string): Date | undefined; - getLastStatus?(fileName: string): UpToDateStatus | undefined; - setLastStatus?(fileName: string, status: UpToDateStatus): void; - parseConfigFile?(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined; - } - export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray { if (project.options.outFile) { return getOutFileOutputs(project); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 96129411db6..2733348e561 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4845,10 +4845,6 @@ namespace ts { /* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution; /* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean; createHash?(data: string): string; - - getModifiedTime?(fileName: string): Date | undefined; - setModifiedTime?(fileName: string, date: Date): void; - deleteFile?(fileName: string): void; } /* @internal */ diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index 1bb358698a2..b4dd97878be 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -205,7 +205,7 @@ namespace fakes { /** * A fake `ts.CompilerHost` that leverages a virtual file system. */ - export class CompilerHost implements ts.CompilerHost { + export class CompilerHost implements ts.CompilerHost, ts.SolutionBuilderHost { public readonly sys: System; public readonly defaultLibLocation: string; public readonly outputs: documents.TextDocument[] = []; diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 9f608180d03..dd6a95f0f12 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -1,8 +1,8 @@ namespace ts.tscWatch { export import libFile = TestFSWithWatch.libFile; - function createSolutionBuilder(host: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { - const compilerHost = createCompilerHost({}, /*setParentNodes*/ undefined, host); - const reportDiag = createDiagnosticReporter(host); + function createSolutionBuilder(system: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { + const host = createSolutionBuilderHost(system); + const reportDiag = createDiagnosticReporter(system); const report = (message: DiagnosticMessage, ...args: string[]) => reportDiag(createCompilerDiagnostic(message, ...args)); const buildHost: BuildHost = { error: report, @@ -10,7 +10,7 @@ namespace ts.tscWatch { message: report, errorDiagnostic: d => reportDiag(d) }; - return ts.createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions || { dry: false, force: false, verbose: false }, host); + return ts.createSolutionBuilder(host, buildHost, rootNames, defaultOptions || { dry: false, force: false, verbose: false }, system); } function createSolutionBuilderWithWatch(host: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index a2413d132bb..d53aa1f56ff 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -243,6 +243,11 @@ namespace ts { // Update to pretty if host supports it updateReportDiagnostic({}); + if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) { + reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build")); + return ExitStatus.DiagnosticsPresent_OutputsSkipped; + } + // Nonsensical combinations if (buildOptions.clean && buildOptions.force) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force")); @@ -274,7 +279,7 @@ namespace ts { errorDiagnostic: d => reportDiagnostic(d) }; - const builder = createSolutionBuilder(createCompilerHost({}), buildHost, projects, buildOptions); + const builder = createSolutionBuilder(createSolutionBuilderHost(), buildHost, projects, buildOptions); if (buildOptions.clean) { return builder.cleanAllProjects(); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index e41db162ae2..5c50a7cf457 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2690,9 +2690,6 @@ declare namespace ts { resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getEnvironmentVariable?(name: string): string | undefined; createHash?(data: string): string; - getModifiedTime?(fileName: string): Date | undefined; - setModifiedTime?(fileName: string, date: Date): void; - deleteFile?(fileName: string): void; } interface SourceMapRange extends TextRange { source?: SourceMapSource; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index fca9d26c306..29e485415fb 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2690,9 +2690,6 @@ declare namespace ts { resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getEnvironmentVariable?(name: string): string | undefined; createHash?(data: string): string; - getModifiedTime?(fileName: string): Date | undefined; - setModifiedTime?(fileName: string, date: Date): void; - deleteFile?(fileName: string): void; } interface SourceMapRange extends TextRange { source?: SourceMapSource; From 26b4b6c9ad87e616c38aeb7e6c1121daadc63f9c Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 20 Aug 2018 12:52:09 -0700 Subject: [PATCH 18/77] Create api with watchHost to include in solution builder host --- src/compiler/tsbuild.ts | 36 +++++++++---- src/compiler/watch.ts | 52 ++++++++++++------- src/testRunner/unittests/tsbuildWatchMode.ts | 4 +- src/tsc/tsc.ts | 6 ++- .../reference/api/tsserverlibrary.d.ts | 25 +++++---- tests/baselines/reference/api/typescript.d.ts | 25 +++++---- 6 files changed, 94 insertions(+), 54 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index f0a81fe8b47..e6bc8d252dd 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -394,6 +394,9 @@ namespace ts { deleteFile(fileName: string): void; } + export interface SolutionBuilderWithWatchHost extends SolutionBuilderHost, WatchHost { + } + export function createSolutionBuilderHost(system = sys) { const host = createCompilerHost({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHost; host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : () => undefined; @@ -402,12 +405,25 @@ namespace ts { return host; } + export function createSolutionBuilderWithWatchHost(system = sys, reportWatchStatus?: WatchStatusReporter) { + const host = createSolutionBuilderHost(system) as SolutionBuilderWithWatchHost; + const watchHost = createWatchHost(system, reportWatchStatus); + host.onWatchStatusChange = watchHost.onWatchStatusChange; + host.watchFile = watchHost.watchFile; + host.watchDirectory = watchHost.watchDirectory; + host.setTimeout = watchHost.setTimeout; + host.clearTimeout = watchHost.clearTimeout; + return host; + } + /** * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but * can dynamically add/remove other projects based on changes on the rootNames' references + * TODO: use SolutionBuilderWithWatchHost => watchedSolution + * use SolutionBuilderHost => Solution */ - export function createSolutionBuilder(host: SolutionBuilderHost, buildHost: BuildHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions, system?: System) { - + export function createSolutionBuilder(host: SolutionBuilderHost, buildHost: BuildHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions) { + const hostWithWatch = host as SolutionBuilderWithWatchHost; const configFileCache = createConfigFileCache(host); let context = createBuildContext(defaultOptions); @@ -430,9 +446,6 @@ namespace ts { }; function startWatching() { - if (!system) throw new Error("System host must be provided if using --watch"); - if (!system.watchFile || !system.watchDirectory || !system.setTimeout) throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch"); - const graph = getGlobalDependencyGraph()!; if (!graph.buildQueue) { // Everything is broken - we don't even know what to watch. Give up. @@ -443,7 +456,7 @@ namespace ts { const cfg = configFileCache.parseConfigFile(resolved); if (cfg) { // Watch this file - system.watchFile(resolved, () => { + hostWithWatch.watchFile(resolved, () => { configFileCache.removeKey(resolved); invalidateProjectAndScheduleBuilds(resolved); }); @@ -451,7 +464,7 @@ namespace ts { // Update watchers for wildcard directories if (cfg.configFileSpecs) { updateWatchingWildcardDirectories(existingWatchersForWildcards, createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), (dir, flags) => { - return system.watchDirectory!(dir, () => { + return hostWithWatch.watchDirectory(dir, () => { invalidateProjectAndScheduleBuilds(resolved); }, !!(flags & WatchDirectoryFlags.Recursive)); }); @@ -459,7 +472,7 @@ namespace ts { // Watch input files for (const input of cfg.fileNames) { - system.watchFile(input, () => { + hostWithWatch.watchFile(input, () => { invalidateProjectAndScheduleBuilds(resolved); }); } @@ -468,8 +481,11 @@ namespace ts { function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName) { invalidateProject(resolved); - system!.setTimeout!(buildInvalidatedProjects, 100); - system!.setTimeout!(buildDependentInvalidatedProjects, 3000); + if (!hostWithWatch.setTimeout) { + return; + } + hostWithWatch.setTimeout(buildInvalidatedProjects, 100); + hostWithWatch.setTimeout(buildDependentInvalidatedProjects, 3000); } } diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 9c759158f63..63904ffa43e 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -174,6 +174,17 @@ namespace ts { const noopFileWatcher: FileWatcher = { close: noop }; + export function createWatchHost(system = sys, reportWatchStatus?: WatchStatusReporter): WatchHost { + const onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system); + return { + onWatchStatusChange, + watchFile: system.watchFile ? ((path, callback, pollingInterval) => system.watchFile!(path, callback, pollingInterval)) : () => noopFileWatcher, + watchDirectory: system.watchDirectory ? ((path, callback, recursive) => system.watchDirectory!(path, callback, recursive)) : () => noopFileWatcher, + setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout!.call(system, callback, ms, ...args)) : noop, + clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout!(timeoutId)) : noop + }; + } + /** * Creates the watch compiler host that can be extended with config file or root file names and options host */ @@ -186,7 +197,7 @@ namespace ts { host; // tslint:disable-line no-unused-expression (TODO: `host` is unused!) const useCaseSensitiveFileNames = () => system.useCaseSensitiveFileNames; const writeFileName = (s: string) => system.write(s + system.newLine); - const onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system); + const { onWatchStatusChange, watchFile, watchDirectory, setTimeout, clearTimeout } = createWatchHost(system, reportWatchStatus); return { useCaseSensitiveFileNames, getNewLine: () => system.newLine, @@ -200,10 +211,10 @@ namespace ts { readDirectory: (path, extensions, exclude, include, depth) => system.readDirectory(path, extensions, exclude, include, depth), realpath: system.realpath && (path => system.realpath!(path)), getEnvironmentVariable: system.getEnvironmentVariable && (name => system.getEnvironmentVariable(name)), - watchFile: system.watchFile ? ((path, callback, pollingInterval) => system.watchFile!(path, callback, pollingInterval)) : () => noopFileWatcher, - watchDirectory: system.watchDirectory ? ((path, callback, recursive) => system.watchDirectory!(path, callback, recursive)) : () => noopFileWatcher, - setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout!.call(system, callback, ms, ...args)) : noop, - clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout!(timeoutId)) : noop, + watchFile, + watchDirectory, + setTimeout, + clearTimeout, trace: s => system.write(s), onWatchStatusChange, createDirectory: path => system.createDirectory(path), @@ -224,10 +235,10 @@ namespace ts { const reportSummary = (errorCount: number) => { if (errorCount === 1) { - onWatchStatusChange(createCompilerDiagnostic(Diagnostics.Found_1_error_Watching_for_file_changes, errorCount), newLine, compilerOptions); + onWatchStatusChange!(createCompilerDiagnostic(Diagnostics.Found_1_error_Watching_for_file_changes, errorCount), newLine, compilerOptions); } else { - onWatchStatusChange(createCompilerDiagnostic(Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount, errorCount), newLine, compilerOptions); + onWatchStatusChange!(createCompilerDiagnostic(Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount, errorCount), newLine, compilerOptions); } }; @@ -270,7 +281,21 @@ namespace ts { export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ export type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; - export interface WatchCompilerHost { + /** Host that has watch functionality used in --watch mode */ + export interface WatchHost { + /** If provided, called with Diagnostic message that informs about change in watch status */ + onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; + + /** Used to watch changes in source files, missing files needed to update the program or config file */ + watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; + /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ + watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; + /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ + setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; + /** If provided, will be used to reset existing delayed compilation */ + clearTimeout?(timeoutId: any): void; + } + export interface WatchCompilerHost extends WatchHost { // TODO: GH#18217 Optional methods are frequently asserted /** @@ -279,8 +304,6 @@ namespace ts { createProgram: CreateProgram; /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; - /** If provided, called with Diagnostic message that informs about change in watch status */ - onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; // Only for testing /*@internal*/ @@ -323,15 +346,6 @@ namespace ts { resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; - - /** Used to watch changes in source files, missing files needed to update the program or config file */ - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; - /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; - /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ - setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; - /** If provided, will be used to reset existing delayed compilation */ - clearTimeout?(timeoutId: any): void; } /** Internal interface used to wire emit through same host */ diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index dd6a95f0f12..87224c09338 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -1,7 +1,7 @@ namespace ts.tscWatch { export import libFile = TestFSWithWatch.libFile; function createSolutionBuilder(system: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { - const host = createSolutionBuilderHost(system); + const host = createSolutionBuilderWithWatchHost(system); const reportDiag = createDiagnosticReporter(system); const report = (message: DiagnosticMessage, ...args: string[]) => reportDiag(createCompilerDiagnostic(message, ...args)); const buildHost: BuildHost = { @@ -10,7 +10,7 @@ namespace ts.tscWatch { message: report, errorDiagnostic: d => reportDiag(d) }; - return ts.createSolutionBuilder(host, buildHost, rootNames, defaultOptions || { dry: false, force: false, verbose: false }, system); + return ts.createSolutionBuilder(host, buildHost, rootNames, defaultOptions || { dry: false, force: false, verbose: false, watch: true }); } function createSolutionBuilderWithWatch(host: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index d53aa1f56ff..5c7af1a4b99 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -247,6 +247,9 @@ namespace ts { reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build")); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } + if (buildOptions.watch) { + reportWatchModeWithoutSysSupport(); + } // Nonsensical combinations if (buildOptions.clean && buildOptions.force) { @@ -279,7 +282,8 @@ namespace ts { errorDiagnostic: d => reportDiagnostic(d) }; - const builder = createSolutionBuilder(createSolutionBuilderHost(), buildHost, projects, buildOptions); + // TODO: change this to host if watch => watchHost otherwiue without wathc + const builder = createSolutionBuilder(createSolutionBuilderWithWatchHost(), buildHost, projects, buildOptions); if (buildOptions.clean) { return builder.cleanAllProjects(); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5c50a7cf457..dd5f3c7c658 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4309,15 +4309,26 @@ declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; - interface WatchCompilerHost { + /** Host that has watch functionality used in --watch mode */ + interface WatchHost { + /** If provided, called with Diagnostic message that informs about change in watch status */ + onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; + /** Used to watch changes in source files, missing files needed to update the program or config file */ + watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; + /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ + watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; + /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ + setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; + /** If provided, will be used to reset existing delayed compilation */ + clearTimeout?(timeoutId: any): void; + } + interface WatchCompilerHost extends WatchHost { /** * Used to create the program when need for program creation or recreation detected */ createProgram: CreateProgram; /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; - /** If provided, called with Diagnostic message that informs about change in watch status */ - onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; useCaseSensitiveFileNames(): boolean; getNewLine(): string; getCurrentDirectory(): string; @@ -4350,14 +4361,6 @@ declare namespace ts { resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; - /** Used to watch changes in source files, missing files needed to update the program or config file */ - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; - /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; - /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ - setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; - /** If provided, will be used to reset existing delayed compilation */ - clearTimeout?(timeoutId: any): void; } /** * Host to create watch with root files and options diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 29e485415fb..2938fc9bcc8 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4309,15 +4309,26 @@ declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; - interface WatchCompilerHost { + /** Host that has watch functionality used in --watch mode */ + interface WatchHost { + /** If provided, called with Diagnostic message that informs about change in watch status */ + onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; + /** Used to watch changes in source files, missing files needed to update the program or config file */ + watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; + /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ + watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; + /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ + setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; + /** If provided, will be used to reset existing delayed compilation */ + clearTimeout?(timeoutId: any): void; + } + interface WatchCompilerHost extends WatchHost { /** * Used to create the program when need for program creation or recreation detected */ createProgram: CreateProgram; /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; - /** If provided, called with Diagnostic message that informs about change in watch status */ - onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; useCaseSensitiveFileNames(): boolean; getNewLine(): string; getCurrentDirectory(): string; @@ -4350,14 +4361,6 @@ declare namespace ts { resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; - /** Used to watch changes in source files, missing files needed to update the program or config file */ - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; - /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; - /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ - setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; - /** If provided, will be used to reset existing delayed compilation */ - clearTimeout?(timeoutId: any): void; } /** * Host to create watch with root files and options From dedb2aefc0b0b2b17b03b671ee89f28ab3403417 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 20 Aug 2018 13:33:54 -0700 Subject: [PATCH 19/77] Combine buildHost methods into SolutionBuilderHost's reportDiagnostic and reportStatus --- src/compiler/tsbuild.ts | 66 +++++---- src/harness/fakes.ts | 38 +++++- src/testRunner/unittests/tsbuild.ts | 134 +++++++------------ src/testRunner/unittests/tsbuildWatchMode.ts | 10 +- src/tsc/tsc.ts | 22 +-- 5 files changed, 132 insertions(+), 138 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index e6bc8d252dd..7efecab608a 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -392,21 +392,37 @@ namespace ts { getModifiedTime(fileName: string): Date | undefined; setModifiedTime(fileName: string, date: Date): void; deleteFile(fileName: string): void; + + reportDiagnostic: DiagnosticReporter; // Technically we want to move it out and allow steps of actions on Solution, but for now just merge stuff in build host here + reportSolutionBuilderStatus: DiagnosticReporter; } export interface SolutionBuilderWithWatchHost extends SolutionBuilderHost, WatchHost { } - export function createSolutionBuilderHost(system = sys) { + /** + * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic + */ + export function createBuilderStatusReporter(system: System, pretty?: boolean): DiagnosticReporter { + return diagnostic => { + let output = pretty ? `[${formatColorAndReset(new Date().toLocaleTimeString(), ForegroundColorEscapeSequences.Grey)}] ` : `${new Date().toLocaleTimeString()} - `; + output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${system.newLine + system.newLine}`; + system.write(output); + }; + } + + export function createSolutionBuilderHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) { const host = createCompilerHost({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHost; host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : () => undefined; host.setModifiedTime = system.setModifiedTime ? (path, date) => system.setModifiedTime!(path, date) : noop; host.deleteFile = system.deleteFile ? path => system.deleteFile!(path) : noop; + host.reportDiagnostic = reportDiagnostic || createDiagnosticReporter(system); + host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system); return host; } - export function createSolutionBuilderWithWatchHost(system = sys, reportWatchStatus?: WatchStatusReporter) { - const host = createSolutionBuilderHost(system) as SolutionBuilderWithWatchHost; + export function createSolutionBuilderWithWatchHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) { + const host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost; const watchHost = createWatchHost(system, reportWatchStatus); host.onWatchStatusChange = watchHost.onWatchStatusChange; host.watchFile = watchHost.watchFile; @@ -422,7 +438,7 @@ namespace ts { * TODO: use SolutionBuilderWithWatchHost => watchedSolution * use SolutionBuilderHost => Solution */ - export function createSolutionBuilder(host: SolutionBuilderHost, buildHost: BuildHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions) { + export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions) { const hostWithWatch = host as SolutionBuilderWithWatchHost; const configFileCache = createConfigFileCache(host); let context = createBuildContext(defaultOptions); @@ -445,6 +461,10 @@ namespace ts { startWatching }; + function reportStatus(message: DiagnosticMessage, ...args: string[]) { + host.reportSolutionBuilderStatus(createCompilerDiagnostic(message, ...args)); + } + function startWatching() { const graph = getGlobalDependencyGraph()!; if (!graph.buildQueue) { @@ -743,7 +763,7 @@ namespace ts { verboseReportProjectStatus(next, status); if (status.type === UpToDateStatusType.UpstreamBlocked) { - if (context.options.verbose) buildHost.verbose(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); + if (context.options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); continue; } @@ -780,7 +800,7 @@ namespace ts { if (temporaryMarks[projPath]) { if (!inCircularContext) { hadError = true; - buildHost.error(Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n")); + reportStatus(Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n")); return; } } @@ -812,11 +832,11 @@ namespace ts { function buildSingleProject(proj: ResolvedConfigFileName): BuildResultFlags { if (context.options.dry) { - buildHost.message(Diagnostics.A_non_dry_build_would_build_project_0, proj); + reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj); return BuildResultFlags.Success; } - if (context.options.verbose) buildHost.verbose(Diagnostics.Building_project_0, proj); + if (context.options.verbose) reportStatus(Diagnostics.Building_project_0, proj); let resultFlags = BuildResultFlags.None; resultFlags |= BuildResultFlags.DeclarationOutputUnchanged; @@ -850,7 +870,7 @@ namespace ts { if (syntaxDiagnostics.length) { resultFlags |= BuildResultFlags.SyntaxErrors; for (const diag of syntaxDiagnostics) { - buildHost.errorDiagnostic(diag); + host.reportDiagnostic(diag); } context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); return resultFlags; @@ -862,7 +882,7 @@ namespace ts { if (declDiagnostics.length) { resultFlags |= BuildResultFlags.DeclarationEmitErrors; for (const diag of declDiagnostics) { - buildHost.errorDiagnostic(diag); + host.reportDiagnostic(diag); } context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" }); return resultFlags; @@ -874,7 +894,7 @@ namespace ts { if (semanticDiagnostics.length) { resultFlags |= BuildResultFlags.TypeErrors; for (const diag of semanticDiagnostics) { - buildHost.errorDiagnostic(diag); + host.reportDiagnostic(diag); } context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" }); return resultFlags; @@ -913,11 +933,11 @@ namespace ts { function updateOutputTimestamps(proj: ParsedCommandLine) { if (context.options.dry) { - return buildHost.message(Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath!); + return reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath!); } if (context.options.verbose) { - buildHost.verbose(Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath!); + reportStatus(Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath!); } const now = new Date(); @@ -970,18 +990,18 @@ namespace ts { function cleanAllProjects() { const resolvedNames: ReadonlyArray | undefined = getAllProjectsInScope(); if (resolvedNames === undefined) { - buildHost.message(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); + reportStatus(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } const filesToDelete = getFilesToClean(resolvedNames); if (filesToDelete === undefined) { - buildHost.message(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); + reportStatus(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); return ExitStatus.DiagnosticsPresent_OutputsSkipped; } if (context.options.dry) { - buildHost.message(Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(f => `\r\n * ${f}`).join("")); + reportStatus(Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(f => `\r\n * ${f}`).join("")); return ExitStatus.Success; } @@ -1001,7 +1021,7 @@ namespace ts { if (host.fileExists(fullPathWithTsconfig)) { return fullPathWithTsconfig as ResolvedConfigFileName; } - buildHost.error(Diagnostics.File_0_not_found, relName(fullPath)); + host.reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_not_found, relName(fullPath))); return undefined; } @@ -1039,7 +1059,7 @@ namespace ts { // Up to date, skip if (defaultOptions.dry) { // In a dry build, inform the user of this fact - buildHost.message(Diagnostics.Project_0_is_up_to_date, projName); + reportStatus(Diagnostics.Project_0_is_up_to_date, projName); } continue; } @@ -1051,7 +1071,7 @@ namespace ts { } if (status.type === UpToDateStatusType.UpstreamBlocked) { - if (context.options.verbose) buildHost.verbose(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName); + if (context.options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName); continue; } @@ -1076,23 +1096,19 @@ namespace ts { for (const name of graph.buildQueue) { names.push(name); } - if (context.options.verbose) buildHost.verbose(Diagnostics.Projects_in_this_build_Colon_0, names.map(s => "\r\n * " + relName(s)).join("")); + if (context.options.verbose) reportStatus(Diagnostics.Projects_in_this_build_Colon_0, names.map(s => "\r\n * " + relName(s)).join("")); } function relName(path: string): string { return convertToRelativePath(path, host.getCurrentDirectory(), f => host.getCanonicalFileName(f)); } - function reportVerbose(message: DiagnosticMessage, ...args: string[]) { - buildHost.verbose(message, ...args); - } - /** * Report the up-to-date status of a project if we're in verbose mode */ function verboseReportProjectStatus(configFileName: string, status: UpToDateStatus) { if (!context.options.verbose) return; - return formatUpToDateStatus(configFileName, status, relName, reportVerbose); + return formatUpToDateStatus(configFileName, status, relName, reportStatus); } } diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index b4dd97878be..bd9d62f90e5 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -205,7 +205,7 @@ namespace fakes { /** * A fake `ts.CompilerHost` that leverages a virtual file system. */ - export class CompilerHost implements ts.CompilerHost, ts.SolutionBuilderHost { + export class CompilerHost implements ts.CompilerHost { public readonly sys: System; public readonly defaultLibLocation: string; public readonly outputs: documents.TextDocument[] = []; @@ -374,5 +374,41 @@ namespace fakes { return parsed; } } + + export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost { + diagnostics: ts.Diagnostic[] = []; + + reportDiagnostic(diagnostic: ts.Diagnostic) { + this.diagnostics.push(diagnostic); + } + + reportSolutionBuilderStatus(diagnostic: ts.Diagnostic) { + this.diagnostics.push(diagnostic); + } + + clearDiagnostics() { + this.diagnostics.length = 0; + } + + assertDiagnosticMessages(...expected: ts.DiagnosticMessage[]) { + const actual = this.diagnostics.slice(); + if (actual.length !== expected.length) { + assert.fail(actual, expected, `Diagnostic arrays did not match - got\r\n${actual.map(a => " " + a.messageText).join("\r\n")}\r\nexpected\r\n${expected.map(e => " " + e.message).join("\r\n")}`); + } + for (let i = 0; i < actual.length; i++) { + if (actual[i].code !== expected[i].code) { + assert.fail(actual[i].messageText, expected[i].message, `Mismatched error code - expected diagnostic ${i} "${actual[i].messageText}" to match ${expected[i].message}`); + } + } + } + + printDiagnostics(header = "== Diagnostics ==") { + const out = ts.createDiagnosticReporter(ts.sys); + ts.sys.write(header + "\r\n"); + for (const d of this.diagnostics) { + out(d); + } + } + } } diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index b65220588c5..f8813ecd1ae 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -1,15 +1,5 @@ namespace ts { let currentTime = 100; - let lastDiagnostics: Diagnostic[] = []; - const reportDiagnostic: DiagnosticReporter = diagnostic => lastDiagnostics.push(diagnostic); - const report = (message: DiagnosticMessage, ...args: string[]) => reportDiagnostic(createCompilerDiagnostic(message, ...args)); - const buildHost: BuildHost = { - error: report, - verbose: report, - message: report, - errorDiagnostic: d => reportDiagnostic(d) - }; - export namespace Sample1 { tick(); const projFs = loadProjectFromDisk("tests/projects/sample1"); @@ -21,12 +11,12 @@ namespace ts { describe("tsbuild - sanity check of clean build of 'sample1' project", () => { it("can build the sample project 'sample1' without error", () => { const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false }); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false }); - clearDiagnostics(); + host.clearDiagnostics(); builder.buildAllProjects(); - assertDiagnosticMessages(/*empty*/); + host.assertDiagnosticMessages(/*empty*/); // Check for outputs. Not an exhaustive list for (const output of allExpectedOutputs) { @@ -37,12 +27,11 @@ namespace ts { describe("tsbuild - dry builds", () => { it("doesn't write any files in a dry build", () => { - clearDiagnostics(); const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: true, force: false, verbose: false }); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/tests"], { dry: true, force: false, verbose: false }); builder.buildAllProjects(); - assertDiagnosticMessages(Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0); + host.assertDiagnosticMessages(Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0); // Check for outputs to not be written. Not an exhaustive list for (const output of allExpectedOutputs) { @@ -51,28 +40,26 @@ namespace ts { }); it("indicates that it would skip builds during a dry build", () => { - clearDiagnostics(); const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); + const host = new fakes.SolutionBuilderHost(fs); - let builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false }); + let builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false }); builder.buildAllProjects(); tick(); - clearDiagnostics(); - builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: true, force: false, verbose: false }); + host.clearDiagnostics(); + builder = createSolutionBuilder(host, ["/src/tests"], { dry: true, force: false, verbose: false }); builder.buildAllProjects(); - assertDiagnosticMessages(Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date); + host.assertDiagnosticMessages(Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date); }); }); describe("tsbuild - clean builds", () => { it("removes all files it built", () => { - clearDiagnostics(); const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); + const host = new fakes.SolutionBuilderHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false }); + const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false }); builder.buildAllProjects(); // Verify they exist for (const output of allExpectedOutputs) { @@ -91,9 +78,9 @@ namespace ts { describe("tsbuild - force builds", () => { it("always builds under --force", () => { const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); + const host = new fakes.SolutionBuilderHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: true, verbose: false }); + const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: true, verbose: false }); builder.buildAllProjects(); let currentTime = time(); checkOutputTimestamps(currentTime); @@ -116,14 +103,14 @@ namespace ts { describe("tsbuild - can detect when and what to rebuild", () => { const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: true }); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: true }); it("Builds the project", () => { - clearDiagnostics(); + host.clearDiagnostics(); builder.resetBuildContext(); builder.buildAllProjects(); - assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, + host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, Diagnostics.Building_project_0, Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, @@ -135,10 +122,10 @@ namespace ts { // All three projects are up to date it("Detects that all projects are up to date", () => { - clearDiagnostics(); + host.clearDiagnostics(); builder.resetBuildContext(); builder.buildAllProjects(); - assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, + host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2); @@ -147,12 +134,12 @@ namespace ts { // Update a file in the leaf node (tests), only it should rebuild the last one it("Only builds the leaf node project", () => { - clearDiagnostics(); + host.clearDiagnostics(); fs.writeFileSync("/src/tests/index.ts", "const m = 10;"); builder.resetBuildContext(); builder.buildAllProjects(); - assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, + host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, @@ -162,12 +149,12 @@ namespace ts { // Update a file in the parent (without affecting types), should get fast downstream builds it("Detects type-only changes in upstream projects", () => { - clearDiagnostics(); + host.clearDiagnostics(); replaceText(fs, "/src/core/index.ts", "HELLO WORLD", "WELCOME PLANET"); builder.resetBuildContext(); builder.buildAllProjects(); - assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, + host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0, Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, Diagnostics.Building_project_0, Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, @@ -180,15 +167,13 @@ namespace ts { describe("tsbuild - downstream-blocked compilations", () => { it("won't build downstream projects if upstream projects have errors", () => { const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: true }); - - clearDiagnostics(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: true }); // Induce an error in the middle project replaceText(fs, "/src/logic/index.ts", "c.multiply(10, 15)", `c.muitply()`); builder.buildAllProjects(); - assertDiagnosticMessages( + host.assertDiagnosticMessages( Diagnostics.Projects_in_this_build_Colon_0, Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, Diagnostics.Building_project_0, @@ -204,12 +189,11 @@ namespace ts { describe("tsbuild - project invalidation", () => { it("invalidates projects correctly", () => { const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false }); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false }); - clearDiagnostics(); builder.buildAllProjects(); - assertDiagnosticMessages(/*empty*/); + host.assertDiagnosticMessages(/*empty*/); // Update a timestamp in the middle project tick(); @@ -240,11 +224,10 @@ namespace ts { function verifyProjectWithResolveJsonModule(configFile: string, ...expectedDiagnosticMessages: DiagnosticMessage[]) { const fs = projFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, [configFile], { dry: false, force: false, verbose: false }); - clearDiagnostics(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, [configFile], { dry: false, force: false, verbose: false }); builder.buildAllProjects(); - assertDiagnosticMessages(...expectedDiagnosticMessages); + host.assertDiagnosticMessages(...expectedDiagnosticMessages); if (!expectedDiagnosticMessages.length) { // Check for outputs. Not an exhaustive list for (const output of allExpectedOutputs) { @@ -274,11 +257,11 @@ namespace ts { let fs: vfs.FileSystem | undefined; before(() => { fs = outFileFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/third"], { dry: false, force: false, verbose: false }); - clearDiagnostics(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: false }); + host.clearDiagnostics(); builder.buildAllProjects(); - assertDiagnosticMessages(/*none*/); + host.assertDiagnosticMessages(/*none*/); }); after(() => { fs = undefined; @@ -293,25 +276,24 @@ namespace ts { describe("tsbuild - downstream prepend projects always get rebuilt", () => { it("", () => { const fs = outFileFs.shadow(); - const host = new fakes.CompilerHost(fs); - const builder = createSolutionBuilder(host, buildHost, ["/src/third"], { dry: false, force: false, verbose: false }); - clearDiagnostics(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: false }); builder.buildAllProjects(); - assertDiagnosticMessages(/*none*/); + host.assertDiagnosticMessages(/*none*/); assert.equal(fs.statSync("src/third/thirdjs/output/third-output.js").mtimeMs, time(), "First build timestamp is correct"); tick(); replaceText(fs, "src/first/first_PART1.ts", "Hello", "Hola"); tick(); builder.resetBuildContext(); builder.buildAllProjects(); - assertDiagnosticMessages(/*none*/); + host.assertDiagnosticMessages(/*none*/); assert.equal(fs.statSync("src/third/thirdjs/output/third-output.js").mtimeMs, time(), "Second build timestamp is correct"); }); }); } describe("tsbuild - graph-ordering", () => { - let host: fakes.CompilerHost | undefined; + let host: fakes.SolutionBuilderHost | undefined; const deps: [string, string][] = [ ["A", "B"], ["B", "C"], @@ -324,7 +306,7 @@ namespace ts { before(() => { const fs = new vfs.FileSystem(false); - host = new fakes.CompilerHost(fs); + host = new fakes.SolutionBuilderHost(fs); writeProjects(fs, ["A", "B", "C", "D", "E", "F", "G"], deps); }); @@ -349,7 +331,7 @@ namespace ts { }); function checkGraphOrdering(rootNames: string[], expectedBuildSet: string[]) { - const builder = createSolutionBuilder(host!, buildHost, rootNames, { dry: true, force: false, verbose: false }); + const builder = createSolutionBuilder(host!, rootNames, { dry: true, force: false, verbose: false }); const projFileNames = rootNames.map(getProjectFileName); const graph = builder.getBuildGraph(projFileNames); @@ -404,30 +386,6 @@ namespace ts { fs.writeFileSync(path, newContent, "utf-8"); } - function assertDiagnosticMessages(...expected: DiagnosticMessage[]) { - const actual = lastDiagnostics.slice(); - if (actual.length !== expected.length) { - assert.fail(actual, expected, `Diagnostic arrays did not match - got\r\n${actual.map(a => " " + a.messageText).join("\r\n")}\r\nexpected\r\n${expected.map(e => " " + e.message).join("\r\n")}`); - } - for (let i = 0; i < actual.length; i++) { - if (actual[i].code !== expected[i].code) { - assert.fail(actual[i].messageText, expected[i].message, `Mismatched error code - expected diagnostic ${i} "${actual[i].messageText}" to match ${expected[i].message}`); - } - } - } - - function clearDiagnostics() { - lastDiagnostics = []; - } - - export function printDiagnostics(header = "== Diagnostics ==") { - const out = createDiagnosticReporter(sys); - sys.write(header + "\r\n"); - for (const d of lastDiagnostics) { - out(d); - } - } - function tick() { currentTime += 60_000; } diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 87224c09338..d43a24a0b9c 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -2,15 +2,7 @@ namespace ts.tscWatch { export import libFile = TestFSWithWatch.libFile; function createSolutionBuilder(system: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { const host = createSolutionBuilderWithWatchHost(system); - const reportDiag = createDiagnosticReporter(system); - const report = (message: DiagnosticMessage, ...args: string[]) => reportDiag(createCompilerDiagnostic(message, ...args)); - const buildHost: BuildHost = { - error: report, - verbose: report, - message: report, - errorDiagnostic: d => reportDiag(d) - }; - return ts.createSolutionBuilder(host, buildHost, rootNames, defaultOptions || { dry: false, force: false, verbose: false, watch: true }); + return ts.createSolutionBuilder(host, rootNames, defaultOptions || { dry: false, force: false, verbose: false, watch: true }); } function createSolutionBuilderWithWatch(host: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index 5c7af1a4b99..5be8660187b 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -13,7 +13,7 @@ namespace ts { } let reportDiagnostic = createDiagnosticReporter(sys); - function updateReportDiagnostic(options: CompilerOptions) { + function updateReportDiagnostic(options?: CompilerOptions) { if (shouldBePretty(options)) { reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true); } @@ -23,8 +23,8 @@ namespace ts { return !!sys.writeOutputIsTTY && sys.writeOutputIsTTY(); } - function shouldBePretty(options: CompilerOptions) { - if (typeof options.pretty === "undefined") { + function shouldBePretty(options?: CompilerOptions) { + if (!options || typeof options.pretty === "undefined") { return defaultIsPretty(); } return options.pretty; @@ -241,7 +241,7 @@ namespace ts { } // Update to pretty if host supports it - updateReportDiagnostic({}); + updateReportDiagnostic(); if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build")); @@ -274,16 +274,8 @@ namespace ts { addProject("."); } - const report = (message: DiagnosticMessage, ...args: string[]) => reportDiagnostic(createCompilerDiagnostic(message, ...args)); - const buildHost: BuildHost = { - error: report, - verbose: report, - message: report, - errorDiagnostic: d => reportDiagnostic(d) - }; - // TODO: change this to host if watch => watchHost otherwiue without wathc - const builder = createSolutionBuilder(createSolutionBuilderWithWatchHost(), buildHost, projects, buildOptions); + const builder = createSolutionBuilder(createSolutionBuilderWithWatchHost(sys, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createWatchStatusReporter()), projects, buildOptions); if (buildOptions.clean) { return builder.cleanAllProjects(); } @@ -300,7 +292,7 @@ namespace ts { const fileName = resolvePath(sys.getCurrentDirectory(), projectSpecification); const refPath = resolveProjectReferencePath(sys, { path: fileName }); if (!sys.fileExists(refPath)) { - return buildHost.error(Diagnostics.File_0_does_not_exist, fileName); + return reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_does_not_exist, fileName)); } projects.push(refPath); } @@ -339,7 +331,7 @@ namespace ts { }; } - function createWatchStatusReporter(options: CompilerOptions) { + function createWatchStatusReporter(options?: CompilerOptions) { return ts.createWatchStatusReporter(sys, shouldBePretty(options)); } From 7960090bb68bda21857c8759cec637dd3fbedd36 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 20 Aug 2018 14:22:58 -0700 Subject: [PATCH 20/77] Add preserveWatchOutput option to build option and report starting compilation and file changes detected status --- src/compiler/tsbuild.ts | 9 +++++++++ src/tsc/tsc.ts | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 7efecab608a..2d66ddfe75d 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -54,6 +54,7 @@ namespace ts { /*@internal*/ clean?: boolean; /*@internal*/ watch?: boolean; /*@internal*/ help?: boolean; + preserveWatchOutput?: boolean; } enum BuildResultFlags { @@ -465,6 +466,12 @@ namespace ts { host.reportSolutionBuilderStatus(createCompilerDiagnostic(message, ...args)); } + function reportWatchStatus(message: DiagnosticMessage, ...args: string[]) { + if (hostWithWatch.onWatchStatusChange) { + hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput }); + } + } + function startWatching() { const graph = getGlobalDependencyGraph()!; if (!graph.buildQueue) { @@ -500,6 +507,7 @@ namespace ts { } function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName) { + reportWatchStatus(Diagnostics.File_change_detected_Starting_incremental_compilation); invalidateProject(resolved); if (!hostWithWatch.setTimeout) { return; @@ -1038,6 +1046,7 @@ namespace ts { } function buildAllProjects(): ExitStatus { + if (context.options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); } const graph = getGlobalDependencyGraph(); if (graph === undefined) return ExitStatus.DiagnosticsPresent_OutputsSkipped; diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index 5be8660187b..1685dfc3449 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -211,7 +211,13 @@ namespace ts { category: Diagnostics.Command_line_Options, description: Diagnostics.Watch_input_files, type: "boolean" - } + }, + { + name: "preserveWatchOutput", + type: "boolean", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen, + }, ]; let buildOptionNameMap: OptionNameMap | undefined; const returnBuildOptionNameMap = () => (buildOptionNameMap || (buildOptionNameMap = createOptionNameMap(buildOpts))); From 0831edab3648dc0f8e2ecb9a7dd30d868d8de27b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 20 Aug 2018 16:06:13 -0700 Subject: [PATCH 21/77] Keep only errors starting on new screen --- src/compiler/watch.ts | 8 +------- src/testRunner/unittests/tscWatchMode.ts | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 63904ffa43e..c091ad5c30c 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -27,12 +27,6 @@ namespace ts { }; } - /** @internal */ - export const nonClearingMessageCodes: number[] = [ - Diagnostics.Found_1_error_Watching_for_file_changes.code, - Diagnostics.Found_0_errors_Watching_for_file_changes.code - ]; - /** * @returns Whether the screen was cleared. */ @@ -41,7 +35,7 @@ namespace ts { !options.preserveWatchOutput && !options.extendedDiagnostics && !options.diagnostics && - !contains(nonClearingMessageCodes, diagnostic.code)) { + contains(screenStartingMessageCodes, diagnostic.code)) { system.clearScreen(); return true; } diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index 51c0d888f0b..c881e9c14da 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -110,7 +110,7 @@ namespace ts.tscWatch { function assertWatchDiagnostic(diagnostic: Diagnostic) { const expected = getWatchDiagnosticWithoutDate(diagnostic); - if (!disableConsoleClears && !contains(nonClearingMessageCodes, diagnostic.code)) { + if (!disableConsoleClears && contains(screenStartingMessageCodes, diagnostic.code)) { assert.equal(host.screenClears[screenClears], index, `Expected screen clear at this diagnostic: ${expected}`); screenClears++; } From 4193846108b7bb7e7caadf7a9e62b487714c60e9 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 21 Aug 2018 13:52:04 -0700 Subject: [PATCH 22/77] Do not expose change in createCompilerHost --- src/compiler/program.ts | 7 ++++++- src/compiler/tsbuild.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 6ca29707cb9..08bb4727781 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -66,7 +66,12 @@ namespace ts { mtime: Date; } - export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost { + export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { + return createCompilerHostWorker(options, setParentNodes); + } + /*@internal*/ + // TODO(shkamat): update this after reworking ts build API + export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost { const existingDirectories = createMap(); function getCanonicalFileName(fileName: string): string { diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 2d66ddfe75d..22b2237d1ae 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -413,7 +413,7 @@ namespace ts { } export function createSolutionBuilderHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) { - const host = createCompilerHost({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHost; + const host = createCompilerHostWorker({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHost; host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : () => undefined; host.setModifiedTime = system.setModifiedTime ? (path, date) => system.setModifiedTime!(path, date) : noop; host.deleteFile = system.deleteFile ? path => system.deleteFile!(path) : noop; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index dd5f3c7c658..3b7764cfd74 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4122,7 +4122,7 @@ declare namespace ts { declare namespace ts { function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined; function resolveTripleslashReference(moduleName: string, containingFile: string): string; - function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system?: System): CompilerHost; + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; interface FormatDiagnosticsHost { getCurrentDirectory(): string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2938fc9bcc8..e92e3d6e1d5 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4122,7 +4122,7 @@ declare namespace ts { declare namespace ts { function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined; function resolveTripleslashReference(moduleName: string, containingFile: string): string; - function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system?: System): CompilerHost; + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; interface FormatDiagnosticsHost { getCurrentDirectory(): string; From 7740822d02d8072f6360090ab10a953775fbe1a3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 21 Aug 2018 15:45:29 -0700 Subject: [PATCH 23/77] Simplify or get constraint in distributive conditional type, but not both --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d2b0187eb0..8f043d51cda 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6921,7 +6921,8 @@ namespace ts { // over the conditional type and possibly reduced. For example, 'T extends undefined ? never : T' // removes 'undefined' from T. if (type.root.isDistributive) { - const constraint = getConstraintOfType(getSimplifiedType(type.checkType)); + const simplified = getSimplifiedType(type.checkType); + const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified; if (constraint) { const mapper = makeUnaryTypeMapper(type.root.checkType, constraint); const instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper)); From db9c202b64d8a26bd5aee42d24dd39693aab2a43 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 21 Aug 2018 16:17:14 -0700 Subject: [PATCH 24/77] Add regression test --- tests/cases/compiler/infiniteConstraints.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/cases/compiler/infiniteConstraints.ts b/tests/cases/compiler/infiniteConstraints.ts index 70d3879da6b..e914b738efc 100644 --- a/tests/cases/compiler/infiniteConstraints.ts +++ b/tests/cases/compiler/infiniteConstraints.ts @@ -31,3 +31,8 @@ const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2 const shouldBeNoError = ensureNoDuplicates({main: value("test")}); const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); + +// Repro from #26448 + +type Cond = T extends number ? number : never; +declare function function1}>(): T[keyof T]["foo"]; From 2f85af83a7b689468fc8a0fc4ac66d6a7df4323a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 21 Aug 2018 16:17:21 -0700 Subject: [PATCH 25/77] Accept new baselines --- .../reference/infiniteConstraints.errors.txt | 10 +++++++++- .../baselines/reference/infiniteConstraints.js | 5 +++++ .../reference/infiniteConstraints.symbols | 18 ++++++++++++++++++ .../reference/infiniteConstraints.types | 8 ++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/infiniteConstraints.errors.txt b/tests/baselines/reference/infiniteConstraints.errors.txt index 108c3693783..387b0daac68 100644 --- a/tests/baselines/reference/infiniteConstraints.errors.txt +++ b/tests/baselines/reference/infiniteConstraints.errors.txt @@ -2,9 +2,10 @@ tests/cases/compiler/infiniteConstraints.ts(4,37): error TS2536: Type '"val"' ca tests/cases/compiler/infiniteConstraints.ts(31,42): error TS2345: Argument of type '{ main: Record<"val", "dup">; alternate: Record<"val", "dup">; }' is not assignable to parameter of type '{ main: never; alternate: never; }'. Types of property 'main' are incompatible. Type 'Record<"val", "dup">' is not assignable to type 'never'. +tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2536: Type '"foo"' cannot be used to index type 'T[keyof T]'. -==== tests/cases/compiler/infiniteConstraints.ts (2 errors) ==== +==== tests/cases/compiler/infiniteConstraints.ts (3 errors) ==== // Both of the following types trigger the recursion limiter in getImmediateBaseConstraint type T1], { val: string }>["val"] }> = B; @@ -42,4 +43,11 @@ tests/cases/compiler/infiniteConstraints.ts(31,42): error TS2345: Argument of ty !!! error TS2345: Argument of type '{ main: Record<"val", "dup">; alternate: Record<"val", "dup">; }' is not assignable to parameter of type '{ main: never; alternate: never; }'. !!! error TS2345: Types of property 'main' are incompatible. !!! error TS2345: Type 'Record<"val", "dup">' is not assignable to type 'never'. + + // Repro from #26448 + + type Cond = T extends number ? number : never; + declare function function1}>(): T[keyof T]["foo"]; + ~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type '"foo"' cannot be used to index type 'T[keyof T]'. \ No newline at end of file diff --git a/tests/baselines/reference/infiniteConstraints.js b/tests/baselines/reference/infiniteConstraints.js index 0ad3b676f14..03a4d70e00c 100644 --- a/tests/baselines/reference/infiniteConstraints.js +++ b/tests/baselines/reference/infiniteConstraints.js @@ -30,6 +30,11 @@ const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2 const shouldBeNoError = ensureNoDuplicates({main: value("test")}); const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); + +// Repro from #26448 + +type Cond = T extends number ? number : never; +declare function function1}>(): T[keyof T]["foo"]; //// [infiniteConstraints.js] diff --git a/tests/baselines/reference/infiniteConstraints.symbols b/tests/baselines/reference/infiniteConstraints.symbols index 0f0d44c9f53..6306203a7e0 100644 --- a/tests/baselines/reference/infiniteConstraints.symbols +++ b/tests/baselines/reference/infiniteConstraints.symbols @@ -120,3 +120,21 @@ const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value(" >alternate : Symbol(alternate, Decl(infiniteConstraints.ts, 30, 61)) >value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) +// Repro from #26448 + +type Cond = T extends number ? number : never; +>Cond : Symbol(Cond, Decl(infiniteConstraints.ts, 30, 88)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 34, 10)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 34, 10)) + +declare function function1}>(): T[keyof T]["foo"]; +>function1 : Symbol(function1, Decl(infiniteConstraints.ts, 34, 49)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 35, 27)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 35, 39)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 35, 27)) +>Cond : Symbol(Cond, Decl(infiniteConstraints.ts, 30, 88)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 35, 27)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 35, 39)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 35, 27)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 35, 27)) + diff --git a/tests/baselines/reference/infiniteConstraints.types b/tests/baselines/reference/infiniteConstraints.types index 78fbc9becaa..e23e138c820 100644 --- a/tests/baselines/reference/infiniteConstraints.types +++ b/tests/baselines/reference/infiniteConstraints.types @@ -87,3 +87,11 @@ const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value(" >value : (val: V) => Record<"val", V> >"dup" : "dup" +// Repro from #26448 + +type Cond = T extends number ? number : never; +>Cond : Cond + +declare function function1}>(): T[keyof T]["foo"]; +>function1 : ; }>() => T[keyof T]["foo"] + From cec1b0a7179983eb880e806120ae25ac207029a9 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 21 Aug 2018 16:25:57 -0700 Subject: [PATCH 26/77] Report error summary from the queue. --- src/compiler/program.ts | 2 +- src/compiler/tsbuild.ts | 166 ++++++++++++++----- src/testRunner/unittests/tsbuild.ts | 4 +- src/testRunner/unittests/tsbuildWatchMode.ts | 80 ++++++++- src/testRunner/unittests/tscWatchMode.ts | 4 +- 5 files changed, 206 insertions(+), 50 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 08bb4727781..d1168046b8b 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -175,7 +175,7 @@ namespace ts { return getDirectoryPath(normalizePath(system.getExecutingFilePath())); } - const newLine = getNewLineCharacter(options); + const newLine = getNewLineCharacter(options, () => system.newLine); const realpath = system.realpath && ((path: string) => system.realpath!(path)); return { diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 22b2237d1ae..5fdab168951 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -35,9 +35,11 @@ namespace ts { * Map from config file name to up-to-date status */ projectStatus: FileMap; + diagnostics?: FileMap; // TODO(shkamat): this should be really be diagnostics but thats for later time - invalidatedProjects: FileMap; - queuedProjects: FileMap; + invalidateProject(project: ResolvedConfigFileName, dependencyGraph: DependencyGraph | undefined): void; + getNextInvalidatedProject(): ResolvedConfigFileName | undefined; + pendingInvalidatedProjects(): boolean; missingRoots: Map; } @@ -194,6 +196,7 @@ namespace ts { hasKey(fileName: string): boolean; removeKey(fileName: string): void; getKeys(): string[]; + getSize(): number; } /** @@ -209,7 +212,8 @@ namespace ts { getValueOrUndefined, removeKey, getKeys, - hasKey + hasKey, + getSize }; function getKeys(): string[] { @@ -242,6 +246,10 @@ namespace ts { const f = normalizePath(fileName); return lookup.get(f); } + + function getSize() { + return lookup.size; + } } function createDependencyMapper() { @@ -375,18 +383,64 @@ namespace ts { } export function createBuildContext(options: BuildOptions): BuildContext { - const invalidatedProjects = createFileMap(); - const queuedProjects = createFileMap(); + const invalidatedProjectQueue = [] as ResolvedConfigFileName[]; + let nextIndex = 0; + const projectPendingBuild = createFileMap(); const missingRoots = createMap(); + const diagnostics = options.watch ? createFileMap() : undefined; return { options, projectStatus: createFileMap(), + diagnostics, unchangedOutputs: createFileMap(), - invalidatedProjects, - missingRoots, - queuedProjects + invalidateProject, + getNextInvalidatedProject, + pendingInvalidatedProjects, + missingRoots }; + + function invalidateProject(proj: ResolvedConfigFileName, dependancyGraph: DependencyGraph | undefined) { + if (!projectPendingBuild.hasKey(proj)) { + addProjToQueue(proj); + if (dependancyGraph) { + queueBuildForDownstreamReferences(proj, dependancyGraph); + } + } + } + + function addProjToQueue(proj: ResolvedConfigFileName) { + projectPendingBuild.setValue(proj, true); + invalidatedProjectQueue.push(proj); + } + + function getNextInvalidatedProject() { + if (nextIndex < invalidatedProjectQueue.length) { + const proj = invalidatedProjectQueue[nextIndex]; + nextIndex++; + projectPendingBuild.removeKey(proj); + if (!projectPendingBuild.getSize()) { + invalidatedProjectQueue.length = 0; + } + return proj; + } + } + + function pendingInvalidatedProjects() { + return !!projectPendingBuild.getSize(); + } + + // Mark all downstream projects of this one needing to be built "later" + function queueBuildForDownstreamReferences(root: ResolvedConfigFileName, dependancyGraph: DependencyGraph) { + const deps = dependancyGraph.dependencyMap.getReferencesTo(root); + for (const ref of deps) { + // Can skip circular references + if (!projectPendingBuild.hasKey(ref)) { + addProjToQueue(ref); + queueBuildForDownstreamReferences(ref, dependancyGraph); + } + } + } } export interface SolutionBuilderHost extends CompilerHost { @@ -443,6 +497,7 @@ namespace ts { const hostWithWatch = host as SolutionBuilderWithWatchHost; const configFileCache = createConfigFileCache(host); let context = createBuildContext(defaultOptions); + let timerToBuildInvalidatedProject: any; const existingWatchersForWildcards = createMap(); return { @@ -454,8 +509,7 @@ namespace ts { getBuildGraph, invalidateProject, - buildInvalidatedProjects, - buildDependentInvalidatedProjects, + buildInvalidatedProject, resolveProjectName, @@ -466,7 +520,19 @@ namespace ts { host.reportSolutionBuilderStatus(createCompilerDiagnostic(message, ...args)); } - function reportWatchStatus(message: DiagnosticMessage, ...args: string[]) { + function storeErrors(proj: ResolvedConfigFileName, diagnostics: ReadonlyArray) { + if (context.options.watch) { + storeErrorSummary(proj, diagnostics.filter(diagnostic => diagnostic.category === DiagnosticCategory.Error).length); + } + } + + function storeErrorSummary(proj: ResolvedConfigFileName, errorCount: number) { + if (context.options.watch) { + context.diagnostics!.setValue(proj, errorCount); + } + } + + function reportWatchStatus(message: DiagnosticMessage, ...args: (string | number | undefined)[]) { if (hostWithWatch.onWatchStatusChange) { hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput }); } @@ -506,15 +572,12 @@ namespace ts { } } - function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName) { - reportWatchStatus(Diagnostics.File_change_detected_Starting_incremental_compilation); - invalidateProject(resolved); - if (!hostWithWatch.setTimeout) { - return; - } - hostWithWatch.setTimeout(buildInvalidatedProjects, 100); - hostWithWatch.setTimeout(buildDependentInvalidatedProjects, 3000); - } + } + + function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName) { + reportWatchStatus(Diagnostics.File_change_detected_Starting_incremental_compilation); + invalidateProject(resolved); + scheduleBuildInvalidatedProject(); } function resetBuildContext(opts = defaultOptions) { @@ -725,33 +788,44 @@ namespace ts { } configFileCache.removeKey(resolved); - context.invalidatedProjects.setValue(resolved, true); context.projectStatus.removeKey(resolved); - - const graph = getGlobalDependencyGraph()!; - if (graph) { - queueBuildForDownstreamReferences(resolved); + if (context.options.watch) { + context.diagnostics!.removeKey(resolved); } - // Mark all downstream projects of this one needing to be built "later" - function queueBuildForDownstreamReferences(root: ResolvedConfigFileName) { - const deps = graph.dependencyMap.getReferencesTo(root); - for (const ref of deps) { - // Can skip circular references - if (!context.queuedProjects.hasKey(ref)) { - context.queuedProjects.setValue(ref, true); - queueBuildForDownstreamReferences(ref); - } + context.invalidateProject(resolved, getGlobalDependencyGraph()); + } + + function scheduleBuildInvalidatedProject() { + if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) { + return; + } + if (timerToBuildInvalidatedProject) { + hostWithWatch.clearTimeout(timerToBuildInvalidatedProject); + } + timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250); + } + + function buildInvalidatedProject() { + timerToBuildInvalidatedProject = undefined; + const buildProject = context.getNextInvalidatedProject(); + buildSomeProjects(p => p === buildProject); + if (context.pendingInvalidatedProjects()) { + if (!timerToBuildInvalidatedProject) { + scheduleBuildInvalidatedProject(); } } + else { + reportErrorSummary(); + } } - function buildInvalidatedProjects() { - buildSomeProjects(p => context.invalidatedProjects.hasKey(p)); - } - - function buildDependentInvalidatedProjects() { - buildSomeProjects(p => context.queuedProjects.hasKey(p)); + function reportErrorSummary() { + if (context.options.watch) { + let errorCount = 0; + context.diagnostics!.getKeys().forEach(resolved => errorCount += context.diagnostics!.getValue(resolved)); + reportWatchStatus(errorCount === 1 ? Diagnostics.Found_1_error_Watching_for_file_changes : Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount); + } } function buildSomeProjects(predicate: (projName: ResolvedConfigFileName) => boolean) { @@ -808,6 +882,7 @@ namespace ts { if (temporaryMarks[projPath]) { if (!inCircularContext) { hadError = true; + // TODO(shkamat): Account for this error reportStatus(Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n")); return; } @@ -853,6 +928,7 @@ namespace ts { if (!configFile) { // Failed to read the config file resultFlags |= BuildResultFlags.ConfigFileErrors; + storeErrorSummary(proj, 1); context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); return resultFlags; } @@ -880,6 +956,7 @@ namespace ts { for (const diag of syntaxDiagnostics) { host.reportDiagnostic(diag); } + storeErrors(proj, syntaxDiagnostics); context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); return resultFlags; } @@ -892,6 +969,7 @@ namespace ts { for (const diag of declDiagnostics) { host.reportDiagnostic(diag); } + storeErrors(proj, declDiagnostics); context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" }); return resultFlags; } @@ -904,6 +982,7 @@ namespace ts { for (const diag of semanticDiagnostics) { host.reportDiagnostic(diag); } + storeErrors(proj, semanticDiagnostics); context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" }); return resultFlags; } @@ -1029,6 +1108,7 @@ namespace ts { if (host.fileExists(fullPathWithTsconfig)) { return fullPathWithTsconfig as ResolvedConfigFileName; } + // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better host.reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_not_found, relName(fullPath))); return undefined; } @@ -1048,7 +1128,10 @@ namespace ts { function buildAllProjects(): ExitStatus { if (context.options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); } const graph = getGlobalDependencyGraph(); - if (graph === undefined) return ExitStatus.DiagnosticsPresent_OutputsSkipped; + if (graph === undefined) { + reportErrorSummary(); + return ExitStatus.DiagnosticsPresent_OutputsSkipped; + } const queue = graph.buildQueue; reportBuildQueue(graph); @@ -1092,6 +1175,7 @@ namespace ts { const buildResult = buildSingleProject(next); anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors); } + reportErrorSummary(); return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success; } diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index f8813ecd1ae..b7d708446c1 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -205,14 +205,14 @@ namespace ts { // Rebuild this project tick(); builder.invalidateProject("/src/logic"); - builder.buildInvalidatedProjects(); + builder.buildInvalidatedProject(); // The file should be updated assert.equal(fs.statSync("/src/logic/index.js").mtimeMs, time(), "JS file should have been rebuilt"); assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should *not* have been rebuilt"); // Build downstream projects should update 'tests', but not 'core' tick(); - builder.buildDependentInvalidatedProjects(); + builder.buildInvalidatedProject(); assert.equal(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have been rebuilt"); assert.isBelow(fs.statSync("/src/core/index.js").mtimeMs, time(), "Upstream JS file should not have been rebuilt"); }); diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index d43a24a0b9c..d1405fa9e2c 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -25,12 +25,18 @@ namespace ts.tscWatch { /** [tsconfig, index] | [tsconfig, index, anotherModule, someDecl] */ type SubProjectFiles = [ReadonlyFile, ReadonlyFile] | [ReadonlyFile, ReadonlyFile, ReadonlyFile, ReadonlyFile]; const root = Harness.IO.getWorkspaceRoot(); + + function projectFilePath(subProject: SubProject, baseFileName: string) { + return `${projectsLocation}/${project}/${subProject}/${baseFileName.toLowerCase()}`; + } + function projectFile(subProject: SubProject, baseFileName: string): File { return { - path: `${projectsLocation}/${project}/${subProject}/${baseFileName.toLowerCase()}`, + path: projectFilePath(subProject, baseFileName), content: Harness.IO.readFile(`${root}/tests/projects/${project}/${subProject}/${baseFileName}`)! }; } + function subProjectFiles(subProject: SubProject, anotherModuleAndSomeDecl?: true): SubProjectFiles { const tsconfig = projectFile(subProject, "tsconfig.json"); const index = projectFile(subProject, "index.ts"); @@ -42,20 +48,86 @@ namespace ts.tscWatch { return [tsconfig, index, anotherModule, someDecl]; } + function getOutputFileNames(subProject: SubProject, baseFileNameWithoutExtension: string) { + const file = projectFilePath(subProject, baseFileNameWithoutExtension); + return [`${file}.js`, `${file}.d.ts`]; + } + + type OutputFileStamp = [string, Date | undefined]; + function getOutputStamps(host: WatchedSystem, subProject: SubProject, baseFileNameWithoutExtension: string): OutputFileStamp[] { + return getOutputFileNames(subProject, baseFileNameWithoutExtension).map(f => [f, host.getModifiedTime(f)] as OutputFileStamp); + } + + function getOutputFileStamps(host: WatchedSystem): OutputFileStamp[] { + return [ + ...getOutputStamps(host, SubProject.core, "anotherModule"), + ...getOutputStamps(host, SubProject.core, "index"), + ...getOutputStamps(host, SubProject.logic, "index"), + ...getOutputStamps(host, SubProject.tests, "index"), + ]; + } + + function verifyChangedFiles(actualStamps: OutputFileStamp[], oldTimeStamps: OutputFileStamp[], changedFiles: string[]) { + for (let i = 0; i < oldTimeStamps.length; i++) { + const actual = actualStamps[i]; + const old = oldTimeStamps[i]; + if (contains(changedFiles, actual[0])) { + assert.isTrue((actual[1] || 0) > (old[1] || 0), `${actual[0]} expected to written`); + } + else { + assert.equal(actual[1], old[1], `${actual[0]} expected to not change`); + } + } + } + const core = subProjectFiles(SubProject.core, /*anotherModuleAndSomeDecl*/ true); const logic = subProjectFiles(SubProject.logic); const tests = subProjectFiles(SubProject.tests); const ui = subProjectFiles(SubProject.ui); const allFiles: ReadonlyArray = [libFile, ...core, ...logic, ...tests, ...ui]; const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path); - it("creates solution in watch mode", () => { + + function createSolutionInWatchMode() { const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); - const originalWrite = host.write; - host.write = s => { console.log(s); originalWrite.call(host, s); }; createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]); checkWatchedFiles(host, testProjectExpectedWatchedFiles); checkWatchedDirectories(host, emptyArray, /*recursive*/ false); checkWatchedDirectories(host, emptyArray, /*recursive*/ true); // TODO: #26524 + checkOutputErrorsInitial(host, emptyArray); + const outputFileStamps = getOutputFileStamps(host); + for (const stamp of outputFileStamps) { + assert.isDefined(stamp[1], `${stamp[0]} expected to be present`); + } + return { host, outputFileStamps }; + } + it("creates solution in watch mode", () => { + createSolutionInWatchMode(); }); + + it("change builds changes and reports found errors message", () => { + const { host, outputFileStamps } = createSolutionInWatchMode(); + host.writeFile(core[1].path, `${core[1].content} +export class someClass { }`); + host.checkTimeoutQueueLengthAndRun(1); // Builds core + const changedCore = getOutputFileStamps(host); + verifyChangedFiles(changedCore, outputFileStamps, [ + ...getOutputFileNames(SubProject.core, "anotherModule"), // This should not be written really + ...getOutputFileNames(SubProject.core, "index") + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds tests + const changedTests = getOutputFileStamps(host); + verifyChangedFiles(changedTests, changedCore, [ + ...getOutputFileNames(SubProject.tests, "index") // Again these need not be written + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds logic + const changedLogic = getOutputFileStamps(host); + verifyChangedFiles(changedLogic, changedTests, [ + ...getOutputFileNames(SubProject.logic, "index") // Again these need not be written + ]); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, emptyArray); + }); + + // TODO: write tests reporting errors but that will have more involved work since file }); } diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index c881e9c14da..da1c4fd0d70 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -136,7 +136,7 @@ namespace ts.tscWatch { : createCompilerDiagnostic(Diagnostics.Found_0_errors_Watching_for_file_changes, errors.length); } - function checkOutputErrorsInitial(host: WatchedSystem, errors: ReadonlyArray, disableConsoleClears?: boolean, logsBeforeErrors?: string[]) { + export function checkOutputErrorsInitial(host: WatchedSystem, errors: ReadonlyArray, disableConsoleClears?: boolean, logsBeforeErrors?: string[]) { checkOutputErrors( host, /*logsBeforeWatchDiagnostic*/ undefined, @@ -147,7 +147,7 @@ namespace ts.tscWatch { createErrorsFoundCompilerDiagnostic(errors)); } - function checkOutputErrorsIncremental(host: WatchedSystem, errors: ReadonlyArray, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) { + export function checkOutputErrorsIncremental(host: WatchedSystem, errors: ReadonlyArray, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) { checkOutputErrors( host, logsBeforeWatchDiagnostic, From 056c87f289d54c52b00b9ae6d5727c36ab2e6081 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Aug 2018 07:08:35 -0700 Subject: [PATCH 27/77] Ignore constraints of generic mapped types in definitelyAssignableRelation --- src/compiler/checker.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 36cf9aa9474..0bc9cd76008 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11778,6 +11778,9 @@ namespace ts { } return Ternary.False; } + if (relation === definitelyAssignableRelation && isGenericMappedType(source)) { + return Ternary.False; + } const sourceIsPrimitive = !!(source.flags & TypeFlags.Primitive); if (relation !== identityRelation) { source = getApparentType(source); From 84d1e9f22fceaf37a0faf5c9ae9ace57023f1199 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Aug 2018 07:16:22 -0700 Subject: [PATCH 28/77] Accept new baselines --- tests/baselines/reference/mappedTypeNoTypeNoCrash.types | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/mappedTypeNoTypeNoCrash.types b/tests/baselines/reference/mappedTypeNoTypeNoCrash.types index 1c835498b81..c3debc7afc2 100644 --- a/tests/baselines/reference/mappedTypeNoTypeNoCrash.types +++ b/tests/baselines/reference/mappedTypeNoTypeNoCrash.types @@ -1,4 +1,4 @@ === tests/cases/compiler/mappedTypeNoTypeNoCrash.ts === type T0 = ({[K in keyof T]}) extends ({[key in K]: T[K]}) ? number : never; ->T0 : number +>T0 : T0 From 74c57caa900e0439cfd46fec587c0c2ff87d8f0e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Aug 2018 07:16:31 -0700 Subject: [PATCH 29/77] Add regression test --- .../conformance/types/mapped/mappedTypesArraysTuples.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts b/tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts index c936a86c897..5d8fbc4b379 100644 --- a/tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts +++ b/tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts @@ -85,3 +85,11 @@ declare function mapArray(arr: T): Mapped; function acceptMappedArray(arr: T) { acceptArray(mapArray(arr)); } + +// Repro from #26163 + +type Unconstrained = ElementType>; +type T1 = Unconstrained<[string, number, boolean]>; // string | number | boolean + +type Constrained = ElementType>; +type T2 = Constrained<[string, number, boolean]>; // string | number | boolean From 45eb043fb18cee03c5aeba317ee51a6e1ffb060b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Aug 2018 07:16:48 -0700 Subject: [PATCH 30/77] Accept new baselines --- .../reference/mappedTypesArraysTuples.js | 12 ++++++++++ .../reference/mappedTypesArraysTuples.symbols | 24 +++++++++++++++++++ .../reference/mappedTypesArraysTuples.types | 14 +++++++++++ 3 files changed, 50 insertions(+) diff --git a/tests/baselines/reference/mappedTypesArraysTuples.js b/tests/baselines/reference/mappedTypesArraysTuples.js index d3d976c04d3..5546f5201df 100644 --- a/tests/baselines/reference/mappedTypesArraysTuples.js +++ b/tests/baselines/reference/mappedTypesArraysTuples.js @@ -83,6 +83,14 @@ declare function mapArray(arr: T): Mapped; function acceptMappedArray(arr: T) { acceptArray(mapArray(arr)); } + +// Repro from #26163 + +type Unconstrained = ElementType>; +type T1 = Unconstrained<[string, number, boolean]>; // string | number | boolean + +type Constrained = ElementType>; +type T2 = Constrained<[string, number, boolean]>; // string | number | boolean //// [mappedTypesArraysTuples.js] @@ -182,3 +190,7 @@ declare type R2 = ElementType>; declare function acceptArray(arr: any[]): void; declare function mapArray(arr: T): Mapped; declare function acceptMappedArray(arr: T): void; +declare type Unconstrained = ElementType>; +declare type T1 = Unconstrained<[string, number, boolean]>; +declare type Constrained = ElementType>; +declare type T2 = Constrained<[string, number, boolean]>; diff --git a/tests/baselines/reference/mappedTypesArraysTuples.symbols b/tests/baselines/reference/mappedTypesArraysTuples.symbols index 1815b354b6c..ffc7fe19e3f 100644 --- a/tests/baselines/reference/mappedTypesArraysTuples.symbols +++ b/tests/baselines/reference/mappedTypesArraysTuples.symbols @@ -328,3 +328,27 @@ function acceptMappedArray(arr: T) { >arr : Symbol(arr, Decl(mappedTypesArraysTuples.ts, 81, 44)) } +// Repro from #26163 + +type Unconstrained = ElementType>; +>Unconstrained : Symbol(Unconstrained, Decl(mappedTypesArraysTuples.ts, 83, 1)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 87, 19)) +>ElementType : Symbol(ElementType, Decl(mappedTypesArraysTuples.ts, 66, 1)) +>Mapped : Symbol(Mapped, Decl(mappedTypesArraysTuples.ts, 70, 59)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 87, 19)) + +type T1 = Unconstrained<[string, number, boolean]>; // string | number | boolean +>T1 : Symbol(T1, Decl(mappedTypesArraysTuples.ts, 87, 47)) +>Unconstrained : Symbol(Unconstrained, Decl(mappedTypesArraysTuples.ts, 83, 1)) + +type Constrained = ElementType>; +>Constrained : Symbol(Constrained, Decl(mappedTypesArraysTuples.ts, 88, 51)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 90, 17)) +>ElementType : Symbol(ElementType, Decl(mappedTypesArraysTuples.ts, 66, 1)) +>Mapped : Symbol(Mapped, Decl(mappedTypesArraysTuples.ts, 70, 59)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 90, 17)) + +type T2 = Constrained<[string, number, boolean]>; // string | number | boolean +>T2 : Symbol(T2, Decl(mappedTypesArraysTuples.ts, 90, 59)) +>Constrained : Symbol(Constrained, Decl(mappedTypesArraysTuples.ts, 88, 51)) + diff --git a/tests/baselines/reference/mappedTypesArraysTuples.types b/tests/baselines/reference/mappedTypesArraysTuples.types index 42ab457b783..df99246e9bd 100644 --- a/tests/baselines/reference/mappedTypesArraysTuples.types +++ b/tests/baselines/reference/mappedTypesArraysTuples.types @@ -241,3 +241,17 @@ function acceptMappedArray(arr: T) { >arr : T } +// Repro from #26163 + +type Unconstrained = ElementType>; +>Unconstrained : ElementType> + +type T1 = Unconstrained<[string, number, boolean]>; // string | number | boolean +>T1 : string | number | boolean + +type Constrained = ElementType>; +>Constrained : ElementType> + +type T2 = Constrained<[string, number, boolean]>; // string | number | boolean +>T2 : string | number | boolean + From f945eb93d5f8f1bac8b1f65f36548b42d90f1932 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 22 Aug 2018 14:18:44 -0700 Subject: [PATCH 31/77] Update user baselines (#26601) --- tests/baselines/reference/user/follow-redirects.log | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/user/follow-redirects.log b/tests/baselines/reference/user/follow-redirects.log index 27df4a5a8f1..d1a5afa2e16 100644 --- a/tests/baselines/reference/user/follow-redirects.log +++ b/tests/baselines/reference/user/follow-redirects.log @@ -2,10 +2,11 @@ Exit Code: 1 Standard output: node_modules/follow-redirects/index.js(80,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. node_modules/follow-redirects/index.js(81,10): error TS2339: Property 'abort' does not exist on type 'RedirectableRequest'. -node_modules/follow-redirects/index.js(195,12): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. -node_modules/follow-redirects/index.js(229,35): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. +node_modules/follow-redirects/index.js(133,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(199,12): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(233,35): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'. -node_modules/follow-redirects/index.js(242,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(246,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. From 194ffb3449d5e9abfdb16117f762940e6df340b8 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 22 Aug 2018 15:20:33 -0700 Subject: [PATCH 32/77] fourslash: Allow to verify textChanges without changing file content (#26607) --- src/harness/fourslash.ts | 176 +++++++++++------- ...deFixForgottenThisPropertyAccess_static.ts | 3 +- .../codeFixUndeclaredInStaticMethod.ts | 4 + .../fourslash/codeFixUndeclaredMethod.ts | 4 +- .../codeFixUndeclaredMethodFunctionArgs.ts | 1 + tests/cases/fourslash/fourslash.ts | 2 + 6 files changed, 117 insertions(+), 73 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index e937b1fe544..7ed3ae2e429 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -50,10 +50,8 @@ namespace FourSlash { data?: {}; } - export interface Range { + export interface Range extends ts.TextRange { fileName: string; - pos: number; - end: number; marker?: Marker; } @@ -1103,7 +1101,7 @@ namespace FourSlash { return node; } - private verifyRange(desc: string, expected: Range, actual: ts.Node) { + private verifyRange(desc: string, expected: ts.TextRange, actual: ts.Node) { const actualStart = actual.getStart(); const actualEnd = actual.getEnd(); if (actualStart !== expected.pos || actualEnd !== expected.end) { @@ -1713,11 +1711,8 @@ Actual: ${stringify(fullActual)}`); } public baselineQuickInfo() { - let baselineFile = this.testData.globalOptions[MetadataOptionNames.baselineFile]; - if (!baselineFile) { - baselineFile = ts.getBaseFileName(this.activeFile.fileName).replace(ts.Extension.Ts, ".baseline"); - } - + const baselineFile = this.testData.globalOptions[MetadataOptionNames.baselineFile] || + ts.getBaseFileName(this.activeFile.fileName).replace(ts.Extension.Ts, ".baseline"); Harness.Baseline.runBaseline( baselineFile, stringify( @@ -1958,18 +1953,11 @@ Actual: ${stringify(fullActual)}`); * May be negative. */ private applyEdits(fileName: string, edits: ReadonlyArray, isFormattingEdit: boolean): number { - // We get back a set of edits, but langSvc.editScript only accepts one at a time. Use this to keep track - // of the incremental offset from each edit to the next. We assume these edit ranges don't overlap - - // Copy this so we don't ruin someone else's copy - edits = JSON.parse(JSON.stringify(edits)); - // Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters const oldContent = this.getFileContent(fileName); let runningOffset = 0; - for (let i = 0; i < edits.length; i++) { - const edit = edits[i]; + forEachTextChange(edits, edit => { const offsetStart = edit.span.start; const offsetEnd = offsetStart + edit.span.length; this.editScriptAndUpdateMarkers(fileName, offsetStart, offsetEnd, edit.newText); @@ -1985,14 +1973,7 @@ Actual: ${stringify(fullActual)}`); } } runningOffset += editDelta; - - // Update positions of any future edits affected by this change - for (let j = i + 1; j < edits.length; j++) { - if (edits[j].span.start >= edits[i].span.start) { - edits[j].span.start += editDelta; - } - } - } + }); if (isFormattingEdit) { const newContent = this.getFileContent(fileName); @@ -2034,30 +2015,14 @@ Actual: ${stringify(fullActual)}`); this.languageServiceAdapterHost.editScript(fileName, editStart, editEnd, newText); for (const marker of this.testData.markers) { if (marker.fileName === fileName) { - marker.position = updatePosition(marker.position); + marker.position = updatePosition(marker.position, editStart, editEnd, newText); } } for (const range of this.testData.ranges) { if (range.fileName === fileName) { - range.pos = updatePosition(range.pos); - range.end = updatePosition(range.end); - } - } - - function updatePosition(position: number) { - if (position > editStart) { - if (position < editEnd) { - // Inside the edit - mark it as invalidated (?) - return -1; - } - else { - // Move marker back/forward by the appropriate amount - return position + (editStart - editEnd) + newText.length; - } - } - else { - return position; + range.pos = updatePosition(range.pos, editStart, editEnd, newText); + range.end = updatePosition(range.end, editStart, editEnd, newText); } } } @@ -2488,22 +2453,24 @@ Actual: ${stringify(fullActual)}`); this.applyCodeActions(codeActions); - this.verifyNewContent(options, ts.flatMap(codeActions, a => a.changes.map(c => c.fileName))); + this.verifyNewContentAfterChange(options, ts.flatMap(codeActions, a => a.changes.map(c => c.fileName))); } public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) { + this.verifyTextMatches(this.rangeText(this.getOnlyRange()), !!includeWhiteSpace, expectedText); + } + + private getOnlyRange() { const ranges = this.getRanges(); if (ranges.length !== 1) { this.raiseError("Exactly one range should be specified in the testfile."); } + return ts.first(ranges); + } - const actualText = this.rangeText(ranges[0]); - - const result = includeWhiteSpace - ? actualText === expectedText - : this.removeWhitespace(actualText) === this.removeWhitespace(expectedText); - - if (!result) { + private verifyTextMatches(actualText: string, includeWhitespace: boolean, expectedText: string) { + const removeWhitespace = (s: string): string => includeWhitespace ? s : this.removeWhitespace(s); + if (removeWhitespace(actualText) !== removeWhitespace(expectedText)) { this.raiseError(`Actual range text doesn't match expected text.\n${showTextDiff(expectedText, actualText)}`); } } @@ -2570,33 +2537,68 @@ Actual: ${stringify(fullActual)}`); const action = actions[index]; assert.equal(action.description, options.description); + assert.deepEqual(action.commands, options.commands); - for (const change of action.changes) { - this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false); + if (options.applyChanges) { + for (const change of action.changes) { + this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false); + } + this.verifyNewContentAfterChange(options, action.changes.map(c => c.fileName)); + } + else { + this.verifyNewContent(options, action.changes); } - - this.verifyNewContent(options, action.changes.map(c => c.fileName)); } - private verifyNewContent(options: FourSlashInterface.NewContentOptions, changedFiles: ReadonlyArray) { - const assertedChangedFiles = !options.newFileContent || typeof options.newFileContent === "string" + private verifyNewContent({ newFileContent, newRangeContent }: FourSlashInterface.NewContentOptions, changes: ReadonlyArray): void { + if (newRangeContent !== undefined) { + assert(newFileContent === undefined); + assert(changes.length === 1, "Affected 0 or more than 1 file, must use 'newFileContent' instead of 'newRangeContent'"); + const change = ts.first(changes); + assert(change.fileName = this.activeFile.fileName); + const newText = ts.textChanges.applyChanges(this.getFileContent(this.activeFile.fileName), change.textChanges); + const newRange = updateTextRangeForTextChanges(this.getOnlyRange(), change.textChanges); + const actualText = newText.slice(newRange.pos, newRange.end); + this.verifyTextMatches(actualText, /*includeWhitespace*/ true, newRangeContent); + } + else { + if (newFileContent === undefined) throw ts.Debug.fail(); + if (typeof newFileContent !== "object") newFileContent = { [this.activeFile.fileName]: newFileContent }; + for (const change of changes) { + const expectedNewContent = newFileContent[change.fileName]; + if (expectedNewContent === undefined) { + ts.Debug.fail(`Did not expect a change in ${change.fileName}`); + } + const oldText = this.tryGetFileContent(change.fileName); + ts.Debug.assert(!!change.isNewFile === (oldText === undefined)); + const newContent = change.isNewFile ? ts.first(change.textChanges).newText : ts.textChanges.applyChanges(oldText!, change.textChanges); + assert.equal(newContent, expectedNewContent); + } + for (const newFileName in newFileContent) { + ts.Debug.assert(changes.some(c => c.fileName === newFileName), "No change in file", () => newFileName); + } + } + } + + private verifyNewContentAfterChange({ newFileContent, newRangeContent }: FourSlashInterface.NewContentOptions, changedFiles: ReadonlyArray) { + const assertedChangedFiles = !newFileContent || typeof newFileContent === "string" ? [this.activeFile.fileName] - : ts.getOwnKeys(options.newFileContent); + : ts.getOwnKeys(newFileContent); assert.deepEqual(assertedChangedFiles, changedFiles); - if (options.newFileContent !== undefined) { - assert(!options.newRangeContent); - if (typeof options.newFileContent === "string") { - this.verifyCurrentFileContent(options.newFileContent); + if (newFileContent !== undefined) { + assert(!newRangeContent); + if (typeof newFileContent === "string") { + this.verifyCurrentFileContent(newFileContent); } else { - for (const fileName in options.newFileContent) { - this.verifyFileContent(fileName, options.newFileContent[fileName]); + for (const fileName in newFileContent) { + this.verifyFileContent(fileName, newFileContent[fileName]); } } } else { - this.verifyRangeIs(options.newRangeContent!, /*includeWhitespace*/ true); + this.verifyRangeIs(newRangeContent!, /*includeWhitespace*/ true); } } @@ -3114,7 +3116,7 @@ Actual: ${stringify(fullActual)}`); assert(action.name === "Move to a new file" && action.description === "Move to a new file"); const editInfo = this.languageService.getEditsForRefactor(range.fileName, this.formatCodeSettings, range, refactor.name, action.name, options.preferences || ts.emptyOptions)!; - this.testNewFileContents(editInfo.edits, options.newFileContents, "move to new file"); + this.verifyNewContent({ newFileContent: options.newFileContents }, editInfo.edits); } private testNewFileContents(edits: ReadonlyArray, newFileContents: { [fileName: string]: string }, description: string): void { @@ -3380,6 +3382,36 @@ Actual: ${stringify(fullActual)}`); } } + function updateTextRangeForTextChanges({ pos, end }: ts.TextRange, textChanges: ReadonlyArray): ts.TextRange { + forEachTextChange(textChanges, change => { + const update = (p: number): number => updatePosition(p, change.span.start, ts.textSpanEnd(change.span), change.newText); + pos = update(pos); + end = update(end); + }); + return { pos, end }; + } + + /** Apply each textChange in order, updating future changes to account for the text offset of previous changes. */ + function forEachTextChange(changes: ReadonlyArray, cb: (change: ts.TextChange) => void): void { + // Copy this so we don't ruin someone else's copy + changes = JSON.parse(JSON.stringify(changes)); + for (let i = 0; i < changes.length; i++) { + const change = changes[i]; + cb(change); + const changeDelta = change.newText.length - change.span.length; + for (let j = i + 1; j < changes.length; j++) { + if (changes[j].span.start >= change.span.start) { + changes[j].span.start += changeDelta; + } + } + } + } + + function updatePosition(position: number, editStart: number, editEnd: number, { length }: string): number { + // If inside the edit, return -1 to mark as invalid + return position <= editStart ? position : position < editEnd ? -1 : position + length - + (editEnd - editStart); + } + function renameKeys(obj: { readonly [key: string]: T }, renameKey: (key: string) => string): { readonly [key: string]: T } { const res: { [key: string]: T } = {}; for (const key in obj) { @@ -4842,10 +4874,12 @@ namespace FourSlashInterface { } export interface VerifyCodeFixOptions extends NewContentOptions { - description: string; - errorCode?: number; - index?: number; - preferences?: ts.UserPreferences; + readonly description: string; + readonly errorCode?: number; + readonly index?: number; + readonly preferences?: ts.UserPreferences; + readonly applyChanges?: boolean; + readonly commands?: ReadonlyArray; } export interface VerifyCodeFixAvailableOptions { diff --git a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts index cc6f8032a51..66e126abd69 100644 --- a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts +++ b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts @@ -12,7 +12,8 @@ verify.codeFix({ `class C { static m() { C.m(); } n() { m(); } -}` +}`, + applyChanges: true, }); verify.codeFix({ diff --git a/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts b/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts index a4ac2488350..a406360c500 100644 --- a/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts +++ b/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts @@ -24,6 +24,7 @@ verify.codeFix({ throw new Error("Method not implemented."); } }`, + applyChanges: true, }); verify.codeFix({ @@ -44,6 +45,7 @@ verify.codeFix({ throw new Error("Method not implemented."); } }`, + applyChanges: true, }); verify.codeFix({ @@ -65,6 +67,7 @@ verify.codeFix({ throw new Error("Method not implemented."); } }`, + applyChanges: true, }); verify.codeFix({ @@ -87,4 +90,5 @@ verify.codeFix({ throw new Error("Method not implemented."); } }`, + applyChanges: true, }); diff --git a/tests/cases/fourslash/codeFixUndeclaredMethod.ts b/tests/cases/fourslash/codeFixUndeclaredMethod.ts index bf276379b0a..151192078f3 100644 --- a/tests/cases/fourslash/codeFixUndeclaredMethod.ts +++ b/tests/cases/fourslash/codeFixUndeclaredMethod.ts @@ -26,6 +26,7 @@ verify.codeFix({ this.foo3<1,2,3,4,5,6,7,8>(); } }`, + applyChanges: true, }); verify.codeFix({ @@ -46,7 +47,8 @@ verify.codeFix({ // 8 type args this.foo3<1,2,3,4,5,6,7,8>(); } -}` +}`, + applyChanges: true, }); verify.codeFix({ diff --git a/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts b/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts index 1c06cfc3afd..1389a50935b 100644 --- a/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts +++ b/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts @@ -15,6 +15,7 @@ verify.codeFix({ throw new Error("Method not implemented."); } `, + applyChanges: true, }); verify.codeFix({ diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 900ae172ab8..8a91718dd7b 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -183,6 +183,8 @@ declare namespace FourSlashInterface { errorCode?: number, index?: number, preferences?: UserPreferences, + applyChanges?: boolean, + commands?: {}[], }); codeFixAvailable(options?: ReadonlyArray): void; applicableRefactorAvailableAtMarker(markerName: string): void; From 5e8b63cd1d6dbc6b271bc15228a0fabde5ab7ef5 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 22 Aug 2018 16:17:42 -0700 Subject: [PATCH 33/77] Use context free expression types in evolving array checking and cache context free type (#26585) * Use context free expression types in evolving array checking and cache context free type * Simplify second test * Low max depth a tad just so node 8 wont stack out * By request make flow control a round number --- src/compiler/checker.ts | 13 +- .../deeplyDependentLargeArrayMutation.symbols | 158 + .../deeplyDependentLargeArrayMutation.types | 234 ++ ...deeplyDependentLargeArrayMutation2.symbols | 1847 +++++++++ .../deeplyDependentLargeArrayMutation2.types | 3674 +++++++++++++++++ .../deeplyDependentLargeArrayMutation.ts | 35 + .../deeplyDependentLargeArrayMutation2.ts | 320 ++ 7 files changed, 6277 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/deeplyDependentLargeArrayMutation.symbols create mode 100644 tests/baselines/reference/deeplyDependentLargeArrayMutation.types create mode 100644 tests/baselines/reference/deeplyDependentLargeArrayMutation2.symbols create mode 100644 tests/baselines/reference/deeplyDependentLargeArrayMutation2.types create mode 100644 tests/cases/compiler/deeplyDependentLargeArrayMutation.ts create mode 100644 tests/cases/compiler/deeplyDependentLargeArrayMutation2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0ca8f265130..7e0e7122404 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14433,8 +14433,8 @@ namespace ts { return resultType; function getTypeAtFlowNode(flow: FlowNode): FlowType { - if (flowDepth === 2500) { - // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error + if (flowDepth === 2000) { + // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error // and disable further control flow analysis in the containing function or module body. flowAnalysisDisabled = true; reportFlowControlError(reference); @@ -14574,7 +14574,8 @@ namespace ts { } } else { - const indexType = getTypeOfExpression((node.left).argumentExpression); + // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time) + const indexType = getContextFreeTypeOfExpression((node.left).argumentExpression); if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { evolvedType = addEvolvingArrayElementType(evolvedType, node.right); } @@ -21720,9 +21721,13 @@ namespace ts { * It sets the contextual type of the node to any before calling getTypeOfExpression. */ function getContextFreeTypeOfExpression(node: Expression) { + const links = getNodeLinks(node); + if (links.contextFreeType) { + return links.contextFreeType; + } const saveContextualType = node.contextualType; node.contextualType = anyType; - const type = getTypeOfExpression(node); + const type = links.contextFreeType = checkExpression(node, CheckMode.SkipContextSensitive); node.contextualType = saveContextualType; return type; } diff --git a/tests/baselines/reference/deeplyDependentLargeArrayMutation.symbols b/tests/baselines/reference/deeplyDependentLargeArrayMutation.symbols new file mode 100644 index 00000000000..47f201f2392 --- /dev/null +++ b/tests/baselines/reference/deeplyDependentLargeArrayMutation.symbols @@ -0,0 +1,158 @@ +=== tests/cases/compiler/foo.js === +// repro from #26031 +function build() { +>build : Symbol(build, Decl(foo.js, 0, 0)) + + var arr = []; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + arr[arr.length] = 'value'; +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(foo.js, 2, 7)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/deeplyDependentLargeArrayMutation.types b/tests/baselines/reference/deeplyDependentLargeArrayMutation.types new file mode 100644 index 00000000000..d578c7bf233 --- /dev/null +++ b/tests/baselines/reference/deeplyDependentLargeArrayMutation.types @@ -0,0 +1,234 @@ +=== tests/cases/compiler/foo.js === +// repro from #26031 +function build() { +>build : () => void + + var arr = []; +>arr : any[] +>[] : undefined[] + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" + + arr[arr.length] = 'value'; +>arr[arr.length] = 'value' : "value" +>arr[arr.length] : any +>arr : any[] +>arr.length : number +>arr : any[] +>length : number +>'value' : "value" +} diff --git a/tests/baselines/reference/deeplyDependentLargeArrayMutation2.symbols b/tests/baselines/reference/deeplyDependentLargeArrayMutation2.symbols new file mode 100644 index 00000000000..a70496c41b1 --- /dev/null +++ b/tests/baselines/reference/deeplyDependentLargeArrayMutation2.symbols @@ -0,0 +1,1847 @@ +=== tests/cases/compiler/foo.js === +// Looking at this test and thinking "that's silly, nobody would write code like that" and thinking it's OK to break this test? +// You'd be wrong - https://raw.githubusercontent.com/archilogic-com/3dio-js/master/build/3dio.js and plenty of other codebases +// have js code exactly like this! This pattern (even at this size!) with a few more embellishments is a common way to encode +// polygons or verticies into a buffer from a formulaic object definition! So while this is a lot more regular than a real piece +// of code, this is still representative of a common pattern. +function build() { +>build : Symbol(build, Decl(foo.js, 0, 0)) + + let i = 0; +>i : Symbol(i, Decl(foo.js, 6, 7)) + + const arr = []; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + arr[i++] = arr[i] + 1; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +>i : Symbol(i, Decl(foo.js, 6, 7)) + + return arr; +>arr : Symbol(arr, Decl(foo.js, 7, 9)) +} + +const a = build(); +>a : Symbol(a, Decl(foo.js, 315, 5)) +>build : Symbol(build, Decl(foo.js, 0, 0)) + diff --git a/tests/baselines/reference/deeplyDependentLargeArrayMutation2.types b/tests/baselines/reference/deeplyDependentLargeArrayMutation2.types new file mode 100644 index 00000000000..359ce7db33f --- /dev/null +++ b/tests/baselines/reference/deeplyDependentLargeArrayMutation2.types @@ -0,0 +1,3674 @@ +=== tests/cases/compiler/foo.js === +// Looking at this test and thinking "that's silly, nobody would write code like that" and thinking it's OK to break this test? +// You'd be wrong - https://raw.githubusercontent.com/archilogic-com/3dio-js/master/build/3dio.js and plenty of other codebases +// have js code exactly like this! This pattern (even at this size!) with a few more embellishments is a common way to encode +// polygons or verticies into a buffer from a formulaic object definition! So while this is a lot more regular than a real piece +// of code, this is still representative of a common pattern. +function build() { +>build : () => any[] + + let i = 0; +>i : number +>0 : 0 + + const arr = []; +>arr : any[] +>[] : undefined[] + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + arr[i++] = arr[i] + 1; +>arr[i++] = arr[i] + 1 : any +>arr[i++] : any +>arr : any[] +>i++ : number +>i : number +>arr[i] + 1 : any +>arr[i] : any +>arr : any[] +>i : number +>1 : 1 + + return arr; +>arr : any[] +} + +const a = build(); +>a : any[] +>build() : any[] +>build : () => any[] + diff --git a/tests/cases/compiler/deeplyDependentLargeArrayMutation.ts b/tests/cases/compiler/deeplyDependentLargeArrayMutation.ts new file mode 100644 index 00000000000..1ea7474ba75 --- /dev/null +++ b/tests/cases/compiler/deeplyDependentLargeArrayMutation.ts @@ -0,0 +1,35 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 +// @filename: foo.js +// repro from #26031 +function build() { + var arr = []; + + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; + arr[arr.length] = 'value'; +} \ No newline at end of file diff --git a/tests/cases/compiler/deeplyDependentLargeArrayMutation2.ts b/tests/cases/compiler/deeplyDependentLargeArrayMutation2.ts new file mode 100644 index 00000000000..d82fae46744 --- /dev/null +++ b/tests/cases/compiler/deeplyDependentLargeArrayMutation2.ts @@ -0,0 +1,320 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @filename: foo.js +// Looking at this test and thinking "that's silly, nobody would write code like that" and thinking it's OK to break this test? +// You'd be wrong - https://raw.githubusercontent.com/archilogic-com/3dio-js/master/build/3dio.js and plenty of other codebases +// have js code exactly like this! This pattern (even at this size!) with a few more embellishments is a common way to encode +// polygons or verticies into a buffer from a formulaic object definition! So while this is a lot more regular than a real piece +// of code, this is still representative of a common pattern. +function build() { + let i = 0; + const arr = []; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + arr[i++] = arr[i] + 1; + return arr; +} + +const a = build(); \ No newline at end of file From bedf776b42e1d4708428a7b26fb0a1521a3f462e Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Thu, 23 Aug 2018 09:08:29 +0200 Subject: [PATCH 34/77] Revert #26360: Don't error on destructure of private property with computed property syntax --- src/compiler/checker.ts | 2 +- .../reference/destructureComputedProperty.errors.txt | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7e0e7122404..983f9f070d0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24250,7 +24250,7 @@ namespace ts { if (nameText) { const property = getPropertyOfType(parentType!, nameText)!; // TODO: GH#18217 markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference. - if (parent.initializer && property && !isComputedPropertyName(name)) { + if (parent.initializer && property) { checkPropertyAccessibility(parent, parent.initializer.kind === SyntaxKind.SuperKeyword, parentType!, property); } } diff --git a/tests/baselines/reference/destructureComputedProperty.errors.txt b/tests/baselines/reference/destructureComputedProperty.errors.txt index 5d461867a54..5b39820988a 100644 --- a/tests/baselines/reference/destructureComputedProperty.errors.txt +++ b/tests/baselines/reference/destructureComputedProperty.errors.txt @@ -1,8 +1,9 @@ tests/cases/compiler/destructureComputedProperty.ts(7,7): error TS2341: Property 'p' is private and only accessible within class 'C'. +tests/cases/compiler/destructureComputedProperty.ts(8,7): error TS2341: Property 'p' is private and only accessible within class 'C'. tests/cases/compiler/destructureComputedProperty.ts(10,7): error TS2341: Property 'p' is private and only accessible within class 'C'. -==== tests/cases/compiler/destructureComputedProperty.ts (2 errors) ==== +==== tests/cases/compiler/destructureComputedProperty.ts (3 errors) ==== declare const ab: { n: number } | { n: string }; const nameN = "n"; const { [nameN]: n } = ab; @@ -13,6 +14,8 @@ tests/cases/compiler/destructureComputedProperty.ts(10,7): error TS2341: Propert ~~~~~~~~~~~ !!! error TS2341: Property 'p' is private and only accessible within class 'C'. const { ["p"]: p1 } = new C(); + ~~~~~~~~~~~~~ +!!! error TS2341: Property 'p' is private and only accessible within class 'C'. const { [nameP]: p2 } = new C(); const { p: p3 } = new C(); ~~~~~~~~~ From 03653934c30f4bc3a94f7067ff8506fcdfa37048 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 23 Aug 2018 08:21:28 -0700 Subject: [PATCH 35/77] Don't create expando object literals in TS (#26525) Previously, getWidenedTypedFromJSPropertyAssignment was not called for Typescript code. Since property assignments on functions, it is. That meant that property assignments would incorrectly create a JS container for empty object literals in a property assignment, even in Typescript: ```ts const one = () => 1 one.p = {} one.p.q = {} // should not work in Typescript! ``` Now empty object literals never create expando objects in Typescript, because getJSExpandoObjectType requires the declaration to be in a JS file. --- src/compiler/checker.ts | 2 +- .../reference/typeFromPropertyAssignment30.js | 15 +++++++++++++ .../typeFromPropertyAssignment30.symbols | 20 ++++++++++++++++++ .../typeFromPropertyAssignment30.types | 21 +++++++++++++++++++ .../salsa/typeFromPropertyAssignment30.ts | 8 +++++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/typeFromPropertyAssignment30.js create mode 100644 tests/baselines/reference/typeFromPropertyAssignment30.symbols create mode 100644 tests/baselines/reference/typeFromPropertyAssignment30.types create mode 100644 tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7e0e7122404..269f8b26f0a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4795,7 +4795,7 @@ namespace ts { } function getJSExpandoObjectType(decl: Node, symbol: Symbol, init: Expression | undefined): Type | undefined { - if (!init || !isObjectLiteralExpression(init) || init.properties.length) { + if (!isInJavaScriptFile(decl) || !init || !isObjectLiteralExpression(init) || init.properties.length) { return undefined; } const exports = createSymbolTable(); diff --git a/tests/baselines/reference/typeFromPropertyAssignment30.js b/tests/baselines/reference/typeFromPropertyAssignment30.js new file mode 100644 index 00000000000..1ec7cf70a8b --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment30.js @@ -0,0 +1,15 @@ +//// [typeFromPropertyAssignment30.ts] +interface Combo { + (): number; + p?: { [s: string]: number }; +} +const c: Combo = () => 1 +// should not be an expando object, but contextually typed by Combo.p +c.p = {} + + + +//// [typeFromPropertyAssignment30.js] +var c = function () { return 1; }; +// should not be an expando object, but contextually typed by Combo.p +c.p = {}; diff --git a/tests/baselines/reference/typeFromPropertyAssignment30.symbols b/tests/baselines/reference/typeFromPropertyAssignment30.symbols new file mode 100644 index 00000000000..5614067864c --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment30.symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts === +interface Combo { +>Combo : Symbol(Combo, Decl(typeFromPropertyAssignment30.ts, 0, 0)) + + (): number; + p?: { [s: string]: number }; +>p : Symbol(Combo.p, Decl(typeFromPropertyAssignment30.ts, 1, 15)) +>s : Symbol(s, Decl(typeFromPropertyAssignment30.ts, 2, 11)) +} +const c: Combo = () => 1 +>c : Symbol(c, Decl(typeFromPropertyAssignment30.ts, 4, 5), Decl(typeFromPropertyAssignment30.ts, 4, 24)) +>Combo : Symbol(Combo, Decl(typeFromPropertyAssignment30.ts, 0, 0)) + +// should not be an expando object, but contextually typed by Combo.p +c.p = {} +>c.p : Symbol(Combo.p, Decl(typeFromPropertyAssignment30.ts, 1, 15)) +>c : Symbol(c, Decl(typeFromPropertyAssignment30.ts, 4, 5), Decl(typeFromPropertyAssignment30.ts, 4, 24)) +>p : Symbol(Combo.p, Decl(typeFromPropertyAssignment30.ts, 1, 15)) + + diff --git a/tests/baselines/reference/typeFromPropertyAssignment30.types b/tests/baselines/reference/typeFromPropertyAssignment30.types new file mode 100644 index 00000000000..ee2c9fdb8c5 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment30.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts === +interface Combo { + (): number; + p?: { [s: string]: number }; +>p : { [s: string]: number; } +>s : string +} +const c: Combo = () => 1 +>c : Combo +>() => 1 : { (): number; p: {}; } +>1 : 1 + +// should not be an expando object, but contextually typed by Combo.p +c.p = {} +>c.p = {} : {} +>c.p : { [s: string]: number; } +>c : Combo +>p : { [s: string]: number; } +>{} : {} + + diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts new file mode 100644 index 00000000000..e24c8ec2b94 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts @@ -0,0 +1,8 @@ +interface Combo { + (): number; + p?: { [s: string]: number }; +} +const c: Combo = () => 1 +// should not be an expando object, but contextually typed by Combo.p +c.p = {} + From c5b07a904d544f77ee2a6c3ca6be1148f7c450be Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Thu, 23 Aug 2018 09:17:40 -0700 Subject: [PATCH 36/77] Update user baselines (#26632) --- .../reference/user/chrome-devtools-frontend.log | 6 +++--- tests/baselines/reference/user/follow-redirects.log | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/user/chrome-devtools-frontend.log b/tests/baselines/reference/user/chrome-devtools-frontend.log index 11d1d0cd2a8..31bd0e9d8b2 100644 --- a/tests/baselines/reference/user/chrome-devtools-frontend.log +++ b/tests/baselines/reference/user/chrome-devtools-frontend.log @@ -3801,15 +3801,15 @@ node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(508,33): node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(513,36): error TS2694: Namespace 'Components.Linkifier' has no exported member 'LinkHandler'. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(517,10): error TS2339: Property 'runtime' does not exist on type 'Window'. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(525,10): error TS2339: Property 'runtime' does not exist on type 'Window'. -node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(564,9): error TS2322: Type '({ section: string; title: string; handler: any; } | { section: string; title: any; handler: () => void; })[]' is not assignable to type '{ title: string; handler: () => any; }[]'. - Type '{ section: string; title: string; handler: any; } | { section: string; title: any; handler: () => void; }' is not assignable to type '{ title: string; handler: () => any; }'. +node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(564,9): error TS2322: Type '({ section: string; title: any; handler: () => void; } | { section: string; title: string; handler: any; })[]' is not assignable to type '{ title: string; handler: () => any; }[]'. + Type '{ section: string; title: any; handler: () => void; } | { section: string; title: string; handler: any; }' is not assignable to type '{ title: string; handler: () => any; }'. Type '{ section: string; title: any; handler: () => void; }' is not assignable to type '{ title: string; handler: () => any; }'. Object literal may only specify known properties, and 'section' does not exist in type '{ title: string; handler: () => any; }'. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(565,16): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(572,16): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(580,16): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(587,16): error TS2555: Expected at least 2 arguments, but got 1. -node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(616,5): error TS2322: Type '({ section: string; title: string; handler: any; } | { section: string; title: any; handler: () => void; })[]' is not assignable to type '{ title: string; handler: () => any; }[]'. +node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(616,5): error TS2322: Type '({ section: string; title: any; handler: () => void; } | { section: string; title: string; handler: any; })[]' is not assignable to type '{ title: string; handler: () => any; }[]'. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(631,2): error TS1131: Property or signature expected. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(646,2): error TS1131: Property or signature expected. node_modules/chrome-devtools-frontend/front_end/components/Linkifier.js(666,22): error TS2551: Property 'LinkHandler' does not exist on type 'typeof Linkifier'. Did you mean '_linkHandlers'? diff --git a/tests/baselines/reference/user/follow-redirects.log b/tests/baselines/reference/user/follow-redirects.log index d1a5afa2e16..4b5959dd0e3 100644 --- a/tests/baselines/reference/user/follow-redirects.log +++ b/tests/baselines/reference/user/follow-redirects.log @@ -1,12 +1,12 @@ Exit Code: 1 Standard output: -node_modules/follow-redirects/index.js(80,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. -node_modules/follow-redirects/index.js(81,10): error TS2339: Property 'abort' does not exist on type 'RedirectableRequest'. -node_modules/follow-redirects/index.js(133,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. -node_modules/follow-redirects/index.js(199,12): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. -node_modules/follow-redirects/index.js(233,35): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. +node_modules/follow-redirects/index.js(86,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(87,10): error TS2339: Property 'abort' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(145,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(211,12): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(245,35): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'. -node_modules/follow-redirects/index.js(246,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. +node_modules/follow-redirects/index.js(258,10): error TS2339: Property 'emit' does not exist on type 'RedirectableRequest'. From 5433cd86850911030df1b81b4dbc9ca324628a63 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 23 Aug 2018 09:18:06 -0700 Subject: [PATCH 37/77] remove Animations from chrome-devtools' user test shim (#26494) It looks like it's successfully merging with the DOM definition now instead. --- tests/cases/user/chrome-devtools-frontend/definitions.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/user/chrome-devtools-frontend/definitions.js b/tests/cases/user/chrome-devtools-frontend/definitions.js index c8bc93d47f1..8e1cf84ec3a 100644 --- a/tests/cases/user/chrome-devtools-frontend/definitions.js +++ b/tests/cases/user/chrome-devtools-frontend/definitions.js @@ -1,6 +1,5 @@ var Accessibility = {}; var AccessibilityTestRunner = {}; -var Animation = {}; var ApplicationTestRunner = {}; var Audits = {}; var Audits2 = {}; From 6ea2278c7a37f0f6eb21f00d0689ba7dd8e61ff4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 23 Aug 2018 11:27:03 -0700 Subject: [PATCH 38/77] Get symbol at location for class expressions/keywords (#26636) * getSymbolAtLocation understands class expressions Previously it did not. * Update baselines --- src/compiler/checker.ts | 1 + tests/cases/fourslash/quickInfoClassKeyword.ts | 8 ++++++++ tests/cases/fourslash/quickInfoInvalidLocations.ts | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/quickInfoClassKeyword.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 269f8b26f0a..0509d53c9b3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27269,6 +27269,7 @@ namespace ts { case SyntaxKind.DefaultKeyword: case SyntaxKind.FunctionKeyword: case SyntaxKind.EqualsGreaterThanToken: + case SyntaxKind.ClassKeyword: return getSymbolOfNode(node.parent); case SyntaxKind.ImportType: return isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal) : undefined; diff --git a/tests/cases/fourslash/quickInfoClassKeyword.ts b/tests/cases/fourslash/quickInfoClassKeyword.ts new file mode 100644 index 00000000000..8a132cf8be9 --- /dev/null +++ b/tests/cases/fourslash/quickInfoClassKeyword.ts @@ -0,0 +1,8 @@ +/// + +////[1].forEach(cla/*1*/ss {}); +////[1].forEach(cla/*2*/ss OK{}); + +verify.quickInfoAt("1", "(local class) (Anonymous class)"); +verify.quickInfoAt("2", "(local class) OK"); + diff --git a/tests/cases/fourslash/quickInfoInvalidLocations.ts b/tests/cases/fourslash/quickInfoInvalidLocations.ts index 396fac67c97..97df6ebd146 100644 --- a/tests/cases/fourslash/quickInfoInvalidLocations.ts +++ b/tests/cases/fourslash/quickInfoInvalidLocations.ts @@ -8,7 +8,7 @@ //// property: string; /////*invalid2*/} //// -////cl/*invalid3*/ass bar imple/*invalid4*/ments IFoo { +////class bar imple/*invalid4*/ments IFoo { //// constructor( /*invalid5*/ ) { //// //// } From f3ceebe55220f11b17cfa606828444214f466f35 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 23 Aug 2018 18:22:07 -0700 Subject: [PATCH 39/77] Fix duplicate completions bugs (#26648) * Fix duplicate completions bugs * Remove old TODO --- src/harness/fourslash.ts | 3 +- src/services/completions.ts | 6 +- .../fourslash/completionEntryForPrimitive.ts | 8 -- .../cases/fourslash/completionListKeywords.ts | 84 +++++++++---------- .../fourslash/completionListPrimitives.ts | 5 -- 5 files changed, 43 insertions(+), 63 deletions(-) delete mode 100644 tests/cases/fourslash/completionEntryForPrimitive.ts delete mode 100644 tests/cases/fourslash/completionListPrimitives.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 7ed3ae2e429..5d1ac5c491f 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -868,8 +868,7 @@ namespace FourSlash { const actualByName = ts.createMap(); for (const entry of actualCompletions.entries) { if (actualByName.has(entry.name)) { - // TODO: GH#23587 - if (entry.name !== "undefined" && entry.name !== "require") this.raiseError(`Duplicate (${actualCompletions.entries.filter(a => a.name === entry.name).length}) completions for ${entry.name}`); + this.raiseError(`Duplicate (${actualCompletions.entries.filter(a => a.name === entry.name).length}) completions for ${entry.name}`); } else { actualByName.set(entry.name, entry); diff --git a/src/services/completions.ts b/src/services/completions.ts index 2b213361418..40986543318 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2116,8 +2116,8 @@ namespace ts.Completions { const kind = stringToToken(entry.name)!; switch (keywordFilter) { case KeywordCompletionFilters.None: - // "undefined" is a global variable, so don't need a keyword completion for it. - return kind !== SyntaxKind.UndefinedKeyword; + return kind === SyntaxKind.AsyncKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind) || kind === SyntaxKind.DeclareKeyword || kind === SyntaxKind.ModuleKeyword + || isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword; case KeywordCompletionFilters.ClassElementKeywords: return isClassMemberCompletionKeyword(kind); case KeywordCompletionFilters.InterfaceElementKeywords: @@ -2152,7 +2152,7 @@ namespace ts.Completions { } function isFunctionLikeBodyKeyword(kind: SyntaxKind) { - return kind === SyntaxKind.AsyncKeyword || !isClassMemberCompletionKeyword(kind); + return kind === SyntaxKind.AsyncKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind); } function keywordForNode(node: Node): SyntaxKind { diff --git a/tests/cases/fourslash/completionEntryForPrimitive.ts b/tests/cases/fourslash/completionEntryForPrimitive.ts deleted file mode 100644 index 9562e879266..00000000000 --- a/tests/cases/fourslash/completionEntryForPrimitive.ts +++ /dev/null @@ -1,8 +0,0 @@ -/// - -////var x = Object.create(/**/ - -goTo.marker(); -verify.not.completionListIsEmpty(); -edit.insert("nu"); -verify.completionListContains("number", undefined, undefined, "keyword"); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListKeywords.ts b/tests/cases/fourslash/completionListKeywords.ts index edfc54bcc7d..8b9a8cc222c 100644 --- a/tests/cases/fourslash/completionListKeywords.ts +++ b/tests/cases/fourslash/completionListKeywords.ts @@ -1,48 +1,42 @@ /// -/////**/ +//// -goTo.marker(); -verify.completionListContains("break"); -verify.completionListContains("case"); -verify.completionListContains("catch"); -verify.completionListContains("class"); -verify.completionListContains("constructor"); -verify.completionListContains("continue"); -verify.completionListContains("debugger"); -verify.completionListContains("declare"); -verify.completionListContains("default"); -verify.completionListContains("delete"); -verify.completionListContains("do"); -verify.completionListContains("else"); -verify.completionListContains("enum"); -verify.completionListContains("export"); -verify.completionListContains("extends"); -verify.completionListContains("false"); -verify.completionListContains("finally"); -verify.completionListContains("for"); -verify.completionListContains("function"); -verify.completionListContains("get"); -verify.completionListContains("if"); -verify.completionListContains("implements"); -verify.completionListContains("import"); -verify.completionListContains("in"); -verify.completionListContains("instanceof"); -verify.completionListContains("interface"); -verify.completionListContains("module"); -verify.completionListContains("new"); -verify.completionListContains("private"); -verify.completionListContains("public"); -verify.completionListContains("return"); -verify.completionListContains("set"); -verify.completionListContains("static"); -verify.completionListContains("super"); -verify.completionListContains("switch"); -verify.completionListContains("this"); -verify.completionListContains("throw"); -verify.completionListContains("true"); -verify.completionListContains("try"); -verify.completionListContains("typeof"); -verify.completionListContains("var"); -verify.completionListContains("while"); -verify.completionListContains("with"); +verify.completions({ + includes: [ + "break", + "case", + "catch", + "class", + "continue", + "debugger", + "declare", + "default", + "delete", + "do", + "else", + "enum", + "export", + "extends", + "false", + "finally", + "for", + "function", + "if", + "instanceof", + "interface", + "module", + "new", + "return", + "super", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "var", + "while", + "with", + ], +}); diff --git a/tests/cases/fourslash/completionListPrimitives.ts b/tests/cases/fourslash/completionListPrimitives.ts deleted file mode 100644 index 7be481f853e..00000000000 --- a/tests/cases/fourslash/completionListPrimitives.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// - -//// - -verify.completions({ includes: ["any", "boolean", "null", "number", "string", "undefined", "void"] }) From 0f04e43cc0b225f1c02d593b21e20977ad0264fb Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 24 Aug 2018 04:10:34 +0000 Subject: [PATCH 40/77] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 20262 ++++++++-------- 1 file changed, 10131 insertions(+), 10131 deletions(-) diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 62489815a38..7fade1f0ae3 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,10132 +1,10132 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - veya - biçiminde olmalıdır. Örneğin, '{0}' veya '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - türü olmalıdır.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()' kullanın.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + veya - biçiminde olmalıdır. Örneğin, '{0}' veya '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + türü olmalıdır.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()' kullanın.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 8ba501926a48c244b13ef3c96c2bf0942628e003 Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Fri, 24 Aug 2018 12:31:53 +0800 Subject: [PATCH 41/77] try get add missing member return type from context (#26250) * try get add missing member return type from context * support contextual type --- src/services/codefixes/helpers.ts | 22 ++++++++----------- .../fourslash/codeFixAddMissingMember10.ts | 16 ++++++++++++++ .../fourslash/codeFixAddMissingMember11.ts | 18 +++++++++++++++ 3 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 tests/cases/fourslash/codeFixAddMissingMember10.ts create mode 100644 tests/cases/fourslash/codeFixAddMissingMember11.ts diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 5b955d24926..eec693bbb69 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -112,27 +112,23 @@ namespace ts.codefix { export function createMethodFromCallExpression( context: CodeFixContextBase, - { typeArguments, arguments: args, parent: parent }: CallExpression, + call: CallExpression, methodName: string, inJs: boolean, makeStatic: boolean, preferences: UserPreferences, body: boolean, ): MethodDeclaration { + const { typeArguments, arguments: args, parent } = call; const checker = context.program.getTypeChecker(); - const types = map(args, - arg => { - let type = checker.getTypeAtLocation(arg); - if (type === undefined) { - return undefined; - } - // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" - type = checker.getBaseTypeOfLiteralType(type); - return checker.typeToTypeNode(type); - }); + const types = map(args, arg => + // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" + checker.typeToTypeNode(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(arg)))); const names = map(args, arg => isIdentifier(arg) ? arg.text : - isPropertyAccessExpression(arg) ? arg.name.text : undefined); + isPropertyAccessExpression(arg) ? arg.name.text : undefined); + const contextualType = checker.getContextualType(call); + const returnType = inJs ? undefined : contextualType && checker.typeToTypeNode(contextualType, call) || createKeywordTypeNode(SyntaxKind.AnyKeyword); return createMethod( /*decorators*/ undefined, /*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined, @@ -142,7 +138,7 @@ namespace ts.codefix { /*typeParameters*/ inJs ? undefined : map(typeArguments, (_, i) => createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)), /*parameters*/ createDummyParameters(args.length, names, types, /*minArgumentCount*/ undefined, inJs), - /*type*/ inJs ? undefined : createKeywordTypeNode(SyntaxKind.AnyKeyword), + /*type*/ returnType, body ? createStubbedMethodBody(preferences) : undefined); } diff --git a/tests/cases/fourslash/codeFixAddMissingMember10.ts b/tests/cases/fourslash/codeFixAddMissingMember10.ts new file mode 100644 index 00000000000..990d86ec49a --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember10.ts @@ -0,0 +1,16 @@ +/// + +//// class C {} +//// const n: number = new C().add(1, 2); + +verify.codeFixAll({ + fixId: "addMissingMember", + fixAllDescription: "Add all missing members", + newFileContent: +`class C { + add(arg0: number, arg1: number): number { + throw new Error("Method not implemented."); + } +} +const n: number = new C().add(1, 2);`, +}); diff --git a/tests/cases/fourslash/codeFixAddMissingMember11.ts b/tests/cases/fourslash/codeFixAddMissingMember11.ts new file mode 100644 index 00000000000..6f68502d4c9 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember11.ts @@ -0,0 +1,18 @@ +/// + +//// class C {} +//// function f(v: number): void { } +//// f(new C().add(1, 2)) + +verify.codeFixAll({ + fixId: "addMissingMember", + fixAllDescription: "Add all missing members", + newFileContent: +`class C { + add(arg0: number, arg1: number): number { + throw new Error("Method not implemented."); + } +} +function f(v: number): void { } +f(new C().add(1, 2))`, +}); From bdb7c351a27e3e42b9c64deb15c617e3332eacc4 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 24 Aug 2018 08:30:21 -0700 Subject: [PATCH 42/77] Update user baselines (#26664) --- .../user/chrome-devtools-frontend.log | 2 - tests/baselines/reference/user/uglify-js.log | 90 +++++++++---------- 2 files changed, 45 insertions(+), 47 deletions(-) diff --git a/tests/baselines/reference/user/chrome-devtools-frontend.log b/tests/baselines/reference/user/chrome-devtools-frontend.log index 31bd0e9d8b2..09fdbcc0b4b 100644 --- a/tests/baselines/reference/user/chrome-devtools-frontend.log +++ b/tests/baselines/reference/user/chrome-devtools-frontend.log @@ -14,8 +14,6 @@ Standard output: ../../../../built/local/lib.es5.d.ts(1346,11): error TS2300: Duplicate identifier 'ArrayLike'. ../../../../built/local/lib.es5.d.ts(1382,6): error TS2300: Duplicate identifier 'Record'. ../../../../node_modules/@types/node/index.d.ts(150,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'module' must be of type '{}', but here has type 'NodeModule'. -definitions.js(3,5): error TS2322: Type '{}' is not assignable to type 'typeof Animation'. - Property 'AnimationGroupPreviewUI' is missing in type '{}'. node_modules/chrome-devtools-frontend/front_end/Runtime.js(43,8): error TS2339: Property '_importScriptPathPrefix' does not exist on type 'Window'. node_modules/chrome-devtools-frontend/front_end/Runtime.js(95,28): error TS2339: Property 'response' does not exist on type 'EventTarget'. node_modules/chrome-devtools-frontend/front_end/Runtime.js(147,37): error TS2339: Property '_importScriptPathPrefix' does not exist on type 'Window'. diff --git a/tests/baselines/reference/user/uglify-js.log b/tests/baselines/reference/user/uglify-js.log index 26ee4837234..0bc48d677a2 100644 --- a/tests/baselines/reference/user/uglify-js.log +++ b/tests/baselines/reference/user/uglify-js.log @@ -5,51 +5,51 @@ node_modules/uglify-js/lib/ast.js(328,33): error TS2339: Property 'transform' do node_modules/uglify-js/lib/ast.js(869,5): error TS2322: Type '{ _visit: (node: any, descend: any) => any; parent: (n: any) => any; push: typeof push; pop: typeof pop; self: () => any; find_parent: (type: any) => any; has_directive: (type: any) => any; loopcontrol_target: (node: any) => any; in_boolean_context: () => boolean | undefined; }' is not assignable to type 'TreeWalker'. Object literal may only specify known properties, but '_visit' does not exist in type 'TreeWalker'. Did you mean to write 'visit'? node_modules/uglify-js/lib/compress.js(167,27): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(501,26): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(818,18): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1073,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(1087,51): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'true | ((node: any) => any)' has no compatible call signatures. -node_modules/uglify-js/lib/compress.js(1151,53): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(1193,112): error TS2532: Object is possibly 'undefined'. -node_modules/uglify-js/lib/compress.js(1194,29): error TS2532: Object is possibly 'undefined'. -node_modules/uglify-js/lib/compress.js(1203,87): error TS2322: Type 'false' is not assignable to type 'number'. -node_modules/uglify-js/lib/compress.js(1211,29): error TS2322: Type 'false' is not assignable to type 'never'. -node_modules/uglify-js/lib/compress.js(1317,38): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1412,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(1508,27): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1540,26): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1951,44): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(2137,19): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3193,23): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3206,33): error TS2322: Type '"f"' is not assignable to type 'boolean'. -node_modules/uglify-js/lib/compress.js(3345,18): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3400,14): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3417,29): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(3442,62): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3669,23): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3690,24): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(3700,28): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(3859,21): error TS2403: Subsequent variable declarations must have the same type. Variable 'defs' must be of type 'Dictionary & { set: (key: any, val: any) => any; add: (key: any, val: any) => any; get: (key: any) => any; del: (key: any) => any; has: (key: any) => boolean; each: (f: any) => void; size: () => any; map: (f: any) => any[]; clone: () => Dictionary & any; toObject: () => any; }', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(3911,17): error TS2447: The '|=' operator is not allowed for boolean types. Consider using '||' instead. -node_modules/uglify-js/lib/compress.js(3967,30): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4076,18): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4375,17): error TS2403: Subsequent variable declarations must have the same type. Variable 'body' must be of type 'any[]', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(4459,22): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4809,30): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4816,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'code' must be of type 'string', but here has type '{ get: () => string; toString: () => string; indent: () => void; indentation: () => number; current_width: () => number; should_break: () => boolean; has_parens: () => boolean; newline: () => void; print: (str: any) => void; ... 24 more ...; parent: (n: any) => any; }'. -node_modules/uglify-js/lib/compress.js(4820,36): error TS2532: Object is possibly 'undefined'. -node_modules/uglify-js/lib/compress.js(4825,41): error TS2339: Property 'get' does not exist on type 'string'. -node_modules/uglify-js/lib/compress.js(5312,18): error TS2454: Variable 'is_strict_comparison' is used before being assigned. -node_modules/uglify-js/lib/compress.js(5747,25): error TS2367: This condition will always return 'false' since the types 'boolean' and '"f"' have no overlap. -node_modules/uglify-js/lib/compress.js(5775,32): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(5835,24): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(5907,24): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(5913,26): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(6306,43): error TS2454: Variable 'property' is used before being assigned. -node_modules/uglify-js/lib/compress.js(6321,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(6324,46): error TS2339: Property 'has_side_effects' does not exist on type 'number'. -node_modules/uglify-js/lib/compress.js(6330,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(6358,19): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(500,26): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(817,18): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1072,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(1086,51): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'true | ((node: any) => any)' has no compatible call signatures. +node_modules/uglify-js/lib/compress.js(1150,53): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(1192,112): error TS2532: Object is possibly 'undefined'. +node_modules/uglify-js/lib/compress.js(1193,29): error TS2532: Object is possibly 'undefined'. +node_modules/uglify-js/lib/compress.js(1202,87): error TS2322: Type 'false' is not assignable to type 'number'. +node_modules/uglify-js/lib/compress.js(1210,29): error TS2322: Type 'false' is not assignable to type 'never'. +node_modules/uglify-js/lib/compress.js(1316,38): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1411,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(1507,27): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1539,26): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1963,44): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(2149,19): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3205,23): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3218,33): error TS2322: Type '"f"' is not assignable to type 'boolean'. +node_modules/uglify-js/lib/compress.js(3358,18): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3413,14): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3430,29): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(3455,62): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3681,23): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3702,24): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(3712,28): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(3871,21): error TS2403: Subsequent variable declarations must have the same type. Variable 'defs' must be of type 'Dictionary & { set: (key: any, val: any) => any; add: (key: any, val: any) => any; get: (key: any) => any; del: (key: any) => any; has: (key: any) => boolean; each: (f: any) => void; size: () => any; map: (f: any) => any[]; clone: () => Dictionary & any; toObject: () => any; }', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(3923,17): error TS2447: The '|=' operator is not allowed for boolean types. Consider using '||' instead. +node_modules/uglify-js/lib/compress.js(3979,30): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(4088,18): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(4387,17): error TS2403: Subsequent variable declarations must have the same type. Variable 'body' must be of type 'any[]', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(4471,22): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(4821,30): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(4828,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'code' must be of type 'string', but here has type '{ get: () => string; toString: () => string; indent: () => void; indentation: () => number; current_width: () => number; should_break: () => boolean; has_parens: () => boolean; newline: () => void; print: (str: any) => void; ... 24 more ...; parent: (n: any) => any; }'. +node_modules/uglify-js/lib/compress.js(4832,36): error TS2532: Object is possibly 'undefined'. +node_modules/uglify-js/lib/compress.js(4837,41): error TS2339: Property 'get' does not exist on type 'string'. +node_modules/uglify-js/lib/compress.js(5324,18): error TS2454: Variable 'is_strict_comparison' is used before being assigned. +node_modules/uglify-js/lib/compress.js(5759,25): error TS2367: This condition will always return 'false' since the types 'boolean' and '"f"' have no overlap. +node_modules/uglify-js/lib/compress.js(5787,32): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(5847,24): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(5919,24): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(5925,26): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(6318,43): error TS2454: Variable 'property' is used before being assigned. +node_modules/uglify-js/lib/compress.js(6333,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(6336,46): error TS2339: Property 'has_side_effects' does not exist on type 'number'. +node_modules/uglify-js/lib/compress.js(6342,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(6370,19): error TS2554: Expected 0 arguments, but got 1. node_modules/uglify-js/lib/minify.js(170,75): error TS2339: Property 'compress' does not exist on type 'Compressor'. node_modules/uglify-js/lib/mozilla-ast.js(566,18): error TS2554: Expected 0 arguments, but got 1. node_modules/uglify-js/lib/output.js(246,9): error TS2554: Expected 0 arguments, but got 2. From 0043ba16b17f82c8e7acf87adabd6e6ad540b147 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 24 Aug 2018 10:30:39 -0700 Subject: [PATCH 43/77] Allow weak type detection for intersection sources (#26668) Previously, intersections were only allowed as targets, but this was just an artifact of the original implementation, which operated inside the structural part of isRelatedTo. Removing this restriction catches subtle bugs in React user code, where a function named `create` returns a mapped type whose types are all branded numbers. The display of these properties, for some original type `T`, is not `number & { __ }` but the much-less-obvious `RegisteredStyle`. --- src/compiler/checker.ts | 2 +- .../intersectionAsWeakTypeSource.errors.txt | 30 ++++++++ .../reference/intersectionAsWeakTypeSource.js | 26 +++++++ .../intersectionAsWeakTypeSource.symbols | 72 +++++++++++++++++++ .../intersectionAsWeakTypeSource.types | 60 ++++++++++++++++ .../intersectionAsWeakTypeSource.ts | 18 +++++ 6 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/intersectionAsWeakTypeSource.errors.txt create mode 100644 tests/baselines/reference/intersectionAsWeakTypeSource.js create mode 100644 tests/baselines/reference/intersectionAsWeakTypeSource.symbols create mode 100644 tests/baselines/reference/intersectionAsWeakTypeSource.types create mode 100644 tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0509d53c9b3..50cbb6cb064 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11178,7 +11178,7 @@ namespace ts { } if (relation !== comparableRelation && - !(source.flags & TypeFlags.UnionOrIntersection) && + !(source.flags & TypeFlags.Union) && !(target.flags & TypeFlags.Union) && !isIntersectionConstituent && source !== globalObjectType && diff --git a/tests/baselines/reference/intersectionAsWeakTypeSource.errors.txt b/tests/baselines/reference/intersectionAsWeakTypeSource.errors.txt new file mode 100644 index 00000000000..69da07115ad --- /dev/null +++ b/tests/baselines/reference/intersectionAsWeakTypeSource.errors.txt @@ -0,0 +1,30 @@ +tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts(8,7): error TS2559: Type 'XY' has no properties in common with type 'Z'. +tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts(18,7): error TS2322: Type 'Brand<{ view: number; styleMedia: string; }>' is not assignable to type 'ViewStyle'. + Property 'view' is missing in type 'Number & { __brand: { view: number; styleMedia: string; }; }'. + + +==== tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts (2 errors) ==== + interface X { x: string } + interface Y { y: number } + interface Z { z?: boolean } + + type XY = X & Y; + const xy: XY = {x: 'x', y: 10}; + + const z1: Z = xy; // error, {xy} doesn't overlap with {z} + ~~ +!!! error TS2559: Type 'XY' has no properties in common with type 'Z'. + + + interface ViewStyle { + view: number + styleMedia: string + } + type Brand = number & { __brand: T } + declare function create(styles: T): { [P in keyof T]: Brand }; + const wrapped = create({ first: { view: 0, styleMedia: "???" } }); + const vs: ViewStyle = wrapped.first // error, first is a branded number + ~~ +!!! error TS2322: Type 'Brand<{ view: number; styleMedia: string; }>' is not assignable to type 'ViewStyle'. +!!! error TS2322: Property 'view' is missing in type 'Number & { __brand: { view: number; styleMedia: string; }; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/intersectionAsWeakTypeSource.js b/tests/baselines/reference/intersectionAsWeakTypeSource.js new file mode 100644 index 00000000000..fefb6f79c2b --- /dev/null +++ b/tests/baselines/reference/intersectionAsWeakTypeSource.js @@ -0,0 +1,26 @@ +//// [intersectionAsWeakTypeSource.ts] +interface X { x: string } +interface Y { y: number } +interface Z { z?: boolean } + +type XY = X & Y; +const xy: XY = {x: 'x', y: 10}; + +const z1: Z = xy; // error, {xy} doesn't overlap with {z} + + +interface ViewStyle { + view: number + styleMedia: string +} +type Brand = number & { __brand: T } +declare function create(styles: T): { [P in keyof T]: Brand }; +const wrapped = create({ first: { view: 0, styleMedia: "???" } }); +const vs: ViewStyle = wrapped.first // error, first is a branded number + + +//// [intersectionAsWeakTypeSource.js] +var xy = { x: 'x', y: 10 }; +var z1 = xy; // error, {xy} doesn't overlap with {z} +var wrapped = create({ first: { view: 0, styleMedia: "???" } }); +var vs = wrapped.first; // error, first is a branded number diff --git a/tests/baselines/reference/intersectionAsWeakTypeSource.symbols b/tests/baselines/reference/intersectionAsWeakTypeSource.symbols new file mode 100644 index 00000000000..78c35abc286 --- /dev/null +++ b/tests/baselines/reference/intersectionAsWeakTypeSource.symbols @@ -0,0 +1,72 @@ +=== tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts === +interface X { x: string } +>X : Symbol(X, Decl(intersectionAsWeakTypeSource.ts, 0, 0)) +>x : Symbol(X.x, Decl(intersectionAsWeakTypeSource.ts, 0, 13)) + +interface Y { y: number } +>Y : Symbol(Y, Decl(intersectionAsWeakTypeSource.ts, 0, 25)) +>y : Symbol(Y.y, Decl(intersectionAsWeakTypeSource.ts, 1, 13)) + +interface Z { z?: boolean } +>Z : Symbol(Z, Decl(intersectionAsWeakTypeSource.ts, 1, 25)) +>z : Symbol(Z.z, Decl(intersectionAsWeakTypeSource.ts, 2, 13)) + +type XY = X & Y; +>XY : Symbol(XY, Decl(intersectionAsWeakTypeSource.ts, 2, 27)) +>X : Symbol(X, Decl(intersectionAsWeakTypeSource.ts, 0, 0)) +>Y : Symbol(Y, Decl(intersectionAsWeakTypeSource.ts, 0, 25)) + +const xy: XY = {x: 'x', y: 10}; +>xy : Symbol(xy, Decl(intersectionAsWeakTypeSource.ts, 5, 5)) +>XY : Symbol(XY, Decl(intersectionAsWeakTypeSource.ts, 2, 27)) +>x : Symbol(x, Decl(intersectionAsWeakTypeSource.ts, 5, 16)) +>y : Symbol(y, Decl(intersectionAsWeakTypeSource.ts, 5, 23)) + +const z1: Z = xy; // error, {xy} doesn't overlap with {z} +>z1 : Symbol(z1, Decl(intersectionAsWeakTypeSource.ts, 7, 5)) +>Z : Symbol(Z, Decl(intersectionAsWeakTypeSource.ts, 1, 25)) +>xy : Symbol(xy, Decl(intersectionAsWeakTypeSource.ts, 5, 5)) + + +interface ViewStyle { +>ViewStyle : Symbol(ViewStyle, Decl(intersectionAsWeakTypeSource.ts, 7, 17)) + + view: number +>view : Symbol(ViewStyle.view, Decl(intersectionAsWeakTypeSource.ts, 10, 21)) + + styleMedia: string +>styleMedia : Symbol(ViewStyle.styleMedia, Decl(intersectionAsWeakTypeSource.ts, 11, 16)) +} +type Brand = number & { __brand: T } +>Brand : Symbol(Brand, Decl(intersectionAsWeakTypeSource.ts, 13, 1)) +>T : Symbol(T, Decl(intersectionAsWeakTypeSource.ts, 14, 11)) +>__brand : Symbol(__brand, Decl(intersectionAsWeakTypeSource.ts, 14, 26)) +>T : Symbol(T, Decl(intersectionAsWeakTypeSource.ts, 14, 11)) + +declare function create(styles: T): { [P in keyof T]: Brand }; +>create : Symbol(create, Decl(intersectionAsWeakTypeSource.ts, 14, 39)) +>T : Symbol(T, Decl(intersectionAsWeakTypeSource.ts, 15, 24)) +>s : Symbol(s, Decl(intersectionAsWeakTypeSource.ts, 15, 37)) +>ViewStyle : Symbol(ViewStyle, Decl(intersectionAsWeakTypeSource.ts, 7, 17)) +>styles : Symbol(styles, Decl(intersectionAsWeakTypeSource.ts, 15, 62)) +>T : Symbol(T, Decl(intersectionAsWeakTypeSource.ts, 15, 24)) +>P : Symbol(P, Decl(intersectionAsWeakTypeSource.ts, 15, 77)) +>T : Symbol(T, Decl(intersectionAsWeakTypeSource.ts, 15, 24)) +>Brand : Symbol(Brand, Decl(intersectionAsWeakTypeSource.ts, 13, 1)) +>T : Symbol(T, Decl(intersectionAsWeakTypeSource.ts, 15, 24)) +>P : Symbol(P, Decl(intersectionAsWeakTypeSource.ts, 15, 77)) + +const wrapped = create({ first: { view: 0, styleMedia: "???" } }); +>wrapped : Symbol(wrapped, Decl(intersectionAsWeakTypeSource.ts, 16, 5)) +>create : Symbol(create, Decl(intersectionAsWeakTypeSource.ts, 14, 39)) +>first : Symbol(first, Decl(intersectionAsWeakTypeSource.ts, 16, 24)) +>view : Symbol(view, Decl(intersectionAsWeakTypeSource.ts, 16, 33)) +>styleMedia : Symbol(styleMedia, Decl(intersectionAsWeakTypeSource.ts, 16, 42)) + +const vs: ViewStyle = wrapped.first // error, first is a branded number +>vs : Symbol(vs, Decl(intersectionAsWeakTypeSource.ts, 17, 5)) +>ViewStyle : Symbol(ViewStyle, Decl(intersectionAsWeakTypeSource.ts, 7, 17)) +>wrapped.first : Symbol(first, Decl(intersectionAsWeakTypeSource.ts, 16, 24)) +>wrapped : Symbol(wrapped, Decl(intersectionAsWeakTypeSource.ts, 16, 5)) +>first : Symbol(first, Decl(intersectionAsWeakTypeSource.ts, 16, 24)) + diff --git a/tests/baselines/reference/intersectionAsWeakTypeSource.types b/tests/baselines/reference/intersectionAsWeakTypeSource.types new file mode 100644 index 00000000000..2362f7c92c1 --- /dev/null +++ b/tests/baselines/reference/intersectionAsWeakTypeSource.types @@ -0,0 +1,60 @@ +=== tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts === +interface X { x: string } +>x : string + +interface Y { y: number } +>y : number + +interface Z { z?: boolean } +>z : boolean + +type XY = X & Y; +>XY : XY + +const xy: XY = {x: 'x', y: 10}; +>xy : XY +>{x: 'x', y: 10} : { x: string; y: number; } +>x : string +>'x' : "x" +>y : number +>10 : 10 + +const z1: Z = xy; // error, {xy} doesn't overlap with {z} +>z1 : Z +>xy : XY + + +interface ViewStyle { + view: number +>view : number + + styleMedia: string +>styleMedia : string +} +type Brand = number & { __brand: T } +>Brand : Brand +>__brand : T + +declare function create(styles: T): { [P in keyof T]: Brand }; +>create : (styles: T) => { [P in keyof T]: Brand; } +>s : string +>styles : T + +const wrapped = create({ first: { view: 0, styleMedia: "???" } }); +>wrapped : { first: Brand<{ view: number; styleMedia: string; }>; } +>create({ first: { view: 0, styleMedia: "???" } }) : { first: Brand<{ view: number; styleMedia: string; }>; } +>create : (styles: T) => { [P in keyof T]: Brand; } +>{ first: { view: 0, styleMedia: "???" } } : { first: { view: number; styleMedia: string; }; } +>first : { view: number; styleMedia: string; } +>{ view: 0, styleMedia: "???" } : { view: number; styleMedia: string; } +>view : number +>0 : 0 +>styleMedia : string +>"???" : "???" + +const vs: ViewStyle = wrapped.first // error, first is a branded number +>vs : ViewStyle +>wrapped.first : Brand<{ view: number; styleMedia: string; }> +>wrapped : { first: Brand<{ view: number; styleMedia: string; }>; } +>first : Brand<{ view: number; styleMedia: string; }> + diff --git a/tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts b/tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts new file mode 100644 index 00000000000..1ebe78b05f5 --- /dev/null +++ b/tests/cases/conformance/types/intersection/intersectionAsWeakTypeSource.ts @@ -0,0 +1,18 @@ +interface X { x: string } +interface Y { y: number } +interface Z { z?: boolean } + +type XY = X & Y; +const xy: XY = {x: 'x', y: 10}; + +const z1: Z = xy; // error, {xy} doesn't overlap with {z} + + +interface ViewStyle { + view: number + styleMedia: string +} +type Brand = number & { __brand: T } +declare function create(styles: T): { [P in keyof T]: Brand }; +const wrapped = create({ first: { view: 0, styleMedia: "???" } }); +const vs: ViewStyle = wrapped.first // error, first is a branded number From 9c551a107a5463de6030b7295b17d624f368e267 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 16:09:08 -0700 Subject: [PATCH 44/77] Ignore parameters when inferring from return type only signature --- src/compiler/checker.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce116ffac23..f070d71bb16 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13549,14 +13549,16 @@ namespace ts { const sourceLen = sourceSignatures.length; const targetLen = targetSignatures.length; const len = sourceLen < targetLen ? sourceLen : targetLen; + const skipParameters = !!(source.flags & TypeFlags.ContainsAnyFunctionType); for (let i = 0; i < len; i++) { - inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getBaseSignature(targetSignatures[targetLen - len + i])); + inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getBaseSignature(targetSignatures[targetLen - len + i]), skipParameters); } } - function inferFromSignature(source: Signature, target: Signature) { - forEachMatchingParameterType(source, target, inferFromContravariantTypes); - + function inferFromSignature(source: Signature, target: Signature, skipParameters: boolean) { + if (!skipParameters) { + forEachMatchingParameterType(source, target, inferFromContravariantTypes); + } const sourceTypePredicate = getTypePredicateOfSignature(source); const targetTypePredicate = getTypePredicateOfSignature(target); if (sourceTypePredicate && targetTypePredicate && sourceTypePredicate.kind === targetTypePredicate.kind) { @@ -20576,8 +20578,10 @@ namespace ts { return links.contextFreeType; } const returnType = getReturnTypeFromBody(node, checkMode); - const singleReturnSignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); - return links.contextFreeType = createAnonymousType(node.symbol, emptySymbols, [singleReturnSignature], emptyArray, undefined, undefined); + const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined); + returnOnlyType.flags |= TypeFlags.ContainsAnyFunctionType; + return links.contextFreeType = returnOnlyType; } return anyFunctionType; } From 09bc7505a742b3ffd8bbf01ec50af2bdd8bef551 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 16:09:18 -0700 Subject: [PATCH 45/77] Add regression test --- .../badInferenceLowerPriorityThanGoodInference.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts b/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts index 59dfb3ff447..8092e909df6 100644 --- a/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts +++ b/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts @@ -1,3 +1,5 @@ +// Repro from #13118 + interface Foo { a: A; b: (x: A) => void; @@ -10,4 +12,11 @@ const result = canYouInferThis(() => ({ b: x => { } })) -result.BLAH; \ No newline at end of file +result.BLAH; + +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} + +goofus((a: string) => ({ dog() { return a; } })); +goofus((a: string) => ({ dog: function() { return a; } })); From ed97443ab6581582bb1dcab5b15cc5f20c312051 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 16:09:25 -0700 Subject: [PATCH 46/77] Accept new baselines --- ...InferenceLowerPriorityThanGoodInference.js | 17 ++++- ...enceLowerPriorityThanGoodInference.symbols | 63 +++++++++++++------ ...erenceLowerPriorityThanGoodInference.types | 30 +++++++++ 3 files changed, 89 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js index de98d754bb0..a089d4eb935 100644 --- a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js +++ b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js @@ -1,4 +1,6 @@ //// [badInferenceLowerPriorityThanGoodInference.ts] +// Repro from #13118 + interface Foo { a: A; b: (x: A) => void; @@ -11,11 +13,24 @@ const result = canYouInferThis(() => ({ b: x => { } })) -result.BLAH; +result.BLAH; + +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} + +goofus((a: string) => ({ dog() { return a; } })); +goofus((a: string) => ({ dog: function() { return a; } })); + //// [badInferenceLowerPriorityThanGoodInference.js] +// Repro from #13118 var result = canYouInferThis(function () { return ({ a: { BLAH: 33 }, b: function (x) { } }); }); result.BLAH; +// Repro from #26629 +function goofus(f) { } +goofus(function (a) { return ({ dog: function () { return a; } }); }); +goofus(function (a) { return ({ dog: function () { return a; } }); }); diff --git a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols index d03ac3b800a..6eb97aef3ba 100644 --- a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols +++ b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols @@ -1,42 +1,65 @@ === tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts === +// Repro from #13118 + interface Foo { >Foo : Symbol(Foo, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 0)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 14)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 14)) a: A; ->a : Symbol(Foo.a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 18)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 14)) +>a : Symbol(Foo.a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 18)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 14)) b: (x: A) => void; ->b : Symbol(Foo.b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 1, 9)) ->x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 8)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 14)) +>b : Symbol(Foo.b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 3, 9)) +>x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 4, 8)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 14)) } declare function canYouInferThis(fn: () => Foo): A; ->canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 3, 1)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 33)) ->fn : Symbol(fn, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 36)) +>canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 1)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 33)) +>fn : Symbol(fn, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 36)) >Foo : Symbol(Foo, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 0)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 33)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 33)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 33)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 33)) const result = canYouInferThis(() => ({ ->result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 5)) ->canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 3, 1)) +>result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 5)) +>canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 1)) a: { BLAH: 33 }, ->a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 39)) ->BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 8)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 39)) +>BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 8)) b: x => { } ->b : Symbol(b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 20)) ->x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 6)) +>b : Symbol(b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 20)) +>x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 11, 6)) })) result.BLAH; ->result.BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 8)) ->result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 5)) ->BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 8)) +>result.BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 8)) +>result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 5)) +>BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 8)) + +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} +>goofus : Symbol(goofus, Decl(badInferenceLowerPriorityThanGoodInference.ts, 14, 12)) +>ARGS : Symbol(ARGS, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 17)) +>f : Symbol(f, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 38)) +>args : Symbol(args, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 42)) +>ARGS : Symbol(ARGS, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 17)) + +goofus((a: string) => ({ dog() { return a; } })); +>goofus : Symbol(goofus, Decl(badInferenceLowerPriorityThanGoodInference.ts, 14, 12)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 20, 8)) +>dog : Symbol(dog, Decl(badInferenceLowerPriorityThanGoodInference.ts, 20, 24)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 20, 8)) + +goofus((a: string) => ({ dog: function() { return a; } })); +>goofus : Symbol(goofus, Decl(badInferenceLowerPriorityThanGoodInference.ts, 14, 12)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 21, 8)) +>dog : Symbol(dog, Decl(badInferenceLowerPriorityThanGoodInference.ts, 21, 24)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 21, 8)) diff --git a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types index 8b0ab548fdd..0847f9c29d8 100644 --- a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types +++ b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types @@ -1,4 +1,6 @@ === tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts === +// Repro from #13118 + interface Foo { a: A; >a : A @@ -38,3 +40,31 @@ result.BLAH; >result : { BLAH: number; } >BLAH : number +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} +>goofus : (f: (...args: ARGS) => any) => void +>f : (...args: ARGS) => any +>args : ARGS + +goofus((a: string) => ({ dog() { return a; } })); +>goofus((a: string) => ({ dog() { return a; } })) : void +>goofus : (f: (...args: ARGS) => any) => void +>(a: string) => ({ dog() { return a; } }) : (a: string) => { dog(): string; } +>a : string +>({ dog() { return a; } }) : { dog(): string; } +>{ dog() { return a; } } : { dog(): string; } +>dog : () => string +>a : string + +goofus((a: string) => ({ dog: function() { return a; } })); +>goofus((a: string) => ({ dog: function() { return a; } })) : void +>goofus : (f: (...args: ARGS) => any) => void +>(a: string) => ({ dog: function() { return a; } }) : (a: string) => { dog: () => string; } +>a : string +>({ dog: function() { return a; } }) : { dog: () => string; } +>{ dog: function() { return a; } } : { dog: () => string; } +>dog : () => string +>function() { return a; } : () => string +>a : string + From e852627df02f9403f6a77ad30334678c4efacd1a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 18:25:02 -0700 Subject: [PATCH 47/77] Add early out for type assertions in getTypeOfExpression --- src/compiler/checker.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce116ffac23..4b15c471c6a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21698,15 +21698,19 @@ namespace ts { * to cache the result. */ function getTypeOfExpression(node: Expression, cache?: boolean) { + const expr = skipParentheses(node); // Optimize for the common case of a call to a function with a single non-generic call // signature where we can just fetch the return type without checking the arguments. - if (node.kind === SyntaxKind.CallExpression && (node).expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(node)) { - const funcType = checkNonNullExpression((node).expression); + if (expr.kind === SyntaxKind.CallExpression && (expr).expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) { + const funcType = checkNonNullExpression((expr).expression); const signature = getSingleCallSignature(funcType); if (signature && !signature.typeParameters) { return getReturnTypeOfSignature(signature); } } + else if (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) { + return getTypeFromTypeNode((expr).type); + } // Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions // should have a parameter that indicates whether full error checking is required such that // we can perform the optimizations locally. From 0c759b819488a44a53fbc33c24415d6e7f921c8f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 18:25:14 -0700 Subject: [PATCH 48/77] Add regression test --- .../controlFlowSelfReferentialLoop.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/cases/compiler/controlFlowSelfReferentialLoop.ts b/tests/cases/compiler/controlFlowSelfReferentialLoop.ts index 361d3a557b4..0be51effc80 100644 --- a/tests/cases/compiler/controlFlowSelfReferentialLoop.ts +++ b/tests/cases/compiler/controlFlowSelfReferentialLoop.ts @@ -99,4 +99,23 @@ function md5(string:string): void { b=II(b,c,d,a,x[k+9], S44,0xEB86D391); } } -export default md5; \ No newline at end of file +export default md5; + +// Repro from #26655 + +interface DataShape { + message: { id: string } +} + +function getObject(id: string | number) { + return {} as any +} + +;(() => { + let id: string | number = 'a' + while (1) { + const data = getObject(id) as DataShape + const message = data.message + id = message.id + } +})() From a1c373c3c72a3010917ad41832f13463d92a60cf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 18:25:20 -0700 Subject: [PATCH 49/77] Accept new baselines --- .../controlFlowSelfReferentialLoop.errors.txt | 22 +++++++- .../controlFlowSelfReferentialLoop.js | 34 ++++++++++++- .../controlFlowSelfReferentialLoop.symbols | 42 +++++++++++++++ .../controlFlowSelfReferentialLoop.types | 51 +++++++++++++++++++ 4 files changed, 147 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/controlFlowSelfReferentialLoop.errors.txt b/tests/baselines/reference/controlFlowSelfReferentialLoop.errors.txt index 69f670359af..b36d991f114 100644 --- a/tests/baselines/reference/controlFlowSelfReferentialLoop.errors.txt +++ b/tests/baselines/reference/controlFlowSelfReferentialLoop.errors.txt @@ -184,4 +184,24 @@ tests/cases/compiler/controlFlowSelfReferentialLoop.ts(17,29): error TS7006: Par b=II(b,c,d,a,x[k+9], S44,0xEB86D391); } } - export default md5; \ No newline at end of file + export default md5; + + // Repro from #26655 + + interface DataShape { + message: { id: string } + } + + function getObject(id: string | number) { + return {} as any + } + + ;(() => { + let id: string | number = 'a' + while (1) { + const data = getObject(id) as DataShape + const message = data.message + id = message.id + } + })() + \ No newline at end of file diff --git a/tests/baselines/reference/controlFlowSelfReferentialLoop.js b/tests/baselines/reference/controlFlowSelfReferentialLoop.js index 4781f2776fb..a6efecb7e2a 100644 --- a/tests/baselines/reference/controlFlowSelfReferentialLoop.js +++ b/tests/baselines/reference/controlFlowSelfReferentialLoop.js @@ -98,7 +98,27 @@ function md5(string:string): void { b=II(b,c,d,a,x[k+9], S44,0xEB86D391); } } -export default md5; +export default md5; + +// Repro from #26655 + +interface DataShape { + message: { id: string } +} + +function getObject(id: string | number) { + return {} as any +} + +;(() => { + let id: string | number = 'a' + while (1) { + const data = getObject(id) as DataShape + const message = data.message + id = message.id + } +})() + //// [controlFlowSelfReferentialLoop.js] "use strict"; @@ -204,3 +224,15 @@ function md5(string) { } } exports["default"] = md5; +function getObject(id) { + return {}; +} +; +(function () { + var id = 'a'; + while (1) { + var data = getObject(id); + var message = data.message; + id = message.id; + } +})(); diff --git a/tests/baselines/reference/controlFlowSelfReferentialLoop.symbols b/tests/baselines/reference/controlFlowSelfReferentialLoop.symbols index ac857a13f43..6247d792c19 100644 --- a/tests/baselines/reference/controlFlowSelfReferentialLoop.symbols +++ b/tests/baselines/reference/controlFlowSelfReferentialLoop.symbols @@ -831,3 +831,45 @@ function md5(string:string): void { export default md5; >md5 : Symbol(md5, Decl(controlFlowSelfReferentialLoop.ts, 0, 0)) +// Repro from #26655 + +interface DataShape { +>DataShape : Symbol(DataShape, Decl(controlFlowSelfReferentialLoop.ts, 99, 19)) + + message: { id: string } +>message : Symbol(DataShape.message, Decl(controlFlowSelfReferentialLoop.ts, 103, 21)) +>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 104, 12)) +} + +function getObject(id: string | number) { +>getObject : Symbol(getObject, Decl(controlFlowSelfReferentialLoop.ts, 105, 1)) +>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 107, 19)) + + return {} as any +} + +;(() => { + let id: string | number = 'a' +>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 112, 5)) + + while (1) { + const data = getObject(id) as DataShape +>data : Symbol(data, Decl(controlFlowSelfReferentialLoop.ts, 114, 9)) +>getObject : Symbol(getObject, Decl(controlFlowSelfReferentialLoop.ts, 105, 1)) +>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 112, 5)) +>DataShape : Symbol(DataShape, Decl(controlFlowSelfReferentialLoop.ts, 99, 19)) + + const message = data.message +>message : Symbol(message, Decl(controlFlowSelfReferentialLoop.ts, 115, 9)) +>data.message : Symbol(DataShape.message, Decl(controlFlowSelfReferentialLoop.ts, 103, 21)) +>data : Symbol(data, Decl(controlFlowSelfReferentialLoop.ts, 114, 9)) +>message : Symbol(DataShape.message, Decl(controlFlowSelfReferentialLoop.ts, 103, 21)) + + id = message.id +>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 112, 5)) +>message.id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 104, 12)) +>message : Symbol(message, Decl(controlFlowSelfReferentialLoop.ts, 115, 9)) +>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 104, 12)) + } +})() + diff --git a/tests/baselines/reference/controlFlowSelfReferentialLoop.types b/tests/baselines/reference/controlFlowSelfReferentialLoop.types index 202286e2eb5..6dba558bd71 100644 --- a/tests/baselines/reference/controlFlowSelfReferentialLoop.types +++ b/tests/baselines/reference/controlFlowSelfReferentialLoop.types @@ -1260,3 +1260,54 @@ function md5(string:string): void { export default md5; >md5 : (string: string) => void +// Repro from #26655 + +interface DataShape { + message: { id: string } +>message : { id: string; } +>id : string +} + +function getObject(id: string | number) { +>getObject : (id: string | number) => any +>id : string | number + + return {} as any +>{} as any : any +>{} : {} +} + +;(() => { +>(() => { let id: string | number = 'a' while (1) { const data = getObject(id) as DataShape const message = data.message id = message.id }})() : void +>(() => { let id: string | number = 'a' while (1) { const data = getObject(id) as DataShape const message = data.message id = message.id }}) : () => void +>() => { let id: string | number = 'a' while (1) { const data = getObject(id) as DataShape const message = data.message id = message.id }} : () => void + + let id: string | number = 'a' +>id : string | number +>'a' : "a" + + while (1) { +>1 : 1 + + const data = getObject(id) as DataShape +>data : DataShape +>getObject(id) as DataShape : DataShape +>getObject(id) : any +>getObject : (id: string | number) => any +>id : string + + const message = data.message +>message : { id: string; } +>data.message : { id: string; } +>data : DataShape +>message : { id: string; } + + id = message.id +>id = message.id : string +>id : string | number +>message.id : string +>message : { id: string; } +>id : string + } +})() + From 61f6d0380acd3714a633e8c7777235e8f8f9a38c Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 27 Aug 2018 08:54:02 -0700 Subject: [PATCH 50/77] Update user baselines (#26687) --- tests/baselines/reference/user/jimp.log | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/user/jimp.log b/tests/baselines/reference/user/jimp.log index 08123f69c4b..9757da0670e 100644 --- a/tests/baselines/reference/user/jimp.log +++ b/tests/baselines/reference/user/jimp.log @@ -1,6 +1,8 @@ Exit Code: 1 Standard output: -node_modules/jimp/jimp.d.ts(499,16): error TS7010: 'appendConstructorOption', which lacks return-type annotation, implicitly has an 'any' return type. +node_modules/jimp/jimp.d.ts(495,16): error TS7010: 'appendConstructorOption', which lacks return-type annotation, implicitly has an 'any' return type. +node_modules/jimp/jimp.d.ts(536,16): error TS7010: 'measureText', which lacks return-type annotation, implicitly has an 'any' return type. +node_modules/jimp/jimp.d.ts(537,16): error TS7010: 'measureTextHeight', which lacks return-type annotation, implicitly has an 'any' return type. From e411381266c8640526148e30db4233d4f966cb54 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 27 Aug 2018 09:38:52 -0700 Subject: [PATCH 51/77] Fix bug: Don't let empty signature documentation override other documentation (#26638) --- src/services/symbolDisplay.ts | 3 +- tests/cases/fourslash/commentsClass.ts | 12 +++--- .../cases/fourslash/commentsCommentParsing.ts | 2 +- .../fourslash/commentsExternalModules.ts | 4 +- .../fourslash/commentsImportDeclaration.ts | 2 +- tests/cases/fourslash/commentsInheritance.ts | 38 +++++++++---------- tests/cases/fourslash/commentsInterface.ts | 6 +-- tests/cases/fourslash/commentsModules.ts | 28 +++++++------- tests/cases/fourslash/commentsOverloads.ts | 30 +++++++-------- .../cases/fourslash/quickInfoCallProperty.ts | 11 ++++++ .../fourslash/quickInfoOnInternalAliases.ts | 2 +- 11 files changed, 75 insertions(+), 63 deletions(-) create mode 100644 tests/cases/fourslash/quickInfoCallProperty.ts diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 611bb26bf1e..d1d8709bef2 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -611,7 +611,8 @@ namespace ts.SymbolDisplay { displayParts.push(textPart(allSignatures.length === 2 ? "overload" : "overloads")); displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } - documentation = signature.getDocumentationComment(typeChecker); + const docComment = signature.getDocumentationComment(typeChecker); + documentation = docComment.length === 0 ? undefined : docComment; tags = signature.getJsDocTags(); } diff --git a/tests/cases/fourslash/commentsClass.ts b/tests/cases/fourslash/commentsClass.ts index 79f1d05af66..87e9b9d3a48 100644 --- a/tests/cases/fourslash/commentsClass.ts +++ b/tests/cases/fourslash/commentsClass.ts @@ -1,6 +1,6 @@ /// -/////** This is class c2 without constuctor*/ +/////** This is class c2 without constructor*/ ////class c/*1*/2 { ////} ////var i/*2*/2 = new c/*28*/2(/*3*/); @@ -59,7 +59,7 @@ ////var myVar = new m.m2.c/*33*/1(); verify.quickInfos({ - 1: ["class c2", "This is class c2 without constuctor"], + 1: ["class c2", "This is class c2 without constructor"], 2: "var i2: c2" }); @@ -67,7 +67,7 @@ verify.signatureHelp({ marker: "3", docComment: "" }); verify.quickInfos({ 4: "var i2_c: typeof c2", - 5: ["class c2", "This is class c2 without constuctor"], + 5: ["class c2", "This is class c2 without constructor"], 6: "class c3", 7: "var i3: c3" }); @@ -107,7 +107,7 @@ verify.quickInfos({ }); goTo.marker('26'); -verify.completionListContains("c2", "class c2", "This is class c2 without constuctor"); +verify.completionListContains("c2", "class c2", "This is class c2 without constructor"); verify.completionListContains("i2", "var i2: c2", ""); verify.completionListContains("i2_c", "var i2_c: typeof c2", ""); verify.completionListContains("c3", "class c3", ""); @@ -131,10 +131,10 @@ verify.signatureHelp({ }); verify.quickInfos({ - 28: "constructor c2(): c2", + 28: ["constructor c2(): c2", "This is class c2 without constructor"], 29: ["constructor c3(): c3", "Constructor comment"], 30: ["constructor c4(): c4", "Constructor comment"], - 31: "constructor c5(): c5", + 31: ["constructor c5(): c5", "Class with statics"], 32: ["constructor c6(): c6", "constructor comment"], 33: ["constructor m.m2.c1(): m.m2.c1", "constructor comment"] }); diff --git a/tests/cases/fourslash/commentsCommentParsing.ts b/tests/cases/fourslash/commentsCommentParsing.ts index 2b59b35bd14..df3adca4c87 100644 --- a/tests/cases/fourslash/commentsCommentParsing.ts +++ b/tests/cases/fourslash/commentsCommentParsing.ts @@ -323,7 +323,7 @@ verify.quickInfos({ verify.signatureHelp({ marker: "26", overloadsCount: 2, docComment: "" }); verify.quickInfos({ - "26q": "function f1(b: string): any (+1 overload)", + "26q": ["function f1(b: string): any (+1 overload)", "fn f1 with number"], "26aq": "(parameter) b: string" }); diff --git a/tests/cases/fourslash/commentsExternalModules.ts b/tests/cases/fourslash/commentsExternalModules.ts index f9c619e5a17..c1c12d8a3ce 100644 --- a/tests/cases/fourslash/commentsExternalModules.ts +++ b/tests/cases/fourslash/commentsExternalModules.ts @@ -55,7 +55,7 @@ verify.quickInfoAt("6q", "function m1.fooExport(): number", "exported function") verify.quickInfoAt("7", "var myvar: m1.m2.c"); goTo.marker('8'); -verify.completionListContains("c", "constructor m1.m2.c(): m1.m2.c", ""); +verify.completionListContains("c", "constructor m1.m2.c(): m1.m2.c", "class comment;"); verify.completionListContains("i", "var m1.m2.i: m1.m2.c", "i"); goTo.file("commentsExternalModules_file1.ts"); @@ -78,5 +78,5 @@ verify.quickInfoAt("13q", "function extMod.m1.fooExport(): number", "exported fu verify.quickInfoAt("14", "var newVar: extMod.m1.m2.c"); goTo.marker('15'); -verify.completionListContains("c", "constructor extMod.m1.m2.c(): extMod.m1.m2.c", ""); +verify.completionListContains("c", "constructor extMod.m1.m2.c(): extMod.m1.m2.c", "class comment;"); verify.completionListContains("i", "var extMod.m1.m2.i: extMod.m1.m2.c", "i"); diff --git a/tests/cases/fourslash/commentsImportDeclaration.ts b/tests/cases/fourslash/commentsImportDeclaration.ts index bc343afeabf..b19eeba6885 100644 --- a/tests/cases/fourslash/commentsImportDeclaration.ts +++ b/tests/cases/fourslash/commentsImportDeclaration.ts @@ -49,7 +49,7 @@ verify.quickInfos({ verify.completions({ marker: "10", exact: [ - { name: "c", text: "constructor extMod.m1.m2.c(): extMod.m1.m2.c" }, + { name: "c", text: "constructor extMod.m1.m2.c(): extMod.m1.m2.c", documentation: "class comment;" }, { name: "i", text: "var extMod.m1.m2.i: extMod.m1.m2.c", documentation: "i" }, ], }); diff --git a/tests/cases/fourslash/commentsInheritance.ts b/tests/cases/fourslash/commentsInheritance.ts index 3443ec23177..aac3cf287f4 100644 --- a/tests/cases/fourslash/commentsInheritance.ts +++ b/tests/cases/fourslash/commentsInheritance.ts @@ -223,7 +223,7 @@ goTo.marker('1'); verify.completionListContains("i1_p1", "(property) i1.i1_p1: number", "i1_p1"); verify.completionListContains("i1_f1", "(method) i1.i1_f1(): void", "i1_f1"); -verify.completionListContains("i1_l1", "(property) i1.i1_l1: () => void", ""); +verify.completionListContains("i1_l1", "(property) i1.i1_l1: () => void", "i1_l1"); verify.completionListContains("i1_nc_p1", "(property) i1.i1_nc_p1: number", ""); verify.completionListContains("i1_nc_f1", "(method) i1.i1_nc_f1(): void", ""); verify.completionListContains("i1_nc_l1", "(property) i1.i1_nc_l1: () => void", ""); @@ -244,7 +244,7 @@ verify.quickInfos({ "3q": "(method) i1.i1_nc_f1(): void", "4q": "(method) i1.f1(): void", "5q": "(method) i1.nc_f1(): void", - l2q: "(property) i1.i1_l1: () => void", + l2q: ["(property) i1.i1_l1: () => void", "i1_l1"], l3q: "(property) i1.i1_nc_l1: () => void", l4q: "(property) i1.l1: () => void", l5q: "(property) i1.nc_l1: () => void" @@ -253,7 +253,7 @@ verify.quickInfos({ goTo.marker('6'); verify.completionListContains("i1_p1", "(property) c1.i1_p1: number", "i1_p1"); verify.completionListContains("i1_f1", "(method) c1.i1_f1(): void", "i1_f1"); -verify.completionListContains("i1_l1", "(property) c1.i1_l1: () => void", ""); +verify.completionListContains("i1_l1", "(property) c1.i1_l1: () => void", "i1_l1"); verify.completionListContains("i1_nc_p1", "(property) c1.i1_nc_p1: number", ""); verify.completionListContains("i1_nc_f1", "(method) c1.i1_nc_f1(): void", ""); verify.completionListContains("i1_nc_l1", "(property) c1.i1_nc_l1: () => void", ""); @@ -278,7 +278,7 @@ verify.quickInfos({ "8q": "(method) c1.i1_nc_f1(): void", "9q": ["(method) c1.f1(): void", "c1_f1"], "10q": ["(method) c1.nc_f1(): void", "c1_nc_f1"], - l7q: "(property) c1.i1_l1: () => void", + l7q: ["(property) c1.i1_l1: () => void", "i1_l1"], l8q: "(property) c1.i1_nc_l1: () => void", l9q: ["(property) c1.l1: () => void", "c1_l1"], l10q: ["(property) c1.nc_l1: () => void", "c1_nc_l1"], @@ -287,7 +287,7 @@ verify.quickInfos({ goTo.marker('11'); verify.completionListContains("i1_p1", "(property) i1.i1_p1: number", "i1_p1"); verify.completionListContains("i1_f1", "(method) i1.i1_f1(): void", "i1_f1"); -verify.completionListContains("i1_l1", "(property) i1.i1_l1: () => void", ""); +verify.completionListContains("i1_l1", "(property) i1.i1_l1: () => void", "i1_l1"); verify.completionListContains("i1_nc_p1", "(property) i1.i1_nc_p1: number", ""); verify.completionListContains("i1_nc_f1", "(method) i1.i1_nc_f1(): void", ""); verify.completionListContains("i1_nc_l1", "(property) i1.i1_nc_l1: () => void", ""); @@ -307,7 +307,7 @@ verify.quickInfos({ "13q": "(method) i1.i1_nc_f1(): void", "14q": "(method) i1.f1(): void", "15q": "(method) i1.nc_f1(): void", - l12q: "(property) i1.i1_l1: () => void", + l12q: ["(property) i1.i1_l1: () => void", "i1_l1"], l13q: "(property) i1.i1_nc_l1: () => void", l14q: "(property) i1.l1: () => void", l15q: "(property) i1.nc_l1: () => void", @@ -437,13 +437,13 @@ verify.completionListContains("c4_i", "var c4_i: c4", ""); goTo.marker('36'); verify.completionListContains("i2_p1", "(property) i2.i2_p1: number", "i2_p1"); verify.completionListContains("i2_f1", "(method) i2.i2_f1(): void", "i2_f1"); -verify.completionListContains("i2_l1", "(property) i2.i2_l1: () => void", ""); +verify.completionListContains("i2_l1", "(property) i2.i2_l1: () => void", "i2_l1"); verify.completionListContains("i2_nc_p1", "(property) i2.i2_nc_p1: number", ""); verify.completionListContains("i2_nc_f1", "(method) i2.i2_nc_f1(): void", ""); verify.completionListContains("i2_nc_l1", "(property) i2.i2_nc_l1: () => void", ""); verify.completionListContains("p1", "(property) i2.p1: number", "i2 p1"); verify.completionListContains("f1", "(method) i2.f1(): void", "i2 f1"); -verify.completionListContains("l1", "(property) i2.l1: () => void", ""); +verify.completionListContains("l1", "(property) i2.l1: () => void", "i2 l1"); verify.completionListContains("nc_p1", "(property) i2.nc_p1: number", ""); verify.completionListContains("nc_f1", "(method) i2.nc_f1(): void", ""); verify.completionListContains("nc_l1", "(property) i2.nc_l1: () => void", ""); @@ -460,22 +460,22 @@ verify.quickInfos({ "38q": "(method) i2.i2_nc_f1(): void", "39q": ["(method) i2.f1(): void", "i2 f1"], "40q": "(method) i2.nc_f1(): void", - "l37q": "(property) i2.i2_l1: () => void", + "l37q": ["(property) i2.i2_l1: () => void", "i2_l1"], "l38q": "(property) i2.i2_nc_l1: () => void", - "l39q": "(property) i2.l1: () => void", + "l39q": ["(property) i2.l1: () => void", "i2 l1"], "l40q": "(property) i2.nc_l1: () => void", }); goTo.marker('41'); verify.completionListContains("i2_p1", "(property) i2.i2_p1: number", "i2_p1"); verify.completionListContains("i2_f1", "(method) i2.i2_f1(): void", "i2_f1"); -verify.completionListContains("i2_l1", "(property) i2.i2_l1: () => void", ""); +verify.completionListContains("i2_l1", "(property) i2.i2_l1: () => void", "i2_l1"); verify.completionListContains("i2_nc_p1", "(property) i2.i2_nc_p1: number", ""); verify.completionListContains("i2_nc_f1", "(method) i2.i2_nc_f1(): void", ""); verify.completionListContains("i2_nc_l1", "(property) i2.i2_nc_l1: () => void", ""); verify.completionListContains("p1", "(property) i3.p1: number", "i3 p1"); verify.completionListContains("f1", "(method) i3.f1(): void", "i3 f1"); -verify.completionListContains("l1", "(property) i3.l1: () => void", ""); +verify.completionListContains("l1", "(property) i3.l1: () => void", "i3 l1"); verify.completionListContains("nc_p1", "(property) i3.nc_p1: number", ""); verify.completionListContains("nc_f1", "(method) i3.nc_f1(): void", ""); verify.completionListContains("nc_l1", "(property) i3.nc_l1: () => void", ""); @@ -490,22 +490,22 @@ verify.quickInfos({ "43q": "(method) i2.i2_nc_f1(): void", "44q": ["(method) i3.f1(): void", "i3 f1"], "45q": "(method) i3.nc_f1(): void", - l42q: "(property) i2.i2_l1: () => void", + l42q: ["(property) i2.i2_l1: () => void", "i2_l1"], l43q: "(property) i2.i2_nc_l1: () => void", - l44q: "(property) i3.l1: () => void", + l44q: ["(property) i3.l1: () => void", "i3 l1"], l45q: "(property) i3.nc_l1: () => void" }); goTo.marker('46'); verify.completionListContains("i2_p1", "(property) i2.i2_p1: number", "i2_p1"); verify.completionListContains("i2_f1", "(method) i2.i2_f1(): void", "i2_f1"); -verify.completionListContains("i2_l1", "(property) i2.i2_l1: () => void", ""); +verify.completionListContains("i2_l1", "(property) i2.i2_l1: () => void", "i2_l1"); verify.completionListContains("i2_nc_p1", "(property) i2.i2_nc_p1: number", ""); verify.completionListContains("i2_nc_f1", "(method) i2.i2_nc_f1(): void", ""); verify.completionListContains("i2_nc_l1", "(property) i2.i2_nc_l1: () => void", ""); verify.completionListContains("p1", "(property) i2.p1: number", "i2 p1"); verify.completionListContains("f1", "(method) i2.f1(): void", "i2 f1"); -verify.completionListContains("l1", "(property) i2.l1: () => void", ""); +verify.completionListContains("l1", "(property) i2.l1: () => void", "i2 l1"); verify.completionListContains("nc_p1", "(property) i2.nc_p1: number", ""); verify.completionListContains("nc_f1", "(method) i2.nc_f1(): void", ""); verify.completionListContains("nc_l1", "(property) i2.nc_l1: () => void", ""); @@ -520,9 +520,9 @@ verify.quickInfos({ "48q": "(method) i2.i2_nc_f1(): void", "49q": ["(method) i2.f1(): void", "i2 f1"], "50q": "(method) i2.nc_f1(): void", - l47q: "(property) i2.i2_l1: () => void", + l47q: ["(property) i2.i2_l1: () => void", "i2_l1"], l48q: "(property) i2.i2_nc_l1: () => void", - l49q: "(property) i2.l1: () => void", + l49q: ["(property) i2.l1: () => void", "i2 l1"], l40q: "(property) i2.nc_l1: () => void" }); @@ -537,7 +537,7 @@ verify.completionListContains("i2", "interface i2", ""); verify.completionListContains("i3", "interface i3", ""); verify.quickInfos({ - 52: "constructor c5(): c5", + 52: ["constructor c5(): c5", "c5 class"], 53: ["class c5", "c5 class"], 54: "(property) c5.b: number", 55: ["constructor c2(a: number): c2", "c2 constructor"], diff --git a/tests/cases/fourslash/commentsInterface.ts b/tests/cases/fourslash/commentsInterface.ts index 85c12118c34..fdeeb8bb3eb 100644 --- a/tests/cases/fourslash/commentsInterface.ts +++ b/tests/cases/fourslash/commentsInterface.ts @@ -96,7 +96,7 @@ verify.quickInfos({ verify.signatureHelp({ marker: "12", docComment: "", parameterDocComment: "param help" }); verify.quickInfos({ - "12q": "(property) i2.foo: (b: number) => string", + "12q": ["(property) i2.foo: (b: number) => string", "this is foo"], 13: "var i2_i_i2_si: number", "13q": "var i2_i: i2", @@ -186,7 +186,7 @@ verify.completionListContains("i3_i", "var i3_i: i3", ""); goTo.marker('41'); verify.quickInfoIs("(method) i3.f(a: number): string", "Function i3 f"); verify.completionListContains("f", "(method) i3.f(a: number): string", "Function i3 f"); -verify.completionListContains("l", "(property) i3.l: (b: number) => string", ""); +verify.completionListContains("l", "(property) i3.l: (b: number) => string", "i3 l"); verify.completionListContains("x", "(property) i3.x: number", "Comment i3 x"); verify.completionListContains("nc_f", "(method) i3.nc_f(a: number): string", ""); verify.completionListContains("nc_l", "(property) i3.nc_l: (b: number) => string", ""); @@ -195,7 +195,7 @@ verify.completionListContains("nc_x", "(property) i3.nc_x: number", ""); verify.signatureHelp({ marker: "42", docComment: "Function i3 f", parameterDocComment: "number parameter" }); verify.signatureHelp({ marker: "43", docComment: "", parameterDocComment: "comment i3 l b" }); -verify.quickInfoAt("43q", "(property) i3.l: (b: number) => string"); +verify.quickInfoAt("43q", "(property) i3.l: (b: number) => string", "i3 l"); verify.signatureHelp({ marker: "44", docComment: "" }); verify.quickInfoAt("44q", "(method) i3.nc_f(a: number): string"); diff --git a/tests/cases/fourslash/commentsModules.ts b/tests/cases/fourslash/commentsModules.ts index d36e530d9bd..545c1569096 100644 --- a/tests/cases/fourslash/commentsModules.ts +++ b/tests/cases/fourslash/commentsModules.ts @@ -119,8 +119,8 @@ verify.signatureHelp({ marker: "6", docComment: "exported function" }); verify.quickInfoAt("7", "var myvar: m1.m2.c"); goTo.marker('8'); -verify.quickInfoIs("constructor m1.m2.c(): m1.m2.c"); -verify.completionListContains("c", "constructor m1.m2.c(): m1.m2.c", ""); +verify.quickInfoIs("constructor m1.m2.c(): m1.m2.c", "class comment;"); +verify.completionListContains("c", "constructor m1.m2.c(): m1.m2.c", "class comment;"); verify.completionListContains("i", "var m1.m2.i: m1.m2.c", "i"); goTo.marker('9'); @@ -132,8 +132,8 @@ verify.completionListContains("m3", "namespace m2.m3"); verify.quickInfoIs("namespace m2.m3", "namespace comment of m2.m3"); goTo.marker('11'); -verify.quickInfoIs("constructor m2.m3.c(): m2.m3.c"); -verify.completionListContains("c", "constructor m2.m3.c(): m2.m3.c", ""); +verify.quickInfoIs("constructor m2.m3.c(): m2.m3.c", "Exported class comment"); +verify.completionListContains("c", "constructor m2.m3.c(): m2.m3.c", "Exported class comment"); goTo.marker('12'); verify.completionListContains("m3", "namespace m3", "namespace comment of m3.m4.m5"); @@ -148,8 +148,8 @@ verify.completionListContains("m5", "namespace m3.m4.m5"); verify.quickInfoIs("namespace m3.m4.m5", "namespace comment of m3.m4.m5"); goTo.marker('15'); -verify.quickInfoIs("constructor m3.m4.m5.c(): m3.m4.m5.c"); -verify.completionListContains("c", "constructor m3.m4.m5.c(): m3.m4.m5.c", ""); +verify.quickInfoIs("constructor m3.m4.m5.c(): m3.m4.m5.c", "Exported class comment"); +verify.completionListContains("c", "constructor m3.m4.m5.c(): m3.m4.m5.c", "Exported class comment"); goTo.marker('16'); verify.completionListContains("m4", "namespace m4", "namespace comment of m4.m5.m6"); @@ -168,8 +168,8 @@ verify.completionListContains("m7", "namespace m4.m5.m6.m7"); verify.quickInfoIs("namespace m4.m5.m6.m7"); goTo.marker('20'); -verify.completionListContains("c", "constructor m4.m5.m6.m7.c(): m4.m5.m6.m7.c", ""); -verify.quickInfoIs("constructor m4.m5.m6.m7.c(): m4.m5.m6.m7.c"); +verify.completionListContains("c", "constructor m4.m5.m6.m7.c(): m4.m5.m6.m7.c", "Exported class comment"); +verify.quickInfoIs("constructor m4.m5.m6.m7.c(): m4.m5.m6.m7.c", "Exported class comment"); goTo.marker('21'); verify.completionListContains("m5", "namespace m5"); @@ -188,8 +188,8 @@ verify.completionListContains("m8", "namespace m5.m6.m7.m8"); verify.quickInfoIs("namespace m5.m6.m7.m8", "namespace m8 comment"); goTo.marker('25'); -verify.completionListContains("c", "constructor m5.m6.m7.m8.c(): m5.m6.m7.m8.c", ""); -verify.quickInfoIs("constructor m5.m6.m7.m8.c(): m5.m6.m7.m8.c"); +verify.completionListContains("c", "constructor m5.m6.m7.m8.c(): m5.m6.m7.m8.c", "Exported class comment"); +verify.quickInfoIs("constructor m5.m6.m7.m8.c(): m5.m6.m7.m8.c", "Exported class comment"); goTo.marker('26'); verify.completionListContains("m6", "namespace m6"); @@ -204,8 +204,8 @@ verify.completionListContains("m8", "namespace m6.m7.m8"); verify.quickInfoIs("namespace m6.m7.m8"); goTo.marker('29'); -verify.completionListContains("c", "constructor m6.m7.m8.c(): m6.m7.m8.c", ""); -verify.quickInfoIs("constructor m6.m7.m8.c(): m6.m7.m8.c"); +verify.completionListContains("c", "constructor m6.m7.m8.c(): m6.m7.m8.c", "Exported class comment"); +verify.quickInfoIs("constructor m6.m7.m8.c(): m6.m7.m8.c", "Exported class comment"); goTo.marker('30'); verify.completionListContains("m7", "namespace m7"); @@ -220,8 +220,8 @@ verify.completionListContains("m9", "namespace m7.m8.m9"); verify.quickInfoIs("namespace m7.m8.m9", "namespace m9 comment"); goTo.marker('33'); -verify.completionListContains("c", "constructor m7.m8.m9.c(): m7.m8.m9.c", ""); -verify.quickInfoIs("constructor m7.m8.m9.c(): m7.m8.m9.c"); +verify.completionListContains("c", "constructor m7.m8.m9.c(): m7.m8.m9.c", "Exported class comment"); +verify.quickInfoIs("constructor m7.m8.m9.c(): m7.m8.m9.c", "Exported class comment"); goTo.marker('34'); verify.completionListContains("c", 'class c', ""); diff --git a/tests/cases/fourslash/commentsOverloads.ts b/tests/cases/fourslash/commentsOverloads.ts index a6c7170d2e9..372eedbb2da 100644 --- a/tests/cases/fourslash/commentsOverloads.ts +++ b/tests/cases/fourslash/commentsOverloads.ts @@ -227,9 +227,9 @@ verify.quickInfos({ 1: ["function f1(a: number): number (+1 overload)", "this is signature 1"], - 2: "function f1(b: string): number (+1 overload)", + 2: ["function f1(b: string): number (+1 overload)", "this is signature 1"], 3: ["function f1(a: number): number (+1 overload)", "this is signature 1"], - "4q": "function f1(b: string): number (+1 overload)", + "4q": ["function f1(b: string): number (+1 overload)", "this is signature 1"], o4q: ["function f1(a: number): number (+1 overload)", "this is signature 1"] }); @@ -237,11 +237,11 @@ verify.signatureHelp({ marker: "4", overloadsCount: 2 }); verify.signatureHelp({ marker: "o4", overloadsCount: 2, docComment: "this is signature 1", parameterDocComment: "param a" }); verify.quickInfos({ - 5: "function f2(a: number): number (+1 overload)", + 5: ["function f2(a: number): number (+1 overload)", "this is signature 2\nthis is f2 var comment"], 6: ["function f2(b: string): number (+1 overload)", "this is signature 2"], - 7: "function f2(a: number): number (+1 overload)", + 7: ["function f2(a: number): number (+1 overload)", "this is signature 2\nthis is f2 var comment"], "8q": ["function f2(b: string): number (+1 overload)", "this is signature 2"], - o8q: "function f2(a: number): number (+1 overload)" + o8q: ["function f2(a: number): number (+1 overload)", "this is signature 2\nthis is f2 var comment"], }); verify.signatureHelp( @@ -274,7 +274,7 @@ verify.signatureHelp( goTo.marker('17'); verify.completionListContains('f1', 'function f1(a: number): number (+1 overload)', 'this is signature 1'); -verify.completionListContains('f2', 'function f2(a: number): number (+1 overload)', ''); +verify.completionListContains('f2', 'function f2(a: number): number (+1 overload)', 'this is signature 2\nthis is f2 var comment'); verify.completionListContains('f3', 'function f3(a: number): number (+1 overload)', ''); verify.completionListContains('f4', 'function f4(a: number): number (+1 overload)', 'this is signature 4 - with number parameter'); @@ -303,7 +303,7 @@ verify.quickInfoAt("22q", "var i1_i: i1\n(b: string) => number (+1 overload)", " goTo.marker('23'); verify.completionListContains('foo', '(method) i1.foo(a: number): number (+1 overload)', 'foo 1'); -verify.completionListContains('foo2', '(method) i1.foo2(a: number): number (+1 overload)', ''); +verify.completionListContains('foo2', '(method) i1.foo2(a: number): number (+1 overload)', 'foo2 2'); verify.completionListContains('foo3', '(method) i1.foo3(a: number): number (+1 overload)', ''); verify.completionListContains('foo4', '(method) i1.foo4(a: number): number (+1 overload)', 'foo4 1'); @@ -314,7 +314,7 @@ verify.signatureHelp({ marker: "25", overloadsCount: 2, docComment: "foo 2" }); verify.quickInfoAt("25q", "(method) i1.foo(b: string): number (+1 overload)", "foo 2"); verify.signatureHelp({ marker: "26", overloadsCount: 2 }); -verify.quickInfoAt("26q", "(method) i1.foo2(a: number): number (+1 overload)"); +verify.quickInfoAt("26q", "(method) i1.foo2(a: number): number (+1 overload)", "foo2 2"); verify.signatureHelp({ marker: "27", overloadsCount: 2, docComment: "foo2 2" }); verify.quickInfoAt("27q", "(method) i1.foo2(b: string): number (+1 overload)", "foo2 2"); @@ -329,7 +329,7 @@ verify.signatureHelp({ marker: "30", overloadsCount: 2, docComment: "foo4 1" }); verify.quickInfoAt("30q", "(method) i1.foo4(a: number): number (+1 overload)", "foo4 1"); verify.signatureHelp({ marker: "31", overloadsCount: 2 }); -verify.quickInfoAt("31q", "(method) i1.foo4(b: string): number (+1 overload)"); +verify.quickInfoAt("31q", "(method) i1.foo4(b: string): number (+1 overload)", "foo4 1"); verify.signatureHelp({ marker: "32", overloadsCount: 2, docComment: "new 2" }); verify.quickInfoAt("32q", "var i2_i: i2\nnew (b: number) => any (+1 overload)", "new 2"); @@ -370,7 +370,7 @@ verify.quickInfoAt("43q", "var i4_i: i4\n(b: string) => number (+1 overload)"); goTo.marker('44'); verify.completionListContains('prop1', '(method) c.prop1(a: number): number (+1 overload)', ''); verify.completionListContains('prop2', '(method) c.prop2(a: number): number (+1 overload)', 'prop2 1'); -verify.completionListContains('prop3', '(method) c.prop3(a: number): number (+1 overload)', ''); +verify.completionListContains('prop3', '(method) c.prop3(a: number): number (+1 overload)', 'prop3 2'); verify.completionListContains('prop4', '(method) c.prop4(a: number): number (+1 overload)', 'prop4 1'); verify.completionListContains('prop5', '(method) c.prop5(a: number): number (+1 overload)', 'prop5 1'); @@ -384,10 +384,10 @@ verify.signatureHelp({ marker: "47", overloadsCount: 2, docComment: "prop2 1" }) verify.quickInfoAt("47q", "(method) c.prop2(a: number): number (+1 overload)", "prop2 1"); verify.signatureHelp({ marker: "48", overloadsCount: 2 }); -verify.quickInfoAt("48q", "(method) c.prop2(b: string): number (+1 overload)"); +verify.quickInfoAt("48q", "(method) c.prop2(b: string): number (+1 overload)", "prop2 1"); verify.signatureHelp({ marker: "49", overloadsCount: 2 }); -verify.quickInfoAt("49q", "(method) c.prop3(a: number): number (+1 overload)"); +verify.quickInfoAt("49q", "(method) c.prop3(a: number): number (+1 overload)", "prop3 2"); verify.signatureHelp({ marker: "50", overloadsCount: 2, docComment: "prop3 2" }); verify.quickInfoAt("50q", "(method) c.prop3(b: string): number (+1 overload)", "prop3 2"); @@ -487,11 +487,11 @@ verify.quickInfos({ 94: "(method) c.prop1(b: string): number (+1 overload)", 95: "(method) c.prop1(a: number): number (+1 overload)", 96: ["(method) c.prop2(a: number): number (+1 overload)", "prop2 1"], - 97: "(method) c.prop2(b: string): number (+1 overload)", + 97: ["(method) c.prop2(b: string): number (+1 overload)", "prop2 1"], 98: ["(method) c.prop2(a: number): number (+1 overload)", "prop2 1"], - 99: "(method) c.prop3(a: number): number (+1 overload)", + 99: ["(method) c.prop3(a: number): number (+1 overload)", "prop3 2"], 100: ["(method) c.prop3(b: string): number (+1 overload)", "prop3 2"], - 101: "(method) c.prop3(a: number): number (+1 overload)", + 101: ["(method) c.prop3(a: number): number (+1 overload)", "prop3 2"], 102: ["(method) c.prop4(a: number): number (+1 overload)", "prop4 1"], 103: ["(method) c.prop4(b: string): number (+1 overload)", "prop4 2"], 104: ["(method) c.prop4(a: number): number (+1 overload)", "prop4 1"], diff --git a/tests/cases/fourslash/quickInfoCallProperty.ts b/tests/cases/fourslash/quickInfoCallProperty.ts new file mode 100644 index 00000000000..a4c43f02e9f --- /dev/null +++ b/tests/cases/fourslash/quickInfoCallProperty.ts @@ -0,0 +1,11 @@ +/// + +////interface I { +//// /** Doc */ +//// m: () => void; +////} +////function f(x: I): void { +//// x./**/m(); +////} + +verify.quickInfoAt("", "(property) I.m: () => void", "Doc"); diff --git a/tests/cases/fourslash/quickInfoOnInternalAliases.ts b/tests/cases/fourslash/quickInfoOnInternalAliases.ts index f22b61ae86d..6626a8b1fdf 100644 --- a/tests/cases/fourslash/quickInfoOnInternalAliases.ts +++ b/tests/cases/fourslash/quickInfoOnInternalAliases.ts @@ -24,7 +24,7 @@ verify.quickInfos({ 2: ["(alias) class internalAlias\nimport internalAlias = m1.m2.c", "This is on import declaration"], 3: ["class m1.m2.c", "class comment;"], 4: "var newVar: internalAlias", - 5: "(alias) new internalAlias(): internalAlias\nimport internalAlias = m1.m2.c", + 5: ["(alias) new internalAlias(): internalAlias\nimport internalAlias = m1.m2.c", "This is on import declaration"], 6: "var anotherAliasVar: typeof internalAlias", 7: ["(alias) class internalAlias\nimport internalAlias = m1.m2.c", "This is on import declaration"], 8: "(alias) function internalFoo(): void\nimport internalFoo = m1.foo", From 6419240ab2668ff818c933796c2fc532588dbe50 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 27 Aug 2018 10:29:53 -0700 Subject: [PATCH 52/77] Declaration emit includes function properties (#26499) * Declaration emit includes function properties It does this by printing the type as an object literal type: ```ts function f() { } f.p = 1 ``` Appears in a d.ts as ```ts declare var f: { (): void; p: number; } ``` It would also be possible to represent it as a namespace merge. I'm not sure which is better. ```ts declare function f(): void; declare namespace f { export var p: number; } ``` In order to avoid a private-name-used error (though I think it was actually *unused*), I also had to change the nodeBuilder code to match. This is arguably harder to read. So it's possible that I should instead keep the nodeBuilder version as `typeof f` and make an exception for private name use. * Emit namespace merge instead of object type This makes the change smaller, overall. * Fix isJSContainerFunctionDeclaration+namespace merges Also improve emit style to match other namespace emit. * Add isPrivate + test case from PR comments --- src/compiler/checker.ts | 25 +- src/compiler/transformers/declarations.ts | 17 +- src/compiler/types.ts | 4 +- .../typeFromPropertyAssignment29.errors.txt | 58 +++-- .../reference/typeFromPropertyAssignment29.js | 130 +++++++++- .../typeFromPropertyAssignment29.symbols | 224 ++++++++++++------ .../typeFromPropertyAssignment29.types | 152 ++++++++++-- .../salsa/typeFromPropertyAssignment29.ts | 35 ++- 8 files changed, 540 insertions(+), 105 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f070d71bb16..a3cd01e3583 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27767,6 +27767,27 @@ namespace ts { hasModifier(parameter, ModifierFlags.ParameterPropertyModifier); } + function isJSContainerFunctionDeclaration(node: Declaration): boolean { + const declaration = getParseTreeNode(node, isFunctionDeclaration); + if (!declaration) { + return false; + } + const symbol = getSymbolOfNode(declaration); + if (!symbol || !(symbol.flags & SymbolFlags.Function)) { + return false; + } + return !!forEachEntry(getExportsOfSymbol(symbol), p => isPropertyAccessExpression(p.valueDeclaration)); + } + + function getPropertiesOfContainerFunction(node: Declaration): Symbol[] { + const declaration = getParseTreeNode(node, isFunctionDeclaration); + if (!declaration) { + return emptyArray; + } + const symbol = getSymbolOfNode(declaration); + return symbol && getPropertiesOfType(getTypeOfSymbol(symbol)) || emptyArray; + } + function getNodeCheckFlags(node: Node): NodeCheckFlags { return getNodeLinks(node).flags || 0; } @@ -27874,7 +27895,7 @@ namespace ts { } } - function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) { + function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) { const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor); if (!declaration) { return createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; @@ -28007,6 +28028,8 @@ namespace ts { isImplementationOfOverload, isRequiredInitializedParameter, isOptionalUninitializedParameterProperty, + isJSContainerFunctionDeclaration, + getPropertiesOfContainerFunction, createTypeOfDeclaration, createReturnTypeOfSignatureDeclaration, createTypeOfExpression, diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 063b5f1cd1d..9974b60875b 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -971,7 +971,7 @@ namespace ts { } case SyntaxKind.FunctionDeclaration: { // Generators lose their generator-ness, excepting their return type - return cleanup(updateFunctionDeclaration( + const clean = cleanup(updateFunctionDeclaration( input, /*decorators*/ undefined, ensureModifiers(input, isPrivate), @@ -982,6 +982,21 @@ namespace ts { ensureType(input, input.type), /*body*/ undefined )); + if (clean && resolver.isJSContainerFunctionDeclaration(input)) { + const declarations = mapDefined(resolver.getPropertiesOfContainerFunction(input), p => { + if (!isPropertyAccessExpression(p.valueDeclaration)) { + return undefined; + } + const type = resolver.createTypeOfDeclaration(p.valueDeclaration, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker); + const varDecl = createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), type, /*initializer*/ undefined); + return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl])); + }); + const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name!, createModuleBlock(declarations), NodeFlags.Namespace); + return [clean, namespaceDecl]; + } + else { + return clean; + } } case SyntaxKind.ModuleDeclaration: { needsDeclare = false; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4330a776d04..3c66a3a9d57 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3374,7 +3374,9 @@ namespace ts { isImplementationOfOverload(node: FunctionLike): boolean | undefined; isRequiredInitializedParameter(node: ParameterDeclaration): boolean; isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean; - createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined; + isJSContainerFunctionDeclaration(node: FunctionDeclaration): boolean; + getPropertiesOfContainerFunction(node: Declaration): Symbol[]; + createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined; createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): Expression; diff --git a/tests/baselines/reference/typeFromPropertyAssignment29.errors.txt b/tests/baselines/reference/typeFromPropertyAssignment29.errors.txt index 173e08e9793..04c4dfc3de6 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment29.errors.txt +++ b/tests/baselines/reference/typeFromPropertyAssignment29.errors.txt @@ -1,15 +1,15 @@ -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(30,14): error TS2339: Property 'prop' does not exist on type '(n: number) => string'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(31,14): error TS2339: Property 'm' does not exist on type '(n: number) => string'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(34,22): error TS2339: Property 'prop' does not exist on type '(n: number) => string'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(34,42): error TS2339: Property 'm' does not exist on type '(n: number) => string'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(40,14): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoClass'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(41,14): error TS2339: Property 'm' does not exist on type 'typeof ExpandoClass'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(44,22): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoClass'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(44,42): error TS2339: Property 'm' does not exist on type 'typeof ExpandoClass'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(50,14): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoExpr3'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(51,14): error TS2339: Property 'm' does not exist on type 'typeof ExpandoExpr3'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(54,22): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoExpr3'. -tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(54,42): error TS2339: Property 'm' does not exist on type 'typeof ExpandoExpr3'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(60,14): error TS2339: Property 'prop' does not exist on type '(n: number) => string'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(61,14): error TS2339: Property 'm' does not exist on type '(n: number) => string'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(64,22): error TS2339: Property 'prop' does not exist on type '(n: number) => string'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(64,42): error TS2339: Property 'm' does not exist on type '(n: number) => string'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(70,14): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoClass'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(71,14): error TS2339: Property 'm' does not exist on type 'typeof ExpandoClass'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(74,22): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoClass'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(74,42): error TS2339: Property 'm' does not exist on type 'typeof ExpandoClass'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(80,14): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoExpr3'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(81,14): error TS2339: Property 'm' does not exist on type 'typeof ExpandoExpr3'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(84,22): error TS2339: Property 'prop' does not exist on type 'typeof ExpandoExpr3'. +tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(84,42): error TS2339: Property 'm' does not exist on type 'typeof ExpandoExpr3'. ==== tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts (12 errors) ==== @@ -25,11 +25,12 @@ tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(54,42): error TS23 const ExpandoExpr = function (n: number) { return n.toString(); } - ExpandoExpr.prop = 2 + ExpandoExpr.prop = { x: 2 } + ExpandoExpr.prop = { y: "" } ExpandoExpr.m = function(n: number) { return n + 1; } - var n = ExpandoExpr.prop + ExpandoExpr.m(12) + ExpandoExpr(101).length + var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length const ExpandoArrow = (n: number) => n.toString(); ExpandoArrow.prop = 2 @@ -38,6 +39,35 @@ tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts(54,42): error TS23 } + function ExpandoNested(n: number) { + const nested = function (m: number) { + return n + m; + }; + nested.total = n + 1_000_000; + return nested; + } + ExpandoNested.also = -1; + + function ExpandoMerge(n: number) { + return n * 100; + } + ExpandoMerge.p1 = 111 + namespace ExpandoMerge { + export var p2 = 222; + } + namespace ExpandoMerge { + export var p3 = 333; + } + var n = ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1); + + namespace Ns { + function ExpandoNamespace(): void {} + ExpandoNamespace.p6 = 42; + export function foo() { + return ExpandoNamespace; + } + } + // Should not work in Typescript -- must be const var ExpandoExpr2 = function (n: number) { return n.toString(); diff --git a/tests/baselines/reference/typeFromPropertyAssignment29.js b/tests/baselines/reference/typeFromPropertyAssignment29.js index d17af851c52..8c2750ebb6d 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment29.js +++ b/tests/baselines/reference/typeFromPropertyAssignment29.js @@ -11,11 +11,12 @@ var n = ExpandoDecl.prop + ExpandoDecl.m(12) + ExpandoDecl(101).length const ExpandoExpr = function (n: number) { return n.toString(); } -ExpandoExpr.prop = 2 +ExpandoExpr.prop = { x: 2 } +ExpandoExpr.prop = { y: "" } ExpandoExpr.m = function(n: number) { return n + 1; } -var n = ExpandoExpr.prop + ExpandoExpr.m(12) + ExpandoExpr(101).length +var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length const ExpandoArrow = (n: number) => n.toString(); ExpandoArrow.prop = 2 @@ -24,6 +25,35 @@ ExpandoArrow.m = function(n: number) { } +function ExpandoNested(n: number) { + const nested = function (m: number) { + return n + m; + }; + nested.total = n + 1_000_000; + return nested; +} +ExpandoNested.also = -1; + +function ExpandoMerge(n: number) { + return n * 100; +} +ExpandoMerge.p1 = 111 +namespace ExpandoMerge { + export var p2 = 222; +} +namespace ExpandoMerge { + export var p3 = 333; +} +var n = ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1); + +namespace Ns { + function ExpandoNamespace(): void {} + ExpandoNamespace.p6 = 42; + export function foo() { + return ExpandoNamespace; + } +} + // Should not work in Typescript -- must be const var ExpandoExpr2 = function (n: number) { return n.toString(); @@ -68,16 +98,45 @@ var n = ExpandoDecl.prop + ExpandoDecl.m(12) + ExpandoDecl(101).length; var ExpandoExpr = function (n) { return n.toString(); }; -ExpandoExpr.prop = 2; +ExpandoExpr.prop = { x: 2 }; +ExpandoExpr.prop = { y: "" }; ExpandoExpr.m = function (n) { return n + 1; }; -var n = ExpandoExpr.prop + ExpandoExpr.m(12) + ExpandoExpr(101).length; +var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length; var ExpandoArrow = function (n) { return n.toString(); }; ExpandoArrow.prop = 2; ExpandoArrow.m = function (n) { return n + 1; }; +function ExpandoNested(n) { + var nested = function (m) { + return n + m; + }; + nested.total = n + 1000000; + return nested; +} +ExpandoNested.also = -1; +function ExpandoMerge(n) { + return n * 100; +} +ExpandoMerge.p1 = 111; +(function (ExpandoMerge) { + ExpandoMerge.p2 = 222; +})(ExpandoMerge || (ExpandoMerge = {})); +(function (ExpandoMerge) { + ExpandoMerge.p3 = 333; +})(ExpandoMerge || (ExpandoMerge = {})); +var n = ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1); +var Ns; +(function (Ns) { + function ExpandoNamespace() { } + ExpandoNamespace.p6 = 42; + function foo() { + return ExpandoNamespace; + } + Ns.foo = foo; +})(Ns || (Ns = {})); // Should not work in Typescript -- must be const var ExpandoExpr2 = function (n) { return n.toString(); @@ -111,3 +170,66 @@ ExpandoExpr3.m = function (n) { return n + 1; }; var n = ExpandoExpr3.prop + ExpandoExpr3.m(13) + new ExpandoExpr3().n; + + +//// [typeFromPropertyAssignment29.d.ts] +declare function ExpandoDecl(n: number): string; +declare namespace ExpandoDecl { + var prop: number; + var m: (n: number) => number; +} +declare var n: number; +declare const ExpandoExpr: { + (n: number): string; + prop: { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; + m(n: number): number; +}; +declare var n: number; +declare const ExpandoArrow: { + (n: number): string; + prop: number; + m(n: number): number; +}; +declare function ExpandoNested(n: number): { + (m: number): number; + total: number; +}; +declare namespace ExpandoNested { + var also: number; +} +declare function ExpandoMerge(n: number): number; +declare namespace ExpandoMerge { + var p1: number; +} +declare namespace ExpandoMerge { + var p2: number; +} +declare namespace ExpandoMerge { + var p3: number; +} +declare var n: number; +declare namespace Ns { + function ExpandoNamespace(): void; + namespace ExpandoNamespace { + var p6: number; + } + function foo(): typeof ExpandoNamespace; +} +declare var ExpandoExpr2: (n: number) => string; +declare var n: number; +declare class ExpandoClass { + n: number; +} +declare var n: number; +declare var ExpandoExpr3: { + new (): { + n: number; + }; +}; +declare var n: number; diff --git a/tests/baselines/reference/typeFromPropertyAssignment29.symbols b/tests/baselines/reference/typeFromPropertyAssignment29.symbols index 4435e67886f..2e51e26304b 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment29.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment29.symbols @@ -23,7 +23,7 @@ ExpandoDecl.m = function(n: number) { >n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 4, 25)) } var n = ExpandoDecl.prop + ExpandoDecl.m(12) + ExpandoDecl(101).length ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 16, 3), Decl(typeFromPropertyAssignment29.ts, 33, 3), Decl(typeFromPropertyAssignment29.ts, 43, 3), Decl(typeFromPropertyAssignment29.ts, 53, 3)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 17, 3), Decl(typeFromPropertyAssignment29.ts, 45, 3), Decl(typeFromPropertyAssignment29.ts, 63, 3), Decl(typeFromPropertyAssignment29.ts, 73, 3) ... and 1 more) >ExpandoDecl.prop : Symbol(ExpandoDecl.prop, Decl(typeFromPropertyAssignment29.ts, 2, 1)) >ExpandoDecl : Symbol(ExpandoDecl, Decl(typeFromPropertyAssignment29.ts, 0, 0), Decl(typeFromPropertyAssignment29.ts, 3, 20)) >prop : Symbol(ExpandoDecl.prop, Decl(typeFromPropertyAssignment29.ts, 2, 1)) @@ -35,7 +35,7 @@ var n = ExpandoDecl.prop + ExpandoDecl.m(12) + ExpandoDecl(101).length >length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) const ExpandoExpr = function (n: number) { ->ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 12, 20)) +>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 13, 28)) >n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 9, 30)) return n.toString(); @@ -43,131 +43,223 @@ const ExpandoExpr = function (n: number) { >n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 9, 30)) >toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) } -ExpandoExpr.prop = 2 ->ExpandoExpr.prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1)) ->ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 12, 20)) ->prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1)) +ExpandoExpr.prop = { x: 2 } +>ExpandoExpr.prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27)) +>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27)) +>x : Symbol(x, Decl(typeFromPropertyAssignment29.ts, 12, 20)) + +ExpandoExpr.prop = { y: "" } +>ExpandoExpr.prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27)) +>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27)) +>y : Symbol(y, Decl(typeFromPropertyAssignment29.ts, 13, 20)) ExpandoExpr.m = function(n: number) { ->ExpandoExpr.m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 12, 20)) ->ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 12, 20)) ->m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 12, 20)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 13, 25)) +>ExpandoExpr.m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 14, 25)) return n + 1; ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 13, 25)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 14, 25)) } -var n = ExpandoExpr.prop + ExpandoExpr.m(12) + ExpandoExpr(101).length ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 16, 3), Decl(typeFromPropertyAssignment29.ts, 33, 3), Decl(typeFromPropertyAssignment29.ts, 43, 3), Decl(typeFromPropertyAssignment29.ts, 53, 3)) ->ExpandoExpr.prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1)) ->ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 12, 20)) ->prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1)) ->ExpandoExpr.m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 12, 20)) ->ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 12, 20)) ->m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 12, 20)) +var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 17, 3), Decl(typeFromPropertyAssignment29.ts, 45, 3), Decl(typeFromPropertyAssignment29.ts, 63, 3), Decl(typeFromPropertyAssignment29.ts, 73, 3) ... and 1 more) +>ExpandoExpr.prop.x : Symbol(x, Decl(typeFromPropertyAssignment29.ts, 12, 20)) +>ExpandoExpr.prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27)) +>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27)) +>x : Symbol(x, Decl(typeFromPropertyAssignment29.ts, 12, 20)) +>ExpandoExpr.m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 13, 28)) +>m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 13, 28)) >ExpandoExpr(101).length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) ->ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 12, 20)) +>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 13, 28)) >length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) const ExpandoArrow = (n: number) => n.toString(); ->ExpandoArrow : Symbol(ExpandoArrow, Decl(typeFromPropertyAssignment29.ts, 18, 5), Decl(typeFromPropertyAssignment29.ts, 19, 21)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 18, 22)) +>ExpandoArrow : Symbol(ExpandoArrow, Decl(typeFromPropertyAssignment29.ts, 19, 5), Decl(typeFromPropertyAssignment29.ts, 20, 21)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 19, 22)) >n.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 18, 22)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 19, 22)) >toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) ExpandoArrow.prop = 2 ->ExpandoArrow.prop : Symbol(ExpandoArrow.prop, Decl(typeFromPropertyAssignment29.ts, 18, 49)) ->ExpandoArrow : Symbol(ExpandoArrow, Decl(typeFromPropertyAssignment29.ts, 18, 5), Decl(typeFromPropertyAssignment29.ts, 19, 21)) ->prop : Symbol(ExpandoArrow.prop, Decl(typeFromPropertyAssignment29.ts, 18, 49)) +>ExpandoArrow.prop : Symbol(ExpandoArrow.prop, Decl(typeFromPropertyAssignment29.ts, 19, 49)) +>ExpandoArrow : Symbol(ExpandoArrow, Decl(typeFromPropertyAssignment29.ts, 19, 5), Decl(typeFromPropertyAssignment29.ts, 20, 21)) +>prop : Symbol(ExpandoArrow.prop, Decl(typeFromPropertyAssignment29.ts, 19, 49)) ExpandoArrow.m = function(n: number) { ->ExpandoArrow.m : Symbol(ExpandoArrow.m, Decl(typeFromPropertyAssignment29.ts, 19, 21)) ->ExpandoArrow : Symbol(ExpandoArrow, Decl(typeFromPropertyAssignment29.ts, 18, 5), Decl(typeFromPropertyAssignment29.ts, 19, 21)) ->m : Symbol(ExpandoArrow.m, Decl(typeFromPropertyAssignment29.ts, 19, 21)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 20, 26)) +>ExpandoArrow.m : Symbol(ExpandoArrow.m, Decl(typeFromPropertyAssignment29.ts, 20, 21)) +>ExpandoArrow : Symbol(ExpandoArrow, Decl(typeFromPropertyAssignment29.ts, 19, 5), Decl(typeFromPropertyAssignment29.ts, 20, 21)) +>m : Symbol(ExpandoArrow.m, Decl(typeFromPropertyAssignment29.ts, 20, 21)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 21, 26)) return n + 1; ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 20, 26)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 21, 26)) } +function ExpandoNested(n: number) { +>ExpandoNested : Symbol(ExpandoNested, Decl(typeFromPropertyAssignment29.ts, 24, 1)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 26, 23)) + + const nested = function (m: number) { +>nested : Symbol(nested, Decl(typeFromPropertyAssignment29.ts, 27, 9)) +>m : Symbol(m, Decl(typeFromPropertyAssignment29.ts, 27, 29)) + + return n + m; +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 26, 23)) +>m : Symbol(m, Decl(typeFromPropertyAssignment29.ts, 27, 29)) + + }; + nested.total = n + 1_000_000; +>nested.total : Symbol(nested.total, Decl(typeFromPropertyAssignment29.ts, 29, 6)) +>nested : Symbol(nested, Decl(typeFromPropertyAssignment29.ts, 27, 9)) +>total : Symbol(nested.total, Decl(typeFromPropertyAssignment29.ts, 29, 6)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 26, 23)) + + return nested; +>nested : Symbol(nested, Decl(typeFromPropertyAssignment29.ts, 27, 9)) +} +ExpandoNested.also = -1; +>ExpandoNested.also : Symbol(ExpandoNested.also, Decl(typeFromPropertyAssignment29.ts, 32, 1)) +>ExpandoNested : Symbol(ExpandoNested, Decl(typeFromPropertyAssignment29.ts, 24, 1)) +>also : Symbol(ExpandoNested.also, Decl(typeFromPropertyAssignment29.ts, 32, 1)) + +function ExpandoMerge(n: number) { +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 35, 22)) + + return n * 100; +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 35, 22)) +} +ExpandoMerge.p1 = 111 +>ExpandoMerge.p1 : Symbol(ExpandoMerge.p1, Decl(typeFromPropertyAssignment29.ts, 37, 1)) +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) +>p1 : Symbol(ExpandoMerge.p1, Decl(typeFromPropertyAssignment29.ts, 37, 1)) + +namespace ExpandoMerge { +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) + + export var p2 = 222; +>p2 : Symbol(p2, Decl(typeFromPropertyAssignment29.ts, 40, 14)) +} +namespace ExpandoMerge { +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) + + export var p3 = 333; +>p3 : Symbol(p3, Decl(typeFromPropertyAssignment29.ts, 43, 14)) +} +var n = ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1); +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 17, 3), Decl(typeFromPropertyAssignment29.ts, 45, 3), Decl(typeFromPropertyAssignment29.ts, 63, 3), Decl(typeFromPropertyAssignment29.ts, 73, 3) ... and 1 more) +>ExpandoMerge.p1 : Symbol(ExpandoMerge.p1, Decl(typeFromPropertyAssignment29.ts, 37, 1)) +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) +>p1 : Symbol(ExpandoMerge.p1, Decl(typeFromPropertyAssignment29.ts, 37, 1)) +>ExpandoMerge.p2 : Symbol(ExpandoMerge.p2, Decl(typeFromPropertyAssignment29.ts, 40, 14)) +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) +>p2 : Symbol(ExpandoMerge.p2, Decl(typeFromPropertyAssignment29.ts, 40, 14)) +>ExpandoMerge.p3 : Symbol(ExpandoMerge.p3, Decl(typeFromPropertyAssignment29.ts, 43, 14)) +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) +>p3 : Symbol(ExpandoMerge.p3, Decl(typeFromPropertyAssignment29.ts, 43, 14)) +>ExpandoMerge : Symbol(ExpandoMerge, Decl(typeFromPropertyAssignment29.ts, 33, 24), Decl(typeFromPropertyAssignment29.ts, 38, 21), Decl(typeFromPropertyAssignment29.ts, 41, 1)) + +namespace Ns { +>Ns : Symbol(Ns, Decl(typeFromPropertyAssignment29.ts, 45, 78)) + + function ExpandoNamespace(): void {} +>ExpandoNamespace : Symbol(ExpandoNamespace, Decl(typeFromPropertyAssignment29.ts, 47, 14)) + + ExpandoNamespace.p6 = 42; +>ExpandoNamespace.p6 : Symbol(ExpandoNamespace.p6, Decl(typeFromPropertyAssignment29.ts, 48, 40)) +>ExpandoNamespace : Symbol(ExpandoNamespace, Decl(typeFromPropertyAssignment29.ts, 47, 14)) +>p6 : Symbol(ExpandoNamespace.p6, Decl(typeFromPropertyAssignment29.ts, 48, 40)) + + export function foo() { +>foo : Symbol(foo, Decl(typeFromPropertyAssignment29.ts, 49, 29)) + + return ExpandoNamespace; +>ExpandoNamespace : Symbol(ExpandoNamespace, Decl(typeFromPropertyAssignment29.ts, 47, 14)) + } +} + // Should not work in Typescript -- must be const var ExpandoExpr2 = function (n: number) { ->ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 26, 3), Decl(typeFromPropertyAssignment29.ts, 29, 21)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 26, 29)) +>ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 56, 3), Decl(typeFromPropertyAssignment29.ts, 59, 21)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 56, 29)) return n.toString(); >n.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 26, 29)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 56, 29)) >toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) } ExpandoExpr2.prop = 2 ->ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 26, 3), Decl(typeFromPropertyAssignment29.ts, 29, 21)) +>ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 56, 3), Decl(typeFromPropertyAssignment29.ts, 59, 21)) ExpandoExpr2.m = function(n: number) { ->ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 26, 3), Decl(typeFromPropertyAssignment29.ts, 29, 21)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 30, 26)) +>ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 56, 3), Decl(typeFromPropertyAssignment29.ts, 59, 21)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 60, 26)) return n + 1; ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 30, 26)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 60, 26)) } var n = ExpandoExpr2.prop + ExpandoExpr2.m(12) + ExpandoExpr2(101).length ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 16, 3), Decl(typeFromPropertyAssignment29.ts, 33, 3), Decl(typeFromPropertyAssignment29.ts, 43, 3), Decl(typeFromPropertyAssignment29.ts, 53, 3)) ->ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 26, 3), Decl(typeFromPropertyAssignment29.ts, 29, 21)) ->ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 26, 3), Decl(typeFromPropertyAssignment29.ts, 29, 21)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 17, 3), Decl(typeFromPropertyAssignment29.ts, 45, 3), Decl(typeFromPropertyAssignment29.ts, 63, 3), Decl(typeFromPropertyAssignment29.ts, 73, 3) ... and 1 more) +>ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 56, 3), Decl(typeFromPropertyAssignment29.ts, 59, 21)) +>ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 56, 3), Decl(typeFromPropertyAssignment29.ts, 59, 21)) >ExpandoExpr2(101).length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) ->ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 26, 3), Decl(typeFromPropertyAssignment29.ts, 29, 21)) +>ExpandoExpr2 : Symbol(ExpandoExpr2, Decl(typeFromPropertyAssignment29.ts, 56, 3), Decl(typeFromPropertyAssignment29.ts, 59, 21)) >length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) // Should not work in typescript -- classes already have statics class ExpandoClass { ->ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 33, 73)) +>ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 63, 73)) n = 1001; ->n : Symbol(ExpandoClass.n, Decl(typeFromPropertyAssignment29.ts, 36, 20)) +>n : Symbol(ExpandoClass.n, Decl(typeFromPropertyAssignment29.ts, 66, 20)) } ExpandoClass.prop = 2 ->ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 33, 73)) +>ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 63, 73)) ExpandoClass.m = function(n: number) { ->ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 33, 73)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 40, 26)) +>ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 63, 73)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 70, 26)) return n + 1; ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 40, 26)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 70, 26)) } var n = ExpandoClass.prop + ExpandoClass.m(12) + new ExpandoClass().n ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 16, 3), Decl(typeFromPropertyAssignment29.ts, 33, 3), Decl(typeFromPropertyAssignment29.ts, 43, 3), Decl(typeFromPropertyAssignment29.ts, 53, 3)) ->ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 33, 73)) ->ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 33, 73)) ->new ExpandoClass().n : Symbol(ExpandoClass.n, Decl(typeFromPropertyAssignment29.ts, 36, 20)) ->ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 33, 73)) ->n : Symbol(ExpandoClass.n, Decl(typeFromPropertyAssignment29.ts, 36, 20)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 17, 3), Decl(typeFromPropertyAssignment29.ts, 45, 3), Decl(typeFromPropertyAssignment29.ts, 63, 3), Decl(typeFromPropertyAssignment29.ts, 73, 3) ... and 1 more) +>ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 63, 73)) +>ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 63, 73)) +>new ExpandoClass().n : Symbol(ExpandoClass.n, Decl(typeFromPropertyAssignment29.ts, 66, 20)) +>ExpandoClass : Symbol(ExpandoClass, Decl(typeFromPropertyAssignment29.ts, 63, 73)) +>n : Symbol(ExpandoClass.n, Decl(typeFromPropertyAssignment29.ts, 66, 20)) // Class expressions shouldn't work in typescript either var ExpandoExpr3 = class { ->ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 46, 3)) +>ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 76, 3)) n = 10001; ->n : Symbol(ExpandoExpr3.n, Decl(typeFromPropertyAssignment29.ts, 46, 26)) +>n : Symbol(ExpandoExpr3.n, Decl(typeFromPropertyAssignment29.ts, 76, 26)) } ExpandoExpr3.prop = 3 ->ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 46, 3)) +>ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 76, 3)) ExpandoExpr3.m = function(n: number) { ->ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 46, 3)) ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 50, 26)) +>ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 76, 3)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 80, 26)) return n + 1; ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 50, 26)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 80, 26)) } var n = ExpandoExpr3.prop + ExpandoExpr3.m(13) + new ExpandoExpr3().n ->n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 16, 3), Decl(typeFromPropertyAssignment29.ts, 33, 3), Decl(typeFromPropertyAssignment29.ts, 43, 3), Decl(typeFromPropertyAssignment29.ts, 53, 3)) ->ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 46, 3)) ->ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 46, 3)) ->new ExpandoExpr3().n : Symbol(ExpandoExpr3.n, Decl(typeFromPropertyAssignment29.ts, 46, 26)) ->ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 46, 3)) ->n : Symbol(ExpandoExpr3.n, Decl(typeFromPropertyAssignment29.ts, 46, 26)) +>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 17, 3), Decl(typeFromPropertyAssignment29.ts, 45, 3), Decl(typeFromPropertyAssignment29.ts, 63, 3), Decl(typeFromPropertyAssignment29.ts, 73, 3) ... and 1 more) +>ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 76, 3)) +>ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 76, 3)) +>new ExpandoExpr3().n : Symbol(ExpandoExpr3.n, Decl(typeFromPropertyAssignment29.ts, 76, 26)) +>ExpandoExpr3 : Symbol(ExpandoExpr3, Decl(typeFromPropertyAssignment29.ts, 76, 3)) +>n : Symbol(ExpandoExpr3.n, Decl(typeFromPropertyAssignment29.ts, 76, 26)) diff --git a/tests/baselines/reference/typeFromPropertyAssignment29.types b/tests/baselines/reference/typeFromPropertyAssignment29.types index eaf8ed66123..1421ec885c5 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment29.types +++ b/tests/baselines/reference/typeFromPropertyAssignment29.types @@ -48,8 +48,8 @@ var n = ExpandoDecl.prop + ExpandoDecl.m(12) + ExpandoDecl(101).length >length : number const ExpandoExpr = function (n: number) { ->ExpandoExpr : { (n: number): string; prop: number; m(n: number): number; } ->function (n: number) { return n.toString();} : { (n: number): string; prop: number; m(n: number): number; } +>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } +>function (n: number) { return n.toString();} : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } >n : number return n.toString(); @@ -58,17 +58,28 @@ const ExpandoExpr = function (n: number) { >n : number >toString : (radix?: number) => string } -ExpandoExpr.prop = 2 ->ExpandoExpr.prop = 2 : 2 ->ExpandoExpr.prop : number ->ExpandoExpr : { (n: number): string; prop: number; m(n: number): number; } ->prop : number +ExpandoExpr.prop = { x: 2 } +>ExpandoExpr.prop = { x: 2 } : { x: number; } +>ExpandoExpr.prop : { x: number; y?: undefined; } | { y: string; x?: undefined; } +>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } +>prop : { x: number; y?: undefined; } | { y: string; x?: undefined; } +>{ x: 2 } : { x: number; } +>x : number >2 : 2 +ExpandoExpr.prop = { y: "" } +>ExpandoExpr.prop = { y: "" } : { y: string; } +>ExpandoExpr.prop : { x: number; y?: undefined; } | { y: string; x?: undefined; } +>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } +>prop : { x: number; y?: undefined; } | { y: string; x?: undefined; } +>{ y: "" } : { y: string; } +>y : string +>"" : "" + ExpandoExpr.m = function(n: number) { >ExpandoExpr.m = function(n: number) { return n + 1;} : (n: number) => number >ExpandoExpr.m : (n: number) => number ->ExpandoExpr : { (n: number): string; prop: number; m(n: number): number; } +>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } >m : (n: number) => number >function(n: number) { return n + 1;} : (n: number) => number >n : number @@ -78,21 +89,26 @@ ExpandoExpr.m = function(n: number) { >n : number >1 : 1 } -var n = ExpandoExpr.prop + ExpandoExpr.m(12) + ExpandoExpr(101).length +var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length >n : number ->ExpandoExpr.prop + ExpandoExpr.m(12) + ExpandoExpr(101).length : number ->ExpandoExpr.prop + ExpandoExpr.m(12) : number ->ExpandoExpr.prop : number ->ExpandoExpr : { (n: number): string; prop: number; m(n: number): number; } ->prop : number +>(ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length : number +>(ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) : number +>(ExpandoExpr.prop.x || 0) : 0 +>ExpandoExpr.prop.x || 0 : 0 +>ExpandoExpr.prop.x : undefined +>ExpandoExpr.prop : { y: string; x?: undefined; } +>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } +>prop : { y: string; x?: undefined; } +>x : undefined +>0 : 0 >ExpandoExpr.m(12) : number >ExpandoExpr.m : (n: number) => number ->ExpandoExpr : { (n: number): string; prop: number; m(n: number): number; } +>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } >m : (n: number) => number >12 : 12 >ExpandoExpr(101).length : number >ExpandoExpr(101) : string ->ExpandoExpr : { (n: number): string; prop: number; m(n: number): number; } +>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; } >101 : 101 >length : number @@ -127,6 +143,110 @@ ExpandoArrow.m = function(n: number) { } +function ExpandoNested(n: number) { +>ExpandoNested : { (n: number): { (m: number): number; total: number; }; also: number; } +>n : number + + const nested = function (m: number) { +>nested : { (m: number): number; total: number; } +>function (m: number) { return n + m; } : { (m: number): number; total: number; } +>m : number + + return n + m; +>n + m : number +>n : number +>m : number + + }; + nested.total = n + 1_000_000; +>nested.total = n + 1_000_000 : number +>nested.total : number +>nested : { (m: number): number; total: number; } +>total : number +>n + 1_000_000 : number +>n : number +>1_000_000 : 1000000 + + return nested; +>nested : { (m: number): number; total: number; } +} +ExpandoNested.also = -1; +>ExpandoNested.also = -1 : -1 +>ExpandoNested.also : number +>ExpandoNested : { (n: number): { (m: number): number; total: number; }; also: number; } +>also : number +>-1 : -1 +>1 : 1 + +function ExpandoMerge(n: number) { +>ExpandoMerge : typeof ExpandoMerge +>n : number + + return n * 100; +>n * 100 : number +>n : number +>100 : 100 +} +ExpandoMerge.p1 = 111 +>ExpandoMerge.p1 = 111 : 111 +>ExpandoMerge.p1 : number +>ExpandoMerge : typeof ExpandoMerge +>p1 : number +>111 : 111 + +namespace ExpandoMerge { +>ExpandoMerge : typeof ExpandoMerge + + export var p2 = 222; +>p2 : number +>222 : 222 +} +namespace ExpandoMerge { +>ExpandoMerge : typeof ExpandoMerge + + export var p3 = 333; +>p3 : number +>333 : 333 +} +var n = ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1); +>n : number +>ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1) : number +>ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 : number +>ExpandoMerge.p1 + ExpandoMerge.p2 : number +>ExpandoMerge.p1 : number +>ExpandoMerge : typeof ExpandoMerge +>p1 : number +>ExpandoMerge.p2 : number +>ExpandoMerge : typeof ExpandoMerge +>p2 : number +>ExpandoMerge.p3 : number +>ExpandoMerge : typeof ExpandoMerge +>p3 : number +>ExpandoMerge(1) : number +>ExpandoMerge : typeof ExpandoMerge +>1 : 1 + +namespace Ns { +>Ns : typeof Ns + + function ExpandoNamespace(): void {} +>ExpandoNamespace : { (): void; p6: number; } + + ExpandoNamespace.p6 = 42; +>ExpandoNamespace.p6 = 42 : 42 +>ExpandoNamespace.p6 : number +>ExpandoNamespace : { (): void; p6: number; } +>p6 : number +>42 : 42 + + export function foo() { +>foo : () => { (): void; p6: number; } + + return ExpandoNamespace; +>ExpandoNamespace : { (): void; p6: number; } + } +} + // Should not work in Typescript -- must be const var ExpandoExpr2 = function (n: number) { >ExpandoExpr2 : (n: number) => string diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts index 70199b00398..1882731c8f1 100644 --- a/tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts @@ -1,3 +1,4 @@ +// @declaration: true function ExpandoDecl(n: number) { return n.toString(); } @@ -10,11 +11,12 @@ var n = ExpandoDecl.prop + ExpandoDecl.m(12) + ExpandoDecl(101).length const ExpandoExpr = function (n: number) { return n.toString(); } -ExpandoExpr.prop = 2 +ExpandoExpr.prop = { x: 2 } +ExpandoExpr.prop = { y: "" } ExpandoExpr.m = function(n: number) { return n + 1; } -var n = ExpandoExpr.prop + ExpandoExpr.m(12) + ExpandoExpr(101).length +var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length const ExpandoArrow = (n: number) => n.toString(); ExpandoArrow.prop = 2 @@ -23,6 +25,35 @@ ExpandoArrow.m = function(n: number) { } +function ExpandoNested(n: number) { + const nested = function (m: number) { + return n + m; + }; + nested.total = n + 1_000_000; + return nested; +} +ExpandoNested.also = -1; + +function ExpandoMerge(n: number) { + return n * 100; +} +ExpandoMerge.p1 = 111 +namespace ExpandoMerge { + export var p2 = 222; +} +namespace ExpandoMerge { + export var p3 = 333; +} +var n = ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1); + +namespace Ns { + function ExpandoNamespace(): void {} + ExpandoNamespace.p6 = 42; + export function foo() { + return ExpandoNamespace; + } +} + // Should not work in Typescript -- must be const var ExpandoExpr2 = function (n: number) { return n.toString(); From 0a59da1a2cfe2e035c197f8cf206cdc4eb18f95e Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 27 Aug 2018 10:30:25 -0700 Subject: [PATCH 53/77] In pickLongestCandidateSignature, instantiate using inferred type arguments (#26646) --- src/compiler/checker.ts | 53 ++++++++++++------- .../fourslash/quickInfoCanBeTruncated.ts | 2 +- .../signatureHelpExplicitTypeArguments.ts | 2 +- .../cases/fourslash/signatureHelpInference.ts | 12 +++++ .../fourslash/trailingCommaSignatureHelp.ts | 2 +- 5 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 tests/cases/fourslash/signatureHelpInference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a3cd01e3583..a551108f75c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18638,7 +18638,7 @@ namespace ts { return getInferredTypes(context); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, excludeArgument: boolean[] | undefined, context: InferenceContext): Type[] { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, excludeArgument: ReadonlyArray | undefined, context: InferenceContext): Type[] { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (const inference of context.inferences) { // As an optimization, we don't have to clear (and later recompute) inferred types @@ -19052,19 +19052,7 @@ namespace ts { // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - let excludeArgument: boolean[] | undefined; - if (!isDecorator && !isSingleNonGenericCandidate) { - // We do not need to call `getEffectiveArgumentCount` here as it only - // applies when calculating the number of arguments for a decorator. - for (let i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - } + let excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the @@ -19227,6 +19215,21 @@ namespace ts { } } + function getExcludeArgument(args: ReadonlyArray): boolean[] | undefined { + let excludeArgument: boolean[] | undefined; + // We do not need to call `getEffectiveArgumentCount` here as it only + // applies when calculating the number of arguments for a decorator. + for (let i = 0; i < args.length; i++) { + if (isContextSensitive(args[i])) { + if (!excludeArgument) { + excludeArgument = new Array(args.length); + } + excludeArgument[i] = true; + } + } + return excludeArgument; + } + // No signature was applicable. We have already reported the errors for the invalid signature. // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. function getCandidateForOverloadFailure( @@ -19305,17 +19308,29 @@ namespace ts { return candidate; } - const typeArgumentNodes: ReadonlyArray = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments || emptyArray : emptyArray; + const typeArgumentNodes: ReadonlyArray | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined; + const instantiated = typeArgumentNodes + ? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJavaScriptFile(node))) + : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args); + candidates[bestIndex] = instantiated; + return instantiated; + } + + function getTypeArgumentsFromNodes(typeArgumentNodes: ReadonlyArray, typeParameters: ReadonlyArray, isJs: boolean): ReadonlyArray { const typeArguments = typeArgumentNodes.map(getTypeOfNode); while (typeArguments.length > typeParameters.length) { typeArguments.pop(); } while (typeArguments.length < typeParameters.length) { - typeArguments.push(getConstraintOfTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node))); + typeArguments.push(getConstraintOfTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isJs)); } - const instantiated = createSignatureInstantiation(candidate, typeArguments); - candidates[bestIndex] = instantiated; - return instantiated; + return typeArguments; + } + + function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: ReadonlyArray, candidate: Signature, args: ReadonlyArray): Signature { + const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); + const typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + return createSignatureInstantiation(candidate, typeArgumentTypes); } function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number { diff --git a/tests/cases/fourslash/quickInfoCanBeTruncated.ts b/tests/cases/fourslash/quickInfoCanBeTruncated.ts index bdf64323636..25ca216a075 100644 --- a/tests/cases/fourslash/quickInfoCanBeTruncated.ts +++ b/tests/cases/fourslash/quickInfoCanBeTruncated.ts @@ -519,7 +519,7 @@ verify.quickInfoIs(`type Less = "_1" | "_2" | "_3" | "_4" | "_5" | "_6" | "_7" | goTo.marker("3"); verify.signatureHelp({ marker: "3", - text: `f(s: "_0" | "_1" | "_2" | "_3" | "_4" | "_5" | "_6" | "_7" | "_8" | "_9" | "_10" | "_11" | "_12" | "_13" | "_14" | "_15" | "_16" | "_17" | "_18" | "_19" | "_20" | "_21" | "_22" | "_23" | "_24" | ... 474 more ... | "_499", x: never, y: string): void` + text: `f(s: "_499", x: "_0" | "_1" | "_2" | "_3" | "_4" | "_5" | "_6" | "_7" | "_8" | "_9" | "_10" | "_11" | "_12" | "_13" | "_14" | "_15" | "_16" | "_17" | "_18" | "_19" | "_20" | "_21" | "_22" | "_23" | "_24" | ... 473 more ... | "_498", y: string): void` }); goTo.marker("4"); verify.quickInfoIs(`type Decomposed = { diff --git a/tests/cases/fourslash/signatureHelpExplicitTypeArguments.ts b/tests/cases/fourslash/signatureHelpExplicitTypeArguments.ts index 2511cfecc19..b1af18469a8 100644 --- a/tests/cases/fourslash/signatureHelpExplicitTypeArguments.ts +++ b/tests/cases/fourslash/signatureHelpExplicitTypeArguments.ts @@ -8,7 +8,7 @@ verify.signatureHelp( { marker: "1", text: "f(x: number, y: string): number" }, - { marker: "2", text: "f(x: {}, y: {}): {}" }, + { marker: "2", text: "f(x: boolean, y: string): boolean" }, // too few -- fill in rest with {} { marker: "3", text: "f(x: number, y: {}): number" }, // too many -- ignore extra type arguments diff --git a/tests/cases/fourslash/signatureHelpInference.ts b/tests/cases/fourslash/signatureHelpInference.ts new file mode 100644 index 00000000000..186dba9c31d --- /dev/null +++ b/tests/cases/fourslash/signatureHelpInference.ts @@ -0,0 +1,12 @@ +/// + +////declare function f(a: T, b: T, c: T): void; +////f("x", /**/); + +verify.signatureHelp({ + marker: "", + text: 'f(a: "x", b: "x", c: "x"): void', + parameterCount: 3, + parameterName: "b", + parameterSpan: 'b: "x"', +}); diff --git a/tests/cases/fourslash/trailingCommaSignatureHelp.ts b/tests/cases/fourslash/trailingCommaSignatureHelp.ts index 362f7145c03..e22ea1c33d3 100644 --- a/tests/cases/fourslash/trailingCommaSignatureHelp.ts +++ b/tests/cases/fourslash/trailingCommaSignatureHelp.ts @@ -25,6 +25,6 @@ verify.signatureHelp( }, { marker: "b", - text: "f(a: {}): {}", + text: "f(a: 2): 2", }, ); From 0dbad04c3fa77c4a41c78d559ffd5aa1e1ee4b1c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 27 Aug 2018 13:32:01 -0700 Subject: [PATCH 54/77] Distribute indexed accesses when simplifying them (#26281) * unknownify accesses * Move to simplify to break less with fewer changes * Accept baselines for now * Always propegate any as an index type * Fix flow control in the presence of simplifiable types * Add spy repro from #25181 * Retain errorType when it is used as a marker for the lack of a constraint * Small refinement * Add new test * Move most potentially recursive types from isIdenticalTo into structuredTypeRelatedTo to match the non-identity relations * Fix nits * Doesnt need to be undefineable at all --- src/compiler/checker.ts | 157 ++++++++---------- .../reference/assignmentCompatForEnums.types | 2 +- ...entedTypeBracketAccessIndexSignature.types | 8 +- ...mentedTypeBracketNamedPropertyAccess.types | 4 +- .../reference/binaryIntegerLiteral.types | 6 +- .../reference/binaryIntegerLiteralES6.types | 6 +- ...larlySimplifyingConditionalTypesNoCrash.js | 55 ++++++ ...SimplifyingConditionalTypesNoCrash.symbols | 154 +++++++++++++++++ ...lySimplifyingConditionalTypesNoCrash.types | 92 ++++++++++ ...onditionalTypesExcessProperties.errors.txt | 10 +- .../reference/defaultIndexProps2.types | 2 +- .../deferredLookupTypeResolution2.errors.txt | 31 ---- tests/baselines/reference/enumBasics.types | 4 +- tests/baselines/reference/enumIndexer.types | 2 +- ...edAccessMethodIntersectionCanBeAccessed.js | 31 ++++ ...essMethodIntersectionCanBeAccessed.symbols | 69 ++++++++ ...ccessMethodIntersectionCanBeAccessed.types | 59 +++++++ .../reference/indexClassByNumber.types | 2 +- .../indexedAccessRelation.errors.txt | 37 +++++ .../reference/indexedAccessRelation.types | 2 +- .../reference/indexingTypesWithNever.types | 4 +- .../limitDeepInstantiations.errors.txt | 5 +- .../reference/limitDeepInstantiations.types | 2 +- ...5LibES6ArrayLibES6WellknownSymbolLib.types | 2 +- .../reference/newWithSpreadES5.types | 18 +- .../reference/newWithSpreadES6.types | 18 +- .../noImplicitAnyIndexingSuppressed.types | 16 +- .../nonPrimitiveIndexingWithForIn.types | 4 +- ...imitiveIndexingWithForInSupressError.types | 4 +- .../reference/numericIndexingResults.types | 28 ++-- ...atureHidingMembersOfExtendedFunction.types | 8 +- ...atureHidingMembersOfExtendedFunction.types | 8 +- ...ringNamedPropertyOfIllegalCharacters.types | 16 +- .../reference/octalIntegerLiteral.types | 6 +- .../reference/octalIntegerLiteralES6.types | 6 +- .../protoAsIndexInIndexExpression.types | 2 +- .../baselines/reference/protoInIndexer.types | 2 +- .../spyComparisonChecking.errors.txt | 29 ++++ .../reference/spyComparisonChecking.js | 34 ++++ .../reference/spyComparisonChecking.symbols | 75 +++++++++ .../reference/spyComparisonChecking.types | 62 +++++++ .../reference/superSymbolIndexedAccess1.types | 4 +- .../reference/superSymbolIndexedAccess5.types | 4 +- .../reference/superSymbolIndexedAccess6.types | 4 +- .../reference/symbolProperty55.types | 2 +- .../reference/symbolProperty56.types | 4 +- .../reference/symbolProperty57.types | 4 +- .../reference/systemJsForInNoException.types | 2 +- .../templateStringInIndexExpression.types | 2 +- .../templateStringInIndexExpressionES6.types | 2 +- ...sIndexOnExistingReadonlyFieldIsNotNever.js | 60 +++++++ ...xOnExistingReadonlyFieldIsNotNever.symbols | 76 +++++++++ ...dexOnExistingReadonlyFieldIsNotNever.types | 57 +++++++ .../reference/unionTypeIndexSignature.types | 20 +-- .../varianceCallbacksAndIndexedAccesses.js | 36 ++++ ...arianceCallbacksAndIndexedAccesses.symbols | 121 ++++++++++++++ .../varianceCallbacksAndIndexedAccesses.types | 81 +++++++++ ...larlySimplifyingConditionalTypesNoCrash.ts | 48 ++++++ ...edAccessMethodIntersectionCanBeAccessed.ts | 20 +++ tests/cases/compiler/spyComparisonChecking.ts | 23 +++ ...sIndexOnExistingReadonlyFieldIsNotNever.ts | 22 +++ .../varianceCallbacksAndIndexedAccesses.ts | 32 ++++ 62 files changed, 1462 insertions(+), 244 deletions(-) create mode 100644 tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.js create mode 100644 tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.symbols create mode 100644 tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types delete mode 100644 tests/baselines/reference/deferredLookupTypeResolution2.errors.txt create mode 100644 tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.js create mode 100644 tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.symbols create mode 100644 tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.types create mode 100644 tests/baselines/reference/indexedAccessRelation.errors.txt create mode 100644 tests/baselines/reference/spyComparisonChecking.errors.txt create mode 100644 tests/baselines/reference/spyComparisonChecking.js create mode 100644 tests/baselines/reference/spyComparisonChecking.symbols create mode 100644 tests/baselines/reference/spyComparisonChecking.types create mode 100644 tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.js create mode 100644 tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.symbols create mode 100644 tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.types create mode 100644 tests/baselines/reference/varianceCallbacksAndIndexedAccesses.js create mode 100644 tests/baselines/reference/varianceCallbacksAndIndexedAccesses.symbols create mode 100644 tests/baselines/reference/varianceCallbacksAndIndexedAccesses.types create mode 100644 tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts create mode 100644 tests/cases/compiler/genericIndexedAccessMethodIntersectionCanBeAccessed.ts create mode 100644 tests/cases/compiler/spyComparisonChecking.ts create mode 100644 tests/cases/compiler/thisIndexOnExistingReadonlyFieldIsNotNever.ts create mode 100644 tests/cases/compiler/varianceCallbacksAndIndexedAccesses.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a551108f75c..9c0f3cd643f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6901,7 +6901,7 @@ namespace ts { function getConstraintOfIndexedAccess(type: IndexedAccessType) { const objectType = getBaseConstraintOfType(type.objectType) || type.objectType; const indexType = getBaseConstraintOfType(type.indexType) || type.indexType; - const constraint = !isGenericObjectType(objectType) && !isGenericIndexType(indexType) ? getIndexedAccessType(objectType, indexType) : undefined; + const constraint = !isGenericObjectType(objectType) && !isGenericIndexType(indexType) ? getIndexedAccessType(objectType, indexType, /*accessNode*/ undefined, errorType) : undefined; return constraint && constraint !== errorType ? constraint : undefined; } @@ -7064,7 +7064,7 @@ namespace ts { if (t.flags & TypeFlags.IndexedAccess) { const baseObjectType = getBaseConstraint((t).objectType); const baseIndexType = getBaseConstraint((t).indexType); - const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType) : undefined; + const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType, /*accessNode*/ undefined, errorType) : undefined; return baseIndexedAccess && baseIndexedAccess !== errorType ? getBaseConstraint(baseIndexedAccess) : undefined; } if (t.flags & TypeFlags.Conditional) { @@ -9149,7 +9149,7 @@ namespace ts { return false; } - function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | undefined, cacheSymbol: boolean) { + function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | undefined, cacheSymbol: boolean, missingType: Type) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = isTypeUsableAsLateBoundName(indexType) ? getLateBoundNameFromType(indexType) : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? @@ -9162,7 +9162,7 @@ namespace ts { markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword); if (isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) { error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, symbolToString(prop)); - return errorType; + return missingType; } if (cacheSymbol) { getNodeLinks(accessNode!).resolvedSymbol = prop; @@ -9221,7 +9221,7 @@ namespace ts { } } } - return anyType; + return missingType; } } if (isJSLiteralType(objectType)) { @@ -9239,7 +9239,10 @@ namespace ts { error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); } } - return errorType; + if (isTypeAny(indexType)) { + return indexType; + } + return missingType; } function isGenericObjectType(type: Type): boolean { @@ -9250,22 +9253,6 @@ namespace ts { return maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive | TypeFlags.Index); } - // Return true if the given type is a non-generic object type with a string index signature and no - // other members. - function isStringIndexOnlyType(type: Type): boolean { - if (type.flags & TypeFlags.Object && !isGenericMappedType(type)) { - const t = resolveStructuredTypeMembers(type); - return t.properties.length === 0 && - t.callSignatures.length === 0 && t.constructSignatures.length === 0 && - !!t.stringIndexInfo && !t.numberIndexInfo; - } - return false; - } - - function isMappedTypeToNever(type: Type): boolean { - return !!(getObjectFlags(type) & ObjectFlags.Mapped) && getTemplateTypeFromMappedType(type as MappedType) === neverType; - } - function getSimplifiedType(type: Type): Type { return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type) : type; } @@ -9280,35 +9267,12 @@ namespace ts { // We recursively simplify the object type as it may in turn be an indexed access type. For example, with // '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type. const objectType = getSimplifiedType(type.objectType); - if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType)) { - // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or - // more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a - // transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed - // access types with default property values as expressed by D. - if (some((objectType).types, isStringIndexOnlyType)) { - const regularTypes: Type[] = []; - const stringIndexTypes: Type[] = []; - for (const t of (objectType).types) { - if (isStringIndexOnlyType(t)) { - stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String)!); - } - else { - regularTypes.push(t); - } - } - return type.simplified = getUnionType([ - getSimplifiedType(getIndexedAccessType(getIntersectionType(regularTypes), type.indexType)), - getIntersectionType(stringIndexTypes) - ]); - } - // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or - // more mapped types with a template type `never`, '(U & V & { [P in T]: never })[K]', return a - // transformed type that removes the never-mapped type: '(U & V)[K]'. This mirrors what would happen - // eventually anyway, but it easier to reason about. - if (some((objectType).types, isMappedTypeToNever)) { - const nonNeverTypes = filter((objectType).types, t => !isMappedTypeToNever(t)); - return type.simplified = getSimplifiedType(getIndexedAccessType(getIntersectionType(nonNeverTypes), type.indexType)); - } + const indexType = getSimplifiedType(type.indexType); + if (objectType.flags & TypeFlags.Union) { + return type.simplified = mapType(objectType, t => getSimplifiedType(getIndexedAccessType(t, indexType))); + } + if (objectType.flags & TypeFlags.Intersection) { + return type.simplified = getIntersectionType(map((objectType as IntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType)))); } // If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper // that substitutes the index type for P. For example, for an index access { [P in K]: Box }[X], we @@ -9332,7 +9296,7 @@ namespace ts { return instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper); } - function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode): Type { + function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode, missingType = accessNode ? errorType : unknownType): Type { if (objectType === wildcardType || indexType === wildcardType) { return wildcardType; } @@ -9360,15 +9324,15 @@ namespace ts { if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) { const propTypes: Type[] = []; for (const t of (indexType).types) { - const propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, /*cacheSymbol*/ false); - if (propType === errorType) { - return errorType; + const propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, /*cacheSymbol*/ false, missingType); + if (propType === missingType) { + return missingType; } propTypes.push(propType); } return getUnionType(propTypes); } - return getPropertyTypeForIndexType(apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true); + return getPropertyTypeForIndexType(apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true, missingType); } function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) { @@ -10532,8 +10496,12 @@ namespace ts { return false; } + function isOrHasGenericConditional(type: Type): boolean { + return !!(type.flags & TypeFlags.Conditional || (type.flags & TypeFlags.Intersection && some((type as IntersectionType).types, isOrHasGenericConditional))); + } + function elaborateError(node: Expression | undefined, source: Type, target: Type): boolean { - if (!node) return false; + if (!node || isOrHasGenericConditional(target)) return false; switch (node.kind) { case SyntaxKind.JsxExpression: case SyntaxKind.ParenthesizedExpression: @@ -10566,9 +10534,9 @@ namespace ts { let reportedError = false; for (let status = iterator.next(); !status.done; status = iterator.next()) { const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value; - const sourcePropType = getIndexedAccessType(source, nameType); - const targetPropType = getIndexedAccessType(target, nameType); - if (!isTypeAssignableTo(sourcePropType, targetPropType)) { + const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType); + const targetPropType = getIndexedAccessType(target, nameType, /*accessNode*/ undefined, errorType); + if (sourcePropType !== errorType && targetPropType !== errorType && !isTypeAssignableTo(sourcePropType, targetPropType)) { const elaborated = next && elaborateError(next, sourcePropType, targetPropType); if (elaborated) { reportedError = true; @@ -11287,7 +11255,7 @@ namespace ts { function isIdenticalTo(source: Type, target: Type): Ternary { let result: Ternary; const flags = source.flags & target.flags; - if (flags & TypeFlags.Object) { + if (flags & TypeFlags.Object || flags & TypeFlags.IndexedAccess || flags & TypeFlags.Conditional || flags & TypeFlags.Index || flags & TypeFlags.Substitution) { return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false); } if (flags & (TypeFlags.Union | TypeFlags.Intersection)) { @@ -11297,32 +11265,6 @@ namespace ts { } } } - if (flags & TypeFlags.Index) { - return isRelatedTo((source).type, (target).type, /*reportErrors*/ false); - } - if (flags & TypeFlags.IndexedAccess) { - if (result = isRelatedTo((source).objectType, (target).objectType, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source).indexType, (target).indexType, /*reportErrors*/ false)) { - return result; - } - } - } - if (flags & TypeFlags.Conditional) { - if ((source).root.isDistributive === (target).root.isDistributive) { - if (result = isRelatedTo((source).checkType, (target).checkType, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source).extendsType, (target).extendsType, /*reportErrors*/ false)) { - if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), /*reportErrors*/ false)) { - if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), /*reportErrors*/ false)) { - return result; - } - } - } - } - } - } - if (flags & TypeFlags.Substitution) { - return isRelatedTo((source).substitute, (target).substitute, /*reportErrors*/ false); - } return Ternary.False; } @@ -11634,6 +11576,37 @@ namespace ts { } function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary { + const flags = source.flags & target.flags; + if (relation === identityRelation && !(flags & TypeFlags.Object)) { + if (flags & TypeFlags.Index) { + return isRelatedTo((source).type, (target).type, /*reportErrors*/ false); + } + let result = Ternary.False; + if (flags & TypeFlags.IndexedAccess) { + if (result = isRelatedTo((source).objectType, (target).objectType, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source).indexType, (target).indexType, /*reportErrors*/ false)) { + return result; + } + } + } + if (flags & TypeFlags.Conditional) { + if ((source).root.isDistributive === (target).root.isDistributive) { + if (result = isRelatedTo((source).checkType, (target).checkType, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source).extendsType, (target).extendsType, /*reportErrors*/ false)) { + if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), /*reportErrors*/ false)) { + if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), /*reportErrors*/ false)) { + return result; + } + } + } + } + } + } + if (flags & TypeFlags.Substitution) { + return isRelatedTo((source).substitute, (target).substitute, /*reportErrors*/ false); + } + return Ternary.False; + } let result: Ternary; let originalErrorInfo: DiagnosticMessageChain | undefined; const saveErrorInfo = errorInfo; @@ -14151,10 +14124,10 @@ namespace ts { getInitialTypeOfBindingElement(node); } - function getInitialOrAssignedType(node: VariableDeclaration | BindingElement | Expression) { - return node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ? + function getInitialOrAssignedType(node: VariableDeclaration | BindingElement | Expression, reference: Node) { + return getConstraintForLocation(node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ? getInitialType(node) : - getAssignedType(node); + getAssignedType(node), reference); } function isEmptyArrayAssignment(node: VariableDeclaration | BindingElement | Expression) { @@ -14540,11 +14513,11 @@ namespace ts { if (isEmptyArrayAssignment(node)) { return getEvolvingArrayType(neverType); } - const assignedType = getBaseTypeOfLiteralType(getInitialOrAssignedType(node)); + const assignedType = getBaseTypeOfLiteralType(getInitialOrAssignedType(node, reference)); return isTypeAssignableTo(assignedType, declaredType) ? assignedType : anyArrayType; } if (declaredType.flags & TypeFlags.Union) { - return getAssignmentReducedType(declaredType, getInitialOrAssignedType(node)); + return getAssignmentReducedType(declaredType, getInitialOrAssignedType(node, reference)); } return declaredType; } diff --git a/tests/baselines/reference/assignmentCompatForEnums.types b/tests/baselines/reference/assignmentCompatForEnums.types index 8d2fdf0a8b3..6ad83f3d75e 100644 --- a/tests/baselines/reference/assignmentCompatForEnums.types +++ b/tests/baselines/reference/assignmentCompatForEnums.types @@ -23,7 +23,7 @@ function foo() { var x: TokenType = list['one']; >x : TokenType ->list['one'] : any +>list['one'] : error >list : {} >'one' : "one" } diff --git a/tests/baselines/reference/augmentedTypeBracketAccessIndexSignature.types b/tests/baselines/reference/augmentedTypeBracketAccessIndexSignature.types index eb23cfaa9e6..62e04728b39 100644 --- a/tests/baselines/reference/augmentedTypeBracketAccessIndexSignature.types +++ b/tests/baselines/reference/augmentedTypeBracketAccessIndexSignature.types @@ -16,14 +16,14 @@ interface Function { } var a = {}[0]; // Should be Foo ->a : any ->{}[0] : any +>a : error +>{}[0] : error >{} : {} >0 : 0 var b = (() => { })[0]; // Should be Bar ->b : any ->(() => { })[0] : any +>b : error +>(() => { })[0] : error >(() => { }) : () => void >() => { } : () => void >0 : 0 diff --git a/tests/baselines/reference/augmentedTypeBracketNamedPropertyAccess.types b/tests/baselines/reference/augmentedTypeBracketNamedPropertyAccess.types index eb90adefde2..81291506485 100644 --- a/tests/baselines/reference/augmentedTypeBracketNamedPropertyAccess.types +++ b/tests/baselines/reference/augmentedTypeBracketNamedPropertyAccess.types @@ -22,8 +22,8 @@ var r1 = o['data']; // Should be number >'data' : "data" var r2 = o['functionData']; // Should be any (no property found) ->r2 : any ->o['functionData'] : any +>r2 : error +>o['functionData'] : error >o : {} >'functionData' : "functionData" diff --git a/tests/baselines/reference/binaryIntegerLiteral.types b/tests/baselines/reference/binaryIntegerLiteral.types index 070ae22d796..1e2fc019e5f 100644 --- a/tests/baselines/reference/binaryIntegerLiteral.types +++ b/tests/baselines/reference/binaryIntegerLiteral.types @@ -79,7 +79,7 @@ obj1["26"]; // string >"26" : "26" obj1["0b11010"]; // any ->obj1["0b11010"] : any +>obj1["0b11010"] : error >obj1 : { 0b11010: string; a: number; bin1: number; b: number; 0B111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111101001010100000010111110001111111111: boolean; } >"0b11010" : "0b11010" @@ -119,7 +119,7 @@ obj2["26"]; // string >"26" : "26" obj2["0B11010"]; // any ->obj2["0B11010"] : any +>obj2["0B11010"] : error >obj2 : { 0B11010: string; a: number; bin2: number; b: number; 0B11111111111111111111111111111111111111111111111101001010100000010111110001111111111: boolean; } >"0B11010" : "0B11010" @@ -149,7 +149,7 @@ obj2["9.671406556917009e+24"]; // boolean >"9.671406556917009e+24" : "9.671406556917009e+24" obj2["Infinity"]; // any ->obj2["Infinity"] : any +>obj2["Infinity"] : error >obj2 : { 0B11010: string; a: number; bin2: number; b: number; 0B11111111111111111111111111111111111111111111111101001010100000010111110001111111111: boolean; } >"Infinity" : "Infinity" diff --git a/tests/baselines/reference/binaryIntegerLiteralES6.types b/tests/baselines/reference/binaryIntegerLiteralES6.types index fe9f65a1f71..78de8bd9fbc 100644 --- a/tests/baselines/reference/binaryIntegerLiteralES6.types +++ b/tests/baselines/reference/binaryIntegerLiteralES6.types @@ -79,7 +79,7 @@ obj1["26"]; // string >"26" : "26" obj1["0b11010"]; // any ->obj1["0b11010"] : any +>obj1["0b11010"] : error >obj1 : { 0b11010: string; a: number; bin1: number; b: number; 0B111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111101001010100000010111110001111111111: boolean; } >"0b11010" : "0b11010" @@ -119,7 +119,7 @@ obj2["26"]; // string >"26" : "26" obj2["0B11010"]; // any ->obj2["0B11010"] : any +>obj2["0B11010"] : error >obj2 : { 0B11010: string; a: number; bin2: number; b: number; 0B11111111111111111111111111111111111111111111111101001010100000010111110001111111111: boolean; } >"0B11010" : "0B11010" @@ -149,7 +149,7 @@ obj2["9.671406556917009e+24"]; // boolean >"9.671406556917009e+24" : "9.671406556917009e+24" obj2["Infinity"]; // any ->obj2["Infinity"] : any +>obj2["Infinity"] : error >obj2 : { 0B11010: string; a: number; bin2: number; b: number; 0B11111111111111111111111111111111111111111111111101001010100000010111110001111111111: boolean; } >"Infinity" : "Infinity" diff --git a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.js b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.js new file mode 100644 index 00000000000..724a8f8dbea --- /dev/null +++ b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.js @@ -0,0 +1,55 @@ +//// [circularlySimplifyingConditionalTypesNoCrash.ts] +type Omit = Pick>; + +type Shared< // Circularly self constraining type, defered thanks to mapping + InjectedProps, + DecorationTargetProps extends Shared + > = { + [P in Extract]: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; + }; + +interface ComponentClass

{ + defaultProps?: Partial

; // Inference target is also mapped _and_ optional +} + +interface InferableComponentEnhancerWithProps { +

>( + component: ComponentClass

+ ): ComponentClass> & TNeedsProps> & { WrappedComponent: ComponentClass

} +} // Then intersected with and indexed via Omit and & + +interface Connect { // Then strictly compared with another signature in its context + ( + mapStateToProps: unknown, + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: null | undefined, + mapDispatchToProps: unknown, + mergeProps: null | undefined, + options: unknown + ): InferableComponentEnhancerWithProps; +} + +declare var connect: Connect; + +const myStoreConnect: Connect = function( + mapStateToProps?: any, + mapDispatchToProps?: any, + mergeProps?: any, + options: unknown = {}, +) { + return connect( + mapStateToProps, + mapDispatchToProps, + mergeProps, + options, + ); +}; + +//// [circularlySimplifyingConditionalTypesNoCrash.js] +"use strict"; +var myStoreConnect = function (mapStateToProps, mapDispatchToProps, mergeProps, options) { + if (options === void 0) { options = {}; } + return connect(mapStateToProps, mapDispatchToProps, mergeProps, options); +}; diff --git a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.symbols b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.symbols new file mode 100644 index 00000000000..97abdadf2b3 --- /dev/null +++ b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.symbols @@ -0,0 +1,154 @@ +=== tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts === +type Omit = Pick>; +>Omit : Symbol(Omit, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 0)) +>T : Symbol(T, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 10)) +>K : Symbol(K, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 12)) +>T : Symbol(T, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 10)) +>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 10)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 10)) +>K : Symbol(K, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 12)) + +type Shared< // Circularly self constraining type, defered thanks to mapping +>Shared : Symbol(Shared, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 63)) + + InjectedProps, +>InjectedProps : Symbol(InjectedProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 2, 12)) + + DecorationTargetProps extends Shared +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 3, 18)) +>Shared : Symbol(Shared, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 63)) +>InjectedProps : Symbol(InjectedProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 2, 12)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 3, 18)) + + > = { + [P in Extract]: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 6, 9)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>InjectedProps : Symbol(InjectedProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 2, 12)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 3, 18)) +>InjectedProps : Symbol(InjectedProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 2, 12)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 6, 9)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 3, 18)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 6, 9)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 3, 18)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 6, 9)) + + }; + +interface ComponentClass

{ +>ComponentClass : Symbol(ComponentClass, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 7, 6)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 9, 25)) + + defaultProps?: Partial

; // Inference target is also mapped _and_ optional +>defaultProps : Symbol(ComponentClass.defaultProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 9, 29)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 9, 25)) +} + +interface InferableComponentEnhancerWithProps { +>InferableComponentEnhancerWithProps : Symbol(InferableComponentEnhancerWithProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 11, 1)) +>TInjectedProps : Symbol(TInjectedProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 13, 46)) +>TNeedsProps : Symbol(TNeedsProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 13, 61)) + +

>( +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 14, 5)) +>Shared : Symbol(Shared, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 63)) +>TInjectedProps : Symbol(TInjectedProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 13, 46)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 14, 5)) + + component: ComponentClass

+>component : Symbol(component, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 14, 42)) +>ComponentClass : Symbol(ComponentClass, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 7, 6)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 14, 5)) + + ): ComponentClass> & TNeedsProps> & { WrappedComponent: ComponentClass

} +>ComponentClass : Symbol(ComponentClass, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 7, 6)) +>Omit : Symbol(Omit, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 0)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 14, 5)) +>Shared : Symbol(Shared, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 0, 63)) +>TInjectedProps : Symbol(TInjectedProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 13, 46)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 14, 5)) +>TNeedsProps : Symbol(TNeedsProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 13, 61)) +>WrappedComponent : Symbol(WrappedComponent, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 16, 81)) +>ComponentClass : Symbol(ComponentClass, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 7, 6)) +>P : Symbol(P, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 14, 5)) + +} // Then intersected with and indexed via Omit and & + +interface Connect { // Then strictly compared with another signature in its context +>Connect : Symbol(Connect, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 17, 1)) + + ( +>TStateProps : Symbol(TStateProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 20, 5)) +>TOwnProps : Symbol(TOwnProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 20, 17)) + + mapStateToProps: unknown, +>mapStateToProps : Symbol(mapStateToProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 20, 29)) + + ): InferableComponentEnhancerWithProps; +>InferableComponentEnhancerWithProps : Symbol(InferableComponentEnhancerWithProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 11, 1)) +>TStateProps : Symbol(TStateProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 20, 5)) +>TOwnProps : Symbol(TOwnProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 20, 17)) + + ( +>TDispatchProps : Symbol(TDispatchProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 24, 5)) +>TOwnProps : Symbol(TOwnProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 24, 20)) + + mapStateToProps: null | undefined, +>mapStateToProps : Symbol(mapStateToProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 24, 32)) + + mapDispatchToProps: unknown, +>mapDispatchToProps : Symbol(mapDispatchToProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 25, 42)) + + mergeProps: null | undefined, +>mergeProps : Symbol(mergeProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 26, 36)) + + options: unknown +>options : Symbol(options, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 27, 37)) + + ): InferableComponentEnhancerWithProps; +>InferableComponentEnhancerWithProps : Symbol(InferableComponentEnhancerWithProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 11, 1)) +>TDispatchProps : Symbol(TDispatchProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 24, 5)) +>TOwnProps : Symbol(TOwnProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 24, 20)) +} + +declare var connect: Connect; +>connect : Symbol(connect, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 32, 11)) +>Connect : Symbol(Connect, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 17, 1)) + +const myStoreConnect: Connect = function( +>myStoreConnect : Symbol(myStoreConnect, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 34, 5)) +>Connect : Symbol(Connect, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 17, 1)) + + mapStateToProps?: any, +>mapStateToProps : Symbol(mapStateToProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 34, 41)) + + mapDispatchToProps?: any, +>mapDispatchToProps : Symbol(mapDispatchToProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 35, 26)) + + mergeProps?: any, +>mergeProps : Symbol(mergeProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 36, 29)) + + options: unknown = {}, +>options : Symbol(options, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 37, 21)) + +) { + return connect( +>connect : Symbol(connect, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 32, 11)) + + mapStateToProps, +>mapStateToProps : Symbol(mapStateToProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 34, 41)) + + mapDispatchToProps, +>mapDispatchToProps : Symbol(mapDispatchToProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 35, 26)) + + mergeProps, +>mergeProps : Symbol(mergeProps, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 36, 29)) + + options, +>options : Symbol(options, Decl(circularlySimplifyingConditionalTypesNoCrash.ts, 37, 21)) + + ); +}; diff --git a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types new file mode 100644 index 00000000000..4a3a1fdbe53 --- /dev/null +++ b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types @@ -0,0 +1,92 @@ +=== tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts === +type Omit = Pick>; +>Omit : Pick> + +type Shared< // Circularly self constraining type, defered thanks to mapping +>Shared : Shared + + InjectedProps, + DecorationTargetProps extends Shared + > = { + [P in Extract]: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; + }; + +interface ComponentClass

{ + defaultProps?: Partial

; // Inference target is also mapped _and_ optional +>defaultProps : Partial

| undefined +} + +interface InferableComponentEnhancerWithProps { +

>( + component: ComponentClass

+>component : ComponentClass

+ + ): ComponentClass> & TNeedsProps> & { WrappedComponent: ComponentClass

} +>WrappedComponent : ComponentClass

+ +} // Then intersected with and indexed via Omit and & + +interface Connect { // Then strictly compared with another signature in its context + ( + mapStateToProps: unknown, +>mapStateToProps : unknown + + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: null | undefined, +>mapStateToProps : null | undefined +>null : null + + mapDispatchToProps: unknown, +>mapDispatchToProps : unknown + + mergeProps: null | undefined, +>mergeProps : null | undefined +>null : null + + options: unknown +>options : unknown + + ): InferableComponentEnhancerWithProps; +} + +declare var connect: Connect; +>connect : Connect + +const myStoreConnect: Connect = function( +>myStoreConnect : Connect +>function( mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options: unknown = {},) { return connect( mapStateToProps, mapDispatchToProps, mergeProps, options, );} : (mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options?: unknown) => InferableComponentEnhancerWithProps<{}, {}> + + mapStateToProps?: any, +>mapStateToProps : any + + mapDispatchToProps?: any, +>mapDispatchToProps : any + + mergeProps?: any, +>mergeProps : any + + options: unknown = {}, +>options : unknown +>{} : {} + +) { + return connect( +>connect( mapStateToProps, mapDispatchToProps, mergeProps, options, ) : InferableComponentEnhancerWithProps<{}, {}> +>connect : Connect + + mapStateToProps, +>mapStateToProps : any + + mapDispatchToProps, +>mapDispatchToProps : any + + mergeProps, +>mergeProps : any + + options, +>options : unknown + + ); +}; diff --git a/tests/baselines/reference/conditionalTypesExcessProperties.errors.txt b/tests/baselines/reference/conditionalTypesExcessProperties.errors.txt index a01cb8c8986..54e8c8742a7 100644 --- a/tests/baselines/reference/conditionalTypesExcessProperties.errors.txt +++ b/tests/baselines/reference/conditionalTypesExcessProperties.errors.txt @@ -1,7 +1,7 @@ tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(8,5): error TS2322: Type '{ test: string; arg: A; }' is not assignable to type 'Something'. Type '{ test: string; arg: A; }' is not assignable to type 'A extends object ? { arg: A; } : { arg?: undefined; }'. -tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(9,33): error TS2322: Type 'A' is not assignable to type 'Something["arr"]'. - Type 'object' is not assignable to type 'Something["arr"]'. +tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(9,33): error TS2322: Type '{ test: string; arg: A; arr: A; }' is not assignable to type 'Something'. + Object literal may only specify known properties, and 'arr' does not exist in type 'Something'. ==== tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts (2 errors) ==== @@ -17,8 +17,8 @@ tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(9, !!! error TS2322: Type '{ test: string; arg: A; }' is not assignable to type 'Something'. !!! error TS2322: Type '{ test: string; arg: A; }' is not assignable to type 'A extends object ? { arg: A; } : { arg?: undefined; }'. sa = { test: 'bye', arg: a, arr: a } // excess - ~~~ -!!! error TS2322: Type 'A' is not assignable to type 'Something["arr"]'. -!!! error TS2322: Type 'object' is not assignable to type 'Something["arr"]'. + ~~~~~~ +!!! error TS2322: Type '{ test: string; arg: A; arr: A; }' is not assignable to type 'Something'. +!!! error TS2322: Object literal may only specify known properties, and 'arr' does not exist in type 'Something'. } \ No newline at end of file diff --git a/tests/baselines/reference/defaultIndexProps2.types b/tests/baselines/reference/defaultIndexProps2.types index a50e4af450e..28c49de3f89 100644 --- a/tests/baselines/reference/defaultIndexProps2.types +++ b/tests/baselines/reference/defaultIndexProps2.types @@ -23,7 +23,7 @@ var o = {v:"Yo2"}; // WScript.Echo(o[0]); 1[0]; ->1[0] : any +>1[0] : error >1 : 1 >0 : 0 diff --git a/tests/baselines/reference/deferredLookupTypeResolution2.errors.txt b/tests/baselines/reference/deferredLookupTypeResolution2.errors.txt deleted file mode 100644 index 88bcd2c4340..00000000000 --- a/tests/baselines/reference/deferredLookupTypeResolution2.errors.txt +++ /dev/null @@ -1,31 +0,0 @@ -tests/cases/compiler/deferredLookupTypeResolution2.ts(14,13): error TS2536: Type '({ [K in Extract]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'. -tests/cases/compiler/deferredLookupTypeResolution2.ts(19,21): error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in Extract]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'. - - -==== tests/cases/compiler/deferredLookupTypeResolution2.ts (2 errors) ==== - // Repro from #17456 - - type StringContains = ({ [K in S]: 'true' } & { [key: string]: 'false'})[L]; - - type ObjectHasKey = StringContains, L>; - - type A = ObjectHasKey; - - type B = ObjectHasKey<[string, number], '1'>; // "true" - type C = ObjectHasKey<[string, number], '2'>; // "false" - type D = A<[string]>; // "true" - - // Error, "false" not handled - type E = { true: 'true' }[ObjectHasKey]; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type '({ [K in Extract]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'. - - type Juxtapose = ({ true: 'otherwise' } & { [k: string]: 'true' })[ObjectHasKey]; - - // Error, "otherwise" is missing - type DeepError = { true: 'true' }[Juxtapose]; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in Extract]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'. - - type DeepOK = { true: 'true', otherwise: 'false' }[Juxtapose]; - \ No newline at end of file diff --git a/tests/baselines/reference/enumBasics.types b/tests/baselines/reference/enumBasics.types index 697d5b40f6f..0ca967cc258 100644 --- a/tests/baselines/reference/enumBasics.types +++ b/tests/baselines/reference/enumBasics.types @@ -141,7 +141,7 @@ enum E7 { A = 'foo'['foo'] >A : E7 ->'foo'['foo'] : any +>'foo'['foo'] : error >'foo' : "foo" >'foo' : "foo" } @@ -152,7 +152,7 @@ enum E8 { B = 'foo'['foo'] >B : E8 ->'foo'['foo'] : any +>'foo'['foo'] : error >'foo' : "foo" >'foo' : "foo" } diff --git a/tests/baselines/reference/enumIndexer.types b/tests/baselines/reference/enumIndexer.types index 6c6e50822b5..a47e9da8c9a 100644 --- a/tests/baselines/reference/enumIndexer.types +++ b/tests/baselines/reference/enumIndexer.types @@ -31,7 +31,7 @@ var x = _arr.map(o => MyEnumType[o.key] === enumValue); // these are not same ty >o => MyEnumType[o.key] === enumValue : (o: { key: string; }) => boolean >o : { key: string; } >MyEnumType[o.key] === enumValue : boolean ->MyEnumType[o.key] : any +>MyEnumType[o.key] : error >MyEnumType : typeof MyEnumType >o.key : string >o : { key: string; } diff --git a/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.js b/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.js new file mode 100644 index 00000000000..091fd6abbd0 --- /dev/null +++ b/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.js @@ -0,0 +1,31 @@ +//// [genericIndexedAccessMethodIntersectionCanBeAccessed.ts] +type ExtendedService = { + [K in keyof T]: T[K] & { + __$daemonMode?: string; + __$action?: string; + }; +}; + +type Service = { + [K in keyof T]: T[K] & {id?: string}; +}; + +export const createService = ( + ServiceCtr: ExtendedService & Service +) => { + Object.keys(ServiceCtr).forEach(key => { + const method = (ServiceCtr)[key as keyof T]; + const {__$daemonMode, __$action, id} = method; + }) +} + + +//// [genericIndexedAccessMethodIntersectionCanBeAccessed.js] +"use strict"; +exports.__esModule = true; +exports.createService = function (ServiceCtr) { + Object.keys(ServiceCtr).forEach(function (key) { + var method = (ServiceCtr)[key]; + var __$daemonMode = method.__$daemonMode, __$action = method.__$action, id = method.id; + }); +}; diff --git a/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.symbols b/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.symbols new file mode 100644 index 00000000000..2b619c997dc --- /dev/null +++ b/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.symbols @@ -0,0 +1,69 @@ +=== tests/cases/compiler/genericIndexedAccessMethodIntersectionCanBeAccessed.ts === +type ExtendedService = { +>ExtendedService : Symbol(ExtendedService, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 0, 0)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 0, 21)) + + [K in keyof T]: T[K] & { +>K : Symbol(K, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 1, 5)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 0, 21)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 0, 21)) +>K : Symbol(K, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 1, 5)) + + __$daemonMode?: string; +>__$daemonMode : Symbol(__$daemonMode, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 1, 28)) + + __$action?: string; +>__$action : Symbol(__$action, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 2, 31)) + + }; +}; + +type Service = { +>Service : Symbol(Service, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 5, 2)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 7, 13)) + + [K in keyof T]: T[K] & {id?: string}; +>K : Symbol(K, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 8, 5)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 7, 13)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 7, 13)) +>K : Symbol(K, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 8, 5)) +>id : Symbol(id, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 8, 28)) + +}; + +export const createService = ( +>createService : Symbol(createService, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 12)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 30)) + + ServiceCtr: ExtendedService & Service +>ServiceCtr : Symbol(ServiceCtr, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 33)) +>ExtendedService : Symbol(ExtendedService, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 0, 0)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 30)) +>Service : Symbol(Service, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 5, 2)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 30)) + +) => { + Object.keys(ServiceCtr).forEach(key => { +>Object.keys(ServiceCtr).forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>Object.keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>ServiceCtr : Symbol(ServiceCtr, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 33)) +>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>key : Symbol(key, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 14, 36)) + + const method = (ServiceCtr)[key as keyof T]; +>method : Symbol(method, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 15, 13)) +>ServiceCtr : Symbol(ServiceCtr, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 33)) +>key : Symbol(key, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 14, 36)) +>T : Symbol(T, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 11, 30)) + + const {__$daemonMode, __$action, id} = method; +>__$daemonMode : Symbol(__$daemonMode, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 16, 15)) +>__$action : Symbol(__$action, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 16, 29)) +>id : Symbol(id, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 16, 40)) +>method : Symbol(method, Decl(genericIndexedAccessMethodIntersectionCanBeAccessed.ts, 15, 13)) + + }) +} + diff --git a/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.types b/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.types new file mode 100644 index 00000000000..d16a75912f4 --- /dev/null +++ b/tests/baselines/reference/genericIndexedAccessMethodIntersectionCanBeAccessed.types @@ -0,0 +1,59 @@ +=== tests/cases/compiler/genericIndexedAccessMethodIntersectionCanBeAccessed.ts === +type ExtendedService = { +>ExtendedService : ExtendedService + + [K in keyof T]: T[K] & { + __$daemonMode?: string; +>__$daemonMode : string | undefined + + __$action?: string; +>__$action : string | undefined + + }; +}; + +type Service = { +>Service : Service + + [K in keyof T]: T[K] & {id?: string}; +>id : string | undefined + +}; + +export const createService = ( +>createService : (ServiceCtr: ExtendedService & Service) => void +>( ServiceCtr: ExtendedService & Service) => { Object.keys(ServiceCtr).forEach(key => { const method = (ServiceCtr)[key as keyof T]; const {__$daemonMode, __$action, id} = method; })} : (ServiceCtr: ExtendedService & Service) => void + + ServiceCtr: ExtendedService & Service +>ServiceCtr : ExtendedService & Service + +) => { + Object.keys(ServiceCtr).forEach(key => { +>Object.keys(ServiceCtr).forEach(key => { const method = (ServiceCtr)[key as keyof T]; const {__$daemonMode, __$action, id} = method; }) : void +>Object.keys(ServiceCtr).forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void +>Object.keys(ServiceCtr) : string[] +>Object.keys : (o: {}) => string[] +>Object : ObjectConstructor +>keys : (o: {}) => string[] +>ServiceCtr : ExtendedService & Service +>forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void +>key => { const method = (ServiceCtr)[key as keyof T]; const {__$daemonMode, __$action, id} = method; } : (key: string) => void +>key : string + + const method = (ServiceCtr)[key as keyof T]; +>method : (ExtendedService & Service)[keyof T] +>(ServiceCtr)[key as keyof T] : (ExtendedService & Service)[keyof T] +>(ServiceCtr) : ExtendedService & Service +>ServiceCtr : ExtendedService & Service +>key as keyof T : keyof T +>key : string + + const {__$daemonMode, __$action, id} = method; +>__$daemonMode : string | undefined +>__$action : string | undefined +>id : string | undefined +>method : (ExtendedService & Service)[keyof T] + + }) +} + diff --git a/tests/baselines/reference/indexClassByNumber.types b/tests/baselines/reference/indexClassByNumber.types index dfd27305ba9..0da451adb36 100644 --- a/tests/baselines/reference/indexClassByNumber.types +++ b/tests/baselines/reference/indexClassByNumber.types @@ -11,7 +11,7 @@ var f = new foo(); f[0] = 4; // Shouldn't be allowed >f[0] = 4 : 4 ->f[0] : any +>f[0] : error >f : foo >0 : 0 >4 : 4 diff --git a/tests/baselines/reference/indexedAccessRelation.errors.txt b/tests/baselines/reference/indexedAccessRelation.errors.txt new file mode 100644 index 00000000000..84e65df856d --- /dev/null +++ b/tests/baselines/reference/indexedAccessRelation.errors.txt @@ -0,0 +1,37 @@ +tests/cases/compiler/indexedAccessRelation.ts(16,23): error TS2345: Argument of type '{ a: T; }' is not assignable to parameter of type 'Pick, "a">'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'S["a"] & T'. + Type 'Foo' is not assignable to type 'S["a"] & T'. + Type 'Foo' is not assignable to type 'S["a"]'. + Type 'T' is not assignable to type 'S["a"]'. + Type 'Foo' is not assignable to type 'S["a"]'. + + +==== tests/cases/compiler/indexedAccessRelation.ts (1 errors) ==== + // Repro from #14723 + + class Component { + setState(state: Pick) {} + } + + export interface State { + a?: T; + } + + class Foo {} + + class Comp extends Component> + { + foo(a: T) { + this.setState({ a: a }); + ~~~~~~~~ +!!! error TS2345: Argument of type '{ a: T; }' is not assignable to parameter of type 'Pick, "a">'. +!!! error TS2345: Types of property 'a' are incompatible. +!!! error TS2345: Type 'T' is not assignable to type 'S["a"] & T'. +!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"] & T'. +!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"]'. +!!! error TS2345: Type 'T' is not assignable to type 'S["a"]'. +!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"]'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/indexedAccessRelation.types b/tests/baselines/reference/indexedAccessRelation.types index 6d2ee19dda2..180cff338cc 100644 --- a/tests/baselines/reference/indexedAccessRelation.types +++ b/tests/baselines/reference/indexedAccessRelation.types @@ -26,7 +26,7 @@ class Comp extends Component> >a : T this.setState({ a: a }); ->this.setState({ a: a }) : void +>this.setState({ a: a }) : any >this.setState : (state: Pick, K>) => void >this : this >setState : (state: Pick, K>) => void diff --git a/tests/baselines/reference/indexingTypesWithNever.types b/tests/baselines/reference/indexingTypesWithNever.types index 7994116d84c..bf141ae0059 100644 --- a/tests/baselines/reference/indexingTypesWithNever.types +++ b/tests/baselines/reference/indexingTypesWithNever.types @@ -69,8 +69,8 @@ declare function genericFn3< // Should be never const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never ->result5 : error ->genericFn3({ g: "gtest", h: "htest" }, "g", "h") : error +>result5 : unknown +>genericFn3({ g: "gtest", h: "htest" }, "g", "h") : unknown >genericFn3 : (obj: T, u: U, v: V) => T[U & V] >{ g: "gtest", h: "htest" } : { g: string; h: string; } >g : string diff --git a/tests/baselines/reference/limitDeepInstantiations.errors.txt b/tests/baselines/reference/limitDeepInstantiations.errors.txt index 2b68b787437..2cf5aade7fd 100644 --- a/tests/baselines/reference/limitDeepInstantiations.errors.txt +++ b/tests/baselines/reference/limitDeepInstantiations.errors.txt @@ -1,7 +1,8 @@ tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2502: '"true"' is referenced directly or indirectly in its own type annotation. +tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'. -==== tests/cases/compiler/limitDeepInstantiations.ts (1 errors) ==== +==== tests/cases/compiler/limitDeepInstantiations.ts (2 errors) ==== // Repro from #14837 type Foo = { "true": Foo> }[T]; @@ -9,4 +10,6 @@ tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2502: '"true"' is !!! error TS2502: '"true"' is referenced directly or indirectly in its own type annotation. let f1: Foo<"true", {}>; let f2: Foo<"false", {}>; + ~~~~~~~ +!!! error TS2344: Type '"false"' does not satisfy the constraint '"true"'. \ No newline at end of file diff --git a/tests/baselines/reference/limitDeepInstantiations.types b/tests/baselines/reference/limitDeepInstantiations.types index 04899df77db..bce090db14b 100644 --- a/tests/baselines/reference/limitDeepInstantiations.types +++ b/tests/baselines/reference/limitDeepInstantiations.types @@ -9,5 +9,5 @@ let f1: Foo<"true", {}>; >f1 : any let f2: Foo<"false", {}>; ->f2 : any +>f2 : unknown diff --git a/tests/baselines/reference/modularizeLibrary_UsingES5LibES6ArrayLibES6WellknownSymbolLib.types b/tests/baselines/reference/modularizeLibrary_UsingES5LibES6ArrayLibES6WellknownSymbolLib.types index caca4cf8759..830cbe6a0f4 100644 --- a/tests/baselines/reference/modularizeLibrary_UsingES5LibES6ArrayLibES6WellknownSymbolLib.types +++ b/tests/baselines/reference/modularizeLibrary_UsingES5LibES6ArrayLibES6WellknownSymbolLib.types @@ -28,7 +28,7 @@ let a = ['c', 'd']; a[Symbol.isConcatSpreadable] = false; >a[Symbol.isConcatSpreadable] = false : false ->a[Symbol.isConcatSpreadable] : any +>a[Symbol.isConcatSpreadable] : error >a : string[] >Symbol.isConcatSpreadable : symbol >Symbol : SymbolConstructor diff --git a/tests/baselines/reference/newWithSpreadES5.types b/tests/baselines/reference/newWithSpreadES5.types index 14b53040a02..f40235832bb 100644 --- a/tests/baselines/reference/newWithSpreadES5.types +++ b/tests/baselines/reference/newWithSpreadES5.types @@ -445,9 +445,9 @@ new h["a-b"]["a-b"](1, 2, ...a, "string"); // Element access expression with a number new i["a-b"][1](1, 2, "string"); ->new i["a-b"][1](1, 2, "string") : any ->i["a-b"][1] : any ->i["a-b"] : any +>new i["a-b"][1](1, 2, "string") : error +>i["a-b"][1] : error +>i["a-b"] : error >i : C[][] >"a-b" : "a-b" >1 : 1 @@ -456,9 +456,9 @@ new i["a-b"][1](1, 2, "string"); >"string" : "string" new i["a-b"][1](1, 2, ...a); ->new i["a-b"][1](1, 2, ...a) : any ->i["a-b"][1] : any ->i["a-b"] : any +>new i["a-b"][1](1, 2, ...a) : error +>i["a-b"][1] : error +>i["a-b"] : error >i : C[][] >"a-b" : "a-b" >1 : 1 @@ -468,9 +468,9 @@ new i["a-b"][1](1, 2, ...a); >a : string[] new i["a-b"][1](1, 2, ...a, "string"); ->new i["a-b"][1](1, 2, ...a, "string") : any ->i["a-b"][1] : any ->i["a-b"] : any +>new i["a-b"][1](1, 2, ...a, "string") : error +>i["a-b"][1] : error +>i["a-b"] : error >i : C[][] >"a-b" : "a-b" >1 : 1 diff --git a/tests/baselines/reference/newWithSpreadES6.types b/tests/baselines/reference/newWithSpreadES6.types index 5914425b096..ab2cf6b3d1d 100644 --- a/tests/baselines/reference/newWithSpreadES6.types +++ b/tests/baselines/reference/newWithSpreadES6.types @@ -446,9 +446,9 @@ new h["a-b"]["a-b"](1, 2, ...a, "string"); // Element access expression with a number new i["a-b"][1](1, 2, "string"); ->new i["a-b"][1](1, 2, "string") : any ->i["a-b"][1] : any ->i["a-b"] : any +>new i["a-b"][1](1, 2, "string") : error +>i["a-b"][1] : error +>i["a-b"] : error >i : C[][] >"a-b" : "a-b" >1 : 1 @@ -457,9 +457,9 @@ new i["a-b"][1](1, 2, "string"); >"string" : "string" new i["a-b"][1](1, 2, ...a); ->new i["a-b"][1](1, 2, ...a) : any ->i["a-b"][1] : any ->i["a-b"] : any +>new i["a-b"][1](1, 2, ...a) : error +>i["a-b"][1] : error +>i["a-b"] : error >i : C[][] >"a-b" : "a-b" >1 : 1 @@ -469,9 +469,9 @@ new i["a-b"][1](1, 2, ...a); >a : string[] new i["a-b"][1](1, 2, ...a, "string"); ->new i["a-b"][1](1, 2, ...a, "string") : any ->i["a-b"][1] : any ->i["a-b"] : any +>new i["a-b"][1](1, 2, ...a, "string") : error +>i["a-b"][1] : error +>i["a-b"] : error >i : C[][] >"a-b" : "a-b" >1 : 1 diff --git a/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types index 3b004aa9589..fe34cdbc130 100644 --- a/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types +++ b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types @@ -24,8 +24,8 @@ var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu] // Should be okay, as we suppress implicit 'any' property access checks var strRepresentation3 = MyEmusEnum["monehh"]; ->strRepresentation3 : any ->MyEmusEnum["monehh"] : any +>strRepresentation3 : error +>MyEmusEnum["monehh"] : error >MyEmusEnum : typeof MyEmusEnum >"monehh" : "monehh" @@ -39,15 +39,15 @@ var strRepresentation4 = MyEmusEnum["emu"]; // Should be okay, as we suppress implicit 'any' property access checks var x = {}["hi"]; ->x : any ->{}["hi"] : any +>x : error +>{}["hi"] : error >{} : {} >"hi" : "hi" // Should be okay, as we suppress implicit 'any' property access checks var y = {}[10]; ->y : any ->{}[10] : any +>y : error +>{}[10] : error >{} : {} >10 : 10 @@ -61,8 +61,8 @@ var emptyObj = {}; // Should be okay, as we suppress implicit 'any' property access checks var z1 = emptyObj[hi]; ->z1 : any ->emptyObj[hi] : any +>z1 : error +>emptyObj[hi] : error >emptyObj : {} >hi : any diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForIn.types b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.types index 44e2b3f4d50..430e03652d7 100644 --- a/tests/baselines/reference/nonPrimitiveIndexingWithForIn.types +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.types @@ -7,8 +7,8 @@ for (var key in a) { >a : object var value = a[key]; ->value : any ->a[key] : any +>value : error +>a[key] : error >a : object >key : string } diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.types b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.types index 3fafa40b596..9c094010701 100644 --- a/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.types +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.types @@ -7,8 +7,8 @@ for (var key in a) { >a : object var value = a[key]; ->value : any ->a[key] : any +>value : error +>a[key] : error >a : object >key : string } diff --git a/tests/baselines/reference/numericIndexingResults.types b/tests/baselines/reference/numericIndexingResults.types index db4d341b560..f4e0d168e6e 100644 --- a/tests/baselines/reference/numericIndexingResults.types +++ b/tests/baselines/reference/numericIndexingResults.types @@ -30,8 +30,8 @@ var r2 = c['2']; >'2' : "2" var r3 = c['3']; ->r3 : any ->c['3'] : any +>r3 : error +>c['3'] : error >c : C >'3' : "3" @@ -80,8 +80,8 @@ var r2 = i['2']; >'2' : "2" var r3 = i['3']; ->r3 : any ->i['3'] : any +>r3 : error +>i['3'] : error >i : I >'3' : "3" @@ -129,8 +129,8 @@ var r2 = a['2']; >'2' : "2" var r3 = a['3']; ->r3 : any ->a['3'] : any +>r3 : error +>a['3'] : error >a : { [x: number]: string; 1: string; "2": string; } >'3' : "3" @@ -162,20 +162,20 @@ var b: { [x: number]: string } = { 1: '', "2": '' } >'' : "" var r1a = b['1']; ->r1a : any ->b['1'] : any +>r1a : error +>b['1'] : error >b : { [x: number]: string; } >'1' : "1" var r2a = b['2']; ->r2a : any ->b['2'] : any +>r2a : error +>b['2'] : error >b : { [x: number]: string; } >'2' : "2" var r3 = b['3']; ->r3 : any ->b['3'] : any +>r3 : error +>b['3'] : error >b : { [x: number]: string; } >'3' : "3" @@ -221,8 +221,8 @@ var r2b = b2['2']; >'2' : "2" var r3 = b2['3']; ->r3 : any ->b2['3'] : any +>r3 : error +>b2['3'] : error >b2 : { [x: number]: string; 1: string; "2": string; } >'3' : "3" diff --git a/tests/baselines/reference/objectTypeWithCallSignatureHidingMembersOfExtendedFunction.types b/tests/baselines/reference/objectTypeWithCallSignatureHidingMembersOfExtendedFunction.types index d36ef8866c7..3ee91c6aff3 100644 --- a/tests/baselines/reference/objectTypeWithCallSignatureHidingMembersOfExtendedFunction.types +++ b/tests/baselines/reference/objectTypeWithCallSignatureHidingMembersOfExtendedFunction.types @@ -55,8 +55,8 @@ var r1d = i.data; >data : number var r1e = i['hm']; // should be Object ->r1e : any ->i['hm'] : any +>r1e : error +>i['hm'] : error >i : I >'hm' : "hm" @@ -104,8 +104,8 @@ var r2d = x.data; >data : number var r2e = x['hm']; // should be Object ->r2e : any ->x['hm'] : any +>r2e : error +>x['hm'] : error >x : { (): void; apply(a: any, b?: any): void; call(thisArg: number, ...argArray: number[]): any; } >'hm' : "hm" diff --git a/tests/baselines/reference/objectTypeWithConstructSignatureHidingMembersOfExtendedFunction.types b/tests/baselines/reference/objectTypeWithConstructSignatureHidingMembersOfExtendedFunction.types index 8bb1785516b..6e00a2ea1e9 100644 --- a/tests/baselines/reference/objectTypeWithConstructSignatureHidingMembersOfExtendedFunction.types +++ b/tests/baselines/reference/objectTypeWithConstructSignatureHidingMembersOfExtendedFunction.types @@ -52,8 +52,8 @@ var r1d = i.data; >data : number var r1e = i['hm']; // should be Object ->r1e : any ->i['hm'] : any +>r1e : error +>i['hm'] : error >i : I >'hm' : "hm" @@ -101,8 +101,8 @@ var r2d = x.data; >data : number var r2e = x['hm']; // should be Object ->r2e : any ->x['hm'] : any +>r2e : error +>x['hm'] : error >x : { new (): number; apply(a: any, b?: any): void; call(thisArg: number, ...argArray: number[]): any; } >'hm' : "hm" diff --git a/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.types b/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.types index d110e79e26e..ad30405de0e 100644 --- a/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.types +++ b/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.types @@ -28,8 +28,8 @@ var r = c[" "]; >" " : " " var r2 = c[" "]; ->r2 : any ->c[" "] : any +>r2 : error +>c[" "] : error >c : C >" " : " " @@ -67,8 +67,8 @@ var r = i[" "]; >" " : " " var r2 = i[" "]; ->r2 : any ->i[" "] : any +>r2 : error +>i[" "] : error >i : I >" " : " " @@ -106,8 +106,8 @@ var r = a[" "]; >" " : " " var r2 = a[" "]; ->r2 : any ->a[" "] : any +>r2 : error +>a[" "] : error >a : { " ": number; "a b": string; "~!@#$%^&*()_+{}|:'<>?\/.,`": number; } >" " : " " @@ -148,8 +148,8 @@ var r = b[" "]; >" " : " " var r2 = b[" "]; ->r2 : any ->b[" "] : any +>r2 : error +>b[" "] : error >b : { " ": number; "a b": string; "~!@#$%^&*()_+{}|:'<>?\/.,`": number; } >" " : " " diff --git a/tests/baselines/reference/octalIntegerLiteral.types b/tests/baselines/reference/octalIntegerLiteral.types index 160a1460977..5b3e484821e 100644 --- a/tests/baselines/reference/octalIntegerLiteral.types +++ b/tests/baselines/reference/octalIntegerLiteral.types @@ -69,7 +69,7 @@ obj1[0o45436]; // string >0o45436 : 19230 obj1["0o45436"]; // any ->obj1["0o45436"] : any +>obj1["0o45436"] : error >obj1 : { 0o45436: string; a: number; b: number; oct1: number; 0o7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777: boolean; } >"0o45436" : "0o45436" @@ -109,7 +109,7 @@ obj2[0O45436]; // string >0O45436 : 19230 obj2["0O45436"]; // any ->obj2["0O45436"] : any +>obj2["0O45436"] : error >obj2 : { 0O45436: string; a: number; b: number; oct2: number; 0o7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777: boolean; } >"0O45436" : "0O45436" @@ -149,7 +149,7 @@ obj2["5.462437423415177e+244"]; // boolean >"5.462437423415177e+244" : "5.462437423415177e+244" obj2["Infinity"]; // any ->obj2["Infinity"] : any +>obj2["Infinity"] : error >obj2 : { 0O45436: string; a: number; b: number; oct2: number; 0o7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777: boolean; } >"Infinity" : "Infinity" diff --git a/tests/baselines/reference/octalIntegerLiteralES6.types b/tests/baselines/reference/octalIntegerLiteralES6.types index 0c799a44697..8f1e7256b17 100644 --- a/tests/baselines/reference/octalIntegerLiteralES6.types +++ b/tests/baselines/reference/octalIntegerLiteralES6.types @@ -69,7 +69,7 @@ obj1[0o45436]; // string >0o45436 : 19230 obj1["0o45436"]; // any ->obj1["0o45436"] : any +>obj1["0o45436"] : error >obj1 : { 0o45436: string; a: number; b: number; oct1: number; 0o7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777: boolean; } >"0o45436" : "0o45436" @@ -109,7 +109,7 @@ obj2[0O45436]; // string >0O45436 : 19230 obj2["0O45436"]; // any ->obj2["0O45436"] : any +>obj2["0O45436"] : error >obj2 : { 0O45436: string; a: number; b: number; oct2: number; 0o7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777: boolean; } >"0O45436" : "0O45436" @@ -149,7 +149,7 @@ obj2["5.462437423415177e+244"]; // boolean >"5.462437423415177e+244" : "5.462437423415177e+244" obj2["Infinity"]; // any ->obj2["Infinity"] : any +>obj2["Infinity"] : error >obj2 : { 0O45436: string; a: number; b: number; oct2: number; 0o7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777: boolean; } >"Infinity" : "Infinity" diff --git a/tests/baselines/reference/protoAsIndexInIndexExpression.types b/tests/baselines/reference/protoAsIndexInIndexExpression.types index 7d276199063..2da76f32f4a 100644 --- a/tests/baselines/reference/protoAsIndexInIndexExpression.types +++ b/tests/baselines/reference/protoAsIndexInIndexExpression.types @@ -15,7 +15,7 @@ var WorkspacePrototype = { }; WorkspacePrototype['__proto__'] = EntityPrototype; >WorkspacePrototype['__proto__'] = EntityPrototype : any ->WorkspacePrototype['__proto__'] : any +>WorkspacePrototype['__proto__'] : error >WorkspacePrototype : { serialize: () => any; } >'__proto__' : "__proto__" >EntityPrototype : any diff --git a/tests/baselines/reference/protoInIndexer.types b/tests/baselines/reference/protoInIndexer.types index c15f98b75ff..e47bb0dd341 100644 --- a/tests/baselines/reference/protoInIndexer.types +++ b/tests/baselines/reference/protoInIndexer.types @@ -5,7 +5,7 @@ class X { constructor() { this['__proto__'] = null; // used to cause ICE >this['__proto__'] = null : null ->this['__proto__'] : any +>this['__proto__'] : error >this : this >'__proto__' : "__proto__" >null : null diff --git a/tests/baselines/reference/spyComparisonChecking.errors.txt b/tests/baselines/reference/spyComparisonChecking.errors.txt new file mode 100644 index 00000000000..8b057dd30ed --- /dev/null +++ b/tests/baselines/reference/spyComparisonChecking.errors.txt @@ -0,0 +1,29 @@ +tests/cases/compiler/spyComparisonChecking.ts(20,32): error TS2339: Property 'returnValue' does not exist on type 'Function'. + + +==== tests/cases/compiler/spyComparisonChecking.ts (1 errors) ==== + interface Spy { + (...params: any[]): any; + + identity: string; + and: Function; + mostRecentCall: { args: any[]; }; + argsForCall: any[]; + } + + type SpyObj = T & { + [k in keyof T]: Spy; + } + + declare function createSpyObj( + name: string, names: Array): SpyObj; + + function mock(spyName: string, methodNames: Array): SpyObj { + const spyObj = createSpyObj(spyName, methodNames); + for (const methodName of methodNames) { + spyObj[methodName].and.returnValue(1); + ~~~~~~~~~~~ +!!! error TS2339: Property 'returnValue' does not exist on type 'Function'. + } + return spyObj; + } \ No newline at end of file diff --git a/tests/baselines/reference/spyComparisonChecking.js b/tests/baselines/reference/spyComparisonChecking.js new file mode 100644 index 00000000000..918c4e149e9 --- /dev/null +++ b/tests/baselines/reference/spyComparisonChecking.js @@ -0,0 +1,34 @@ +//// [spyComparisonChecking.ts] +interface Spy { + (...params: any[]): any; + + identity: string; + and: Function; + mostRecentCall: { args: any[]; }; + argsForCall: any[]; +} + +type SpyObj = T & { + [k in keyof T]: Spy; +} + +declare function createSpyObj( + name: string, names: Array): SpyObj; + +function mock(spyName: string, methodNames: Array): SpyObj { + const spyObj = createSpyObj(spyName, methodNames); + for (const methodName of methodNames) { + spyObj[methodName].and.returnValue(1); + } + return spyObj; +} + +//// [spyComparisonChecking.js] +function mock(spyName, methodNames) { + var spyObj = createSpyObj(spyName, methodNames); + for (var _i = 0, methodNames_1 = methodNames; _i < methodNames_1.length; _i++) { + var methodName = methodNames_1[_i]; + spyObj[methodName].and.returnValue(1); + } + return spyObj; +} diff --git a/tests/baselines/reference/spyComparisonChecking.symbols b/tests/baselines/reference/spyComparisonChecking.symbols new file mode 100644 index 00000000000..50d8afaa0d1 --- /dev/null +++ b/tests/baselines/reference/spyComparisonChecking.symbols @@ -0,0 +1,75 @@ +=== tests/cases/compiler/spyComparisonChecking.ts === +interface Spy { +>Spy : Symbol(Spy, Decl(spyComparisonChecking.ts, 0, 0)) + + (...params: any[]): any; +>params : Symbol(params, Decl(spyComparisonChecking.ts, 1, 5)) + + identity: string; +>identity : Symbol(Spy.identity, Decl(spyComparisonChecking.ts, 1, 28)) + + and: Function; +>and : Symbol(Spy.and, Decl(spyComparisonChecking.ts, 3, 21)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + mostRecentCall: { args: any[]; }; +>mostRecentCall : Symbol(Spy.mostRecentCall, Decl(spyComparisonChecking.ts, 4, 18)) +>args : Symbol(args, Decl(spyComparisonChecking.ts, 5, 21)) + + argsForCall: any[]; +>argsForCall : Symbol(Spy.argsForCall, Decl(spyComparisonChecking.ts, 5, 37)) +} + +type SpyObj = T & { +>SpyObj : Symbol(SpyObj, Decl(spyComparisonChecking.ts, 7, 1)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 9, 12)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 9, 12)) + + [k in keyof T]: Spy; +>k : Symbol(k, Decl(spyComparisonChecking.ts, 10, 5)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 9, 12)) +>Spy : Symbol(Spy, Decl(spyComparisonChecking.ts, 0, 0)) +} + +declare function createSpyObj( +>createSpyObj : Symbol(createSpyObj, Decl(spyComparisonChecking.ts, 11, 1)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 13, 30)) + + name: string, names: Array): SpyObj; +>name : Symbol(name, Decl(spyComparisonChecking.ts, 13, 33)) +>names : Symbol(names, Decl(spyComparisonChecking.ts, 14, 17)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 13, 30)) +>SpyObj : Symbol(SpyObj, Decl(spyComparisonChecking.ts, 7, 1)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 13, 30)) + +function mock(spyName: string, methodNames: Array): SpyObj { +>mock : Symbol(mock, Decl(spyComparisonChecking.ts, 14, 52)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 16, 14)) +>spyName : Symbol(spyName, Decl(spyComparisonChecking.ts, 16, 17)) +>methodNames : Symbol(methodNames, Decl(spyComparisonChecking.ts, 16, 33)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 16, 14)) +>SpyObj : Symbol(SpyObj, Decl(spyComparisonChecking.ts, 7, 1)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 16, 14)) + + const spyObj = createSpyObj(spyName, methodNames); +>spyObj : Symbol(spyObj, Decl(spyComparisonChecking.ts, 17, 9)) +>createSpyObj : Symbol(createSpyObj, Decl(spyComparisonChecking.ts, 11, 1)) +>T : Symbol(T, Decl(spyComparisonChecking.ts, 16, 14)) +>spyName : Symbol(spyName, Decl(spyComparisonChecking.ts, 16, 17)) +>methodNames : Symbol(methodNames, Decl(spyComparisonChecking.ts, 16, 33)) + + for (const methodName of methodNames) { +>methodName : Symbol(methodName, Decl(spyComparisonChecking.ts, 18, 14)) +>methodNames : Symbol(methodNames, Decl(spyComparisonChecking.ts, 16, 33)) + + spyObj[methodName].and.returnValue(1); +>spyObj[methodName].and : Symbol(Spy.and, Decl(spyComparisonChecking.ts, 3, 21)) +>spyObj : Symbol(spyObj, Decl(spyComparisonChecking.ts, 17, 9)) +>methodName : Symbol(methodName, Decl(spyComparisonChecking.ts, 18, 14)) +>and : Symbol(Spy.and, Decl(spyComparisonChecking.ts, 3, 21)) + } + return spyObj; +>spyObj : Symbol(spyObj, Decl(spyComparisonChecking.ts, 17, 9)) +} diff --git a/tests/baselines/reference/spyComparisonChecking.types b/tests/baselines/reference/spyComparisonChecking.types new file mode 100644 index 00000000000..3401bc45ac4 --- /dev/null +++ b/tests/baselines/reference/spyComparisonChecking.types @@ -0,0 +1,62 @@ +=== tests/cases/compiler/spyComparisonChecking.ts === +interface Spy { + (...params: any[]): any; +>params : any[] + + identity: string; +>identity : string + + and: Function; +>and : Function + + mostRecentCall: { args: any[]; }; +>mostRecentCall : { args: any[]; } +>args : any[] + + argsForCall: any[]; +>argsForCall : any[] +} + +type SpyObj = T & { +>SpyObj : SpyObj + + [k in keyof T]: Spy; +} + +declare function createSpyObj( +>createSpyObj : (name: string, names: (keyof T)[]) => SpyObj + + name: string, names: Array): SpyObj; +>name : string +>names : (keyof T)[] + +function mock(spyName: string, methodNames: Array): SpyObj { +>mock : (spyName: string, methodNames: (keyof T)[]) => SpyObj +>spyName : string +>methodNames : (keyof T)[] + + const spyObj = createSpyObj(spyName, methodNames); +>spyObj : SpyObj +>createSpyObj(spyName, methodNames) : SpyObj +>createSpyObj : (name: string, names: (keyof T)[]) => SpyObj +>spyName : string +>methodNames : (keyof T)[] + + for (const methodName of methodNames) { +>methodName : keyof T +>methodNames : (keyof T)[] + + spyObj[methodName].and.returnValue(1); +>spyObj[methodName].and.returnValue(1) : any +>spyObj[methodName].and.returnValue : any +>spyObj[methodName].and : Function +>spyObj[methodName] : SpyObj[keyof T] +>spyObj : SpyObj +>methodName : keyof T +>and : Function +>returnValue : any +>1 : 1 + } + return spyObj; +>spyObj : SpyObj +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess1.types b/tests/baselines/reference/superSymbolIndexedAccess1.types index 11b67cadfcd..46e21336436 100644 --- a/tests/baselines/reference/superSymbolIndexedAccess1.types +++ b/tests/baselines/reference/superSymbolIndexedAccess1.types @@ -28,8 +28,8 @@ class Bar extends Foo { >symbol : symbol return super[symbol](); ->super[symbol]() : any ->super[symbol] : any +>super[symbol]() : error +>super[symbol] : error >super : Foo >symbol : symbol } diff --git a/tests/baselines/reference/superSymbolIndexedAccess5.types b/tests/baselines/reference/superSymbolIndexedAccess5.types index cbbd98ee320..b0395936a8a 100644 --- a/tests/baselines/reference/superSymbolIndexedAccess5.types +++ b/tests/baselines/reference/superSymbolIndexedAccess5.types @@ -23,8 +23,8 @@ class Bar extends Foo { >symbol : any return super[symbol](); ->super[symbol]() : any ->super[symbol] : any +>super[symbol]() : error +>super[symbol] : error >super : Foo >symbol : any } diff --git a/tests/baselines/reference/superSymbolIndexedAccess6.types b/tests/baselines/reference/superSymbolIndexedAccess6.types index dab66292718..e60869d6fe6 100644 --- a/tests/baselines/reference/superSymbolIndexedAccess6.types +++ b/tests/baselines/reference/superSymbolIndexedAccess6.types @@ -23,8 +23,8 @@ class Bar extends Foo { >symbol : any return super[symbol](); ->super[symbol]() : any ->super[symbol] : any +>super[symbol]() : error +>super[symbol] : error >super : typeof Foo >symbol : any } diff --git a/tests/baselines/reference/symbolProperty55.types b/tests/baselines/reference/symbolProperty55.types index 3c185f96d1e..d96b8b43751 100644 --- a/tests/baselines/reference/symbolProperty55.types +++ b/tests/baselines/reference/symbolProperty55.types @@ -21,7 +21,7 @@ module M { // The following should be of type 'any'. This is because even though obj has a property keyed by Symbol.iterator, // the key passed in here is the *wrong* Symbol.iterator. It is not the iterator property of the global Symbol. obj[Symbol.iterator]; ->obj[Symbol.iterator] : any +>obj[Symbol.iterator] : error >obj : { [Symbol.iterator]: number; } >Symbol.iterator : symbol >Symbol : SymbolConstructor diff --git a/tests/baselines/reference/symbolProperty56.types b/tests/baselines/reference/symbolProperty56.types index 1f061739c41..b6731ed5e80 100644 --- a/tests/baselines/reference/symbolProperty56.types +++ b/tests/baselines/reference/symbolProperty56.types @@ -21,9 +21,9 @@ module M { // The following should be of type 'any'. This is because even though obj has a property keyed by Symbol.iterator, // the key passed in here is the *wrong* Symbol.iterator. It is not the iterator property of the global Symbol. obj[Symbol["iterator"]]; ->obj[Symbol["iterator"]] : any +>obj[Symbol["iterator"]] : error >obj : { [Symbol.iterator]: number; } ->Symbol["iterator"] : any +>Symbol["iterator"] : error >Symbol : {} >"iterator" : "iterator" } diff --git a/tests/baselines/reference/symbolProperty57.types b/tests/baselines/reference/symbolProperty57.types index 88dca83627f..eeb00489bb2 100644 --- a/tests/baselines/reference/symbolProperty57.types +++ b/tests/baselines/reference/symbolProperty57.types @@ -14,9 +14,9 @@ var obj = { // Should give type 'any'. obj[Symbol["nonsense"]]; ->obj[Symbol["nonsense"]] : any +>obj[Symbol["nonsense"]] : error >obj : { [Symbol.iterator]: number; } ->Symbol["nonsense"] : any +>Symbol["nonsense"] : error >Symbol : SymbolConstructor >"nonsense" : "nonsense" diff --git a/tests/baselines/reference/systemJsForInNoException.types b/tests/baselines/reference/systemJsForInNoException.types index 6d9dbbb6e7b..31bef844a6f 100644 --- a/tests/baselines/reference/systemJsForInNoException.types +++ b/tests/baselines/reference/systemJsForInNoException.types @@ -14,7 +14,7 @@ for (var key in obj) >console.log : (message?: any, ...optionalParams: any[]) => void >console : Console >log : (message?: any, ...optionalParams: any[]) => void ->obj[key] : any +>obj[key] : error >obj : { a: number; } >key : string diff --git a/tests/baselines/reference/templateStringInIndexExpression.types b/tests/baselines/reference/templateStringInIndexExpression.types index f0faac5f45c..9ad6b1e141d 100644 --- a/tests/baselines/reference/templateStringInIndexExpression.types +++ b/tests/baselines/reference/templateStringInIndexExpression.types @@ -1,6 +1,6 @@ === tests/cases/conformance/es6/templates/templateStringInIndexExpression.ts === `abc${0}abc`[`0`]; ->`abc${0}abc`[`0`] : any +>`abc${0}abc`[`0`] : error >`abc${0}abc` : string >0 : 0 >`0` : "0" diff --git a/tests/baselines/reference/templateStringInIndexExpressionES6.types b/tests/baselines/reference/templateStringInIndexExpressionES6.types index eabc71c9fac..d86fb2309e7 100644 --- a/tests/baselines/reference/templateStringInIndexExpressionES6.types +++ b/tests/baselines/reference/templateStringInIndexExpressionES6.types @@ -1,6 +1,6 @@ === tests/cases/conformance/es6/templates/templateStringInIndexExpressionES6.ts === `abc${0}abc`[`0`]; ->`abc${0}abc`[`0`] : any +>`abc${0}abc`[`0`] : error >`abc${0}abc` : string >0 : 0 >`0` : "0" diff --git a/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.js b/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.js new file mode 100644 index 00000000000..56273a2b006 --- /dev/null +++ b/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.js @@ -0,0 +1,60 @@ +//// [thisIndexOnExistingReadonlyFieldIsNotNever.ts] +declare class Component { + readonly props: Readonly<{ children?: unknown }> & Readonly

; + state: Readonly; +} +interface CoachMarkAnchorProps { + anchorRef?: (anchor: C) => void; +} +type AnchorType

= Component

; + +class CoachMarkAnchorDecorator { + decorateComponent

(anchor: P) { + return class CoachMarkAnchor extends Component> & P, {}> { + private _onAnchorRef = (anchor: AnchorType

) => { + const anchorRef = this.props.anchorRef; + if (anchorRef) { + anchorRef(anchor); + } + } + }; + } +} + + +//// [thisIndexOnExistingReadonlyFieldIsNotNever.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + 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 extendStatics(d, b); + } + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var CoachMarkAnchorDecorator = /** @class */ (function () { + function CoachMarkAnchorDecorator() { + } + CoachMarkAnchorDecorator.prototype.decorateComponent = function (anchor) { + return /** @class */ (function (_super) { + __extends(CoachMarkAnchor, _super); + function CoachMarkAnchor() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this._onAnchorRef = function (anchor) { + var anchorRef = _this.props.anchorRef; + if (anchorRef) { + anchorRef(anchor); + } + }; + return _this; + } + return CoachMarkAnchor; + }(Component)); + }; + return CoachMarkAnchorDecorator; +}()); diff --git a/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.symbols b/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.symbols new file mode 100644 index 00000000000..6cedbe269bf --- /dev/null +++ b/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.symbols @@ -0,0 +1,76 @@ +=== tests/cases/compiler/thisIndexOnExistingReadonlyFieldIsNotNever.ts === +declare class Component { +>Component : Symbol(Component, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 0)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 24)) +>S : Symbol(S, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 26)) + + readonly props: Readonly<{ children?: unknown }> & Readonly

; +>props : Symbol(Component.props, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 36)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>children : Symbol(children, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 1, 30)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 24)) + + state: Readonly; +>state : Symbol(Component.state, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 1, 67)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>S : Symbol(S, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 26)) +} +interface CoachMarkAnchorProps { +>CoachMarkAnchorProps : Symbol(CoachMarkAnchorProps, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 3, 1)) +>C : Symbol(C, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 4, 31)) + + anchorRef?: (anchor: C) => void; +>anchorRef : Symbol(CoachMarkAnchorProps.anchorRef, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 4, 35)) +>anchor : Symbol(anchor, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 5, 17)) +>C : Symbol(C, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 4, 31)) +} +type AnchorType

= Component

; +>AnchorType : Symbol(AnchorType, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 6, 1)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 7, 16)) +>Component : Symbol(Component, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 0)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 7, 16)) + +class CoachMarkAnchorDecorator { +>CoachMarkAnchorDecorator : Symbol(CoachMarkAnchorDecorator, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 7, 34)) + + decorateComponent

(anchor: P) { +>decorateComponent : Symbol(CoachMarkAnchorDecorator.decorateComponent, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 9, 32)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 10, 22)) +>anchor : Symbol(anchor, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 10, 25)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 10, 22)) + + return class CoachMarkAnchor extends Component> & P, {}> { +>CoachMarkAnchor : Symbol(CoachMarkAnchor, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 11, 14)) +>Component : Symbol(Component, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 0)) +>CoachMarkAnchorProps : Symbol(CoachMarkAnchorProps, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 3, 1)) +>AnchorType : Symbol(AnchorType, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 6, 1)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 10, 22)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 10, 22)) + + private _onAnchorRef = (anchor: AnchorType

) => { +>_onAnchorRef : Symbol(CoachMarkAnchor._onAnchorRef, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 11, 101)) +>anchor : Symbol(anchor, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 12, 36)) +>AnchorType : Symbol(AnchorType, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 6, 1)) +>P : Symbol(P, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 10, 22)) + + const anchorRef = this.props.anchorRef; +>anchorRef : Symbol(anchorRef, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 13, 21)) +>this.props.anchorRef : Symbol(anchorRef, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 4, 35)) +>this.props : Symbol(Component.props, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 36)) +>this : Symbol(CoachMarkAnchor, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 11, 14)) +>props : Symbol(Component.props, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 0, 36)) +>anchorRef : Symbol(anchorRef, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 4, 35)) + + if (anchorRef) { +>anchorRef : Symbol(anchorRef, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 13, 21)) + + anchorRef(anchor); +>anchorRef : Symbol(anchorRef, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 13, 21)) +>anchor : Symbol(anchor, Decl(thisIndexOnExistingReadonlyFieldIsNotNever.ts, 12, 36)) + } + } + }; + } +} + diff --git a/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.types b/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.types new file mode 100644 index 00000000000..30dfd635724 --- /dev/null +++ b/tests/baselines/reference/thisIndexOnExistingReadonlyFieldIsNotNever.types @@ -0,0 +1,57 @@ +=== tests/cases/compiler/thisIndexOnExistingReadonlyFieldIsNotNever.ts === +declare class Component { +>Component : Component + + readonly props: Readonly<{ children?: unknown }> & Readonly

; +>props : Readonly<{ children?: unknown; }> & Readonly

+>children : unknown + + state: Readonly; +>state : Readonly +} +interface CoachMarkAnchorProps { + anchorRef?: (anchor: C) => void; +>anchorRef : ((anchor: C) => void) | undefined +>anchor : C +} +type AnchorType

= Component

; +>AnchorType : Component + +class CoachMarkAnchorDecorator { +>CoachMarkAnchorDecorator : CoachMarkAnchorDecorator + + decorateComponent

(anchor: P) { +>decorateComponent :

(anchor: P) => typeof CoachMarkAnchor +>anchor : P + + return class CoachMarkAnchor extends Component> & P, {}> { +>class CoachMarkAnchor extends Component> & P, {}> { private _onAnchorRef = (anchor: AnchorType

) => { const anchorRef = this.props.anchorRef; if (anchorRef) { anchorRef(anchor); } } } : typeof CoachMarkAnchor +>CoachMarkAnchor : typeof CoachMarkAnchor +>Component : Component> & P, {}> + + private _onAnchorRef = (anchor: AnchorType

) => { +>_onAnchorRef : (anchor: Component) => void +>(anchor: AnchorType

) => { const anchorRef = this.props.anchorRef; if (anchorRef) { anchorRef(anchor); } } : (anchor: Component) => void +>anchor : Component + + const anchorRef = this.props.anchorRef; +>anchorRef : (CoachMarkAnchorProps> & P)["anchorRef"] | undefined +>this.props.anchorRef : (CoachMarkAnchorProps> & P)["anchorRef"] | undefined +>this.props : Readonly<{ children?: unknown; }> & Readonly> & P> +>this : this +>props : Readonly<{ children?: unknown; }> & Readonly> & P> +>anchorRef : (CoachMarkAnchorProps> & P)["anchorRef"] | undefined + + if (anchorRef) { +>anchorRef : (CoachMarkAnchorProps> & P)["anchorRef"] | undefined + + anchorRef(anchor); +>anchorRef(anchor) : void +>anchorRef : (anchor: Component) => void +>anchor : Component + } + } + }; + } +} + diff --git a/tests/baselines/reference/unionTypeIndexSignature.types b/tests/baselines/reference/unionTypeIndexSignature.types index b8dc9900404..f20d879a548 100644 --- a/tests/baselines/reference/unionTypeIndexSignature.types +++ b/tests/baselines/reference/unionTypeIndexSignature.types @@ -32,16 +32,16 @@ var unionOfTypesWithAndWithoutStringSignature: { [a: string]: number; } | boolea >a : string anyVar = unionOfTypesWithAndWithoutStringSignature["hello"]; // any ->anyVar = unionOfTypesWithAndWithoutStringSignature["hello"] : any +>anyVar = unionOfTypesWithAndWithoutStringSignature["hello"] : error >anyVar : number ->unionOfTypesWithAndWithoutStringSignature["hello"] : any +>unionOfTypesWithAndWithoutStringSignature["hello"] : error >unionOfTypesWithAndWithoutStringSignature : boolean | { [a: string]: number; } >"hello" : "hello" anyVar = unionOfTypesWithAndWithoutStringSignature[10]; // any ->anyVar = unionOfTypesWithAndWithoutStringSignature[10] : any +>anyVar = unionOfTypesWithAndWithoutStringSignature[10] : error >anyVar : number ->unionOfTypesWithAndWithoutStringSignature[10] : any +>unionOfTypesWithAndWithoutStringSignature[10] : error >unionOfTypesWithAndWithoutStringSignature : boolean | { [a: string]: number; } >10 : 10 @@ -53,9 +53,9 @@ var unionOfDifferentReturnType1: { [a: number]: number; } | { [a: number]: Date; >a : number numOrDate = unionOfDifferentReturnType1["hello"]; // any ->numOrDate = unionOfDifferentReturnType1["hello"] : any +>numOrDate = unionOfDifferentReturnType1["hello"] : error >numOrDate : number | Date ->unionOfDifferentReturnType1["hello"] : any +>unionOfDifferentReturnType1["hello"] : error >unionOfDifferentReturnType1 : { [a: number]: number; } | { [a: number]: Date; } >"hello" : "hello" @@ -71,16 +71,16 @@ var unionOfTypesWithAndWithoutStringSignature1: { [a: number]: number; } | boole >a : number anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"]; // any ->anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"] : any +>anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"] : error >anyVar : number ->unionOfTypesWithAndWithoutStringSignature1["hello"] : any +>unionOfTypesWithAndWithoutStringSignature1["hello"] : error >unionOfTypesWithAndWithoutStringSignature1 : boolean | { [a: number]: number; } >"hello" : "hello" anyVar = unionOfTypesWithAndWithoutStringSignature1[10]; // any ->anyVar = unionOfTypesWithAndWithoutStringSignature1[10] : any +>anyVar = unionOfTypesWithAndWithoutStringSignature1[10] : error >anyVar : number ->unionOfTypesWithAndWithoutStringSignature1[10] : any +>unionOfTypesWithAndWithoutStringSignature1[10] : error >unionOfTypesWithAndWithoutStringSignature1 : boolean | { [a: number]: number; } >10 : 10 diff --git a/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.js b/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.js new file mode 100644 index 00000000000..ec188824455 --- /dev/null +++ b/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.js @@ -0,0 +1,36 @@ +//// [varianceCallbacksAndIndexedAccesses.ts] +type Source = { + (type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; +} + +interface Action1 { + (arg: T): void; +} +interface MessageEventLike { + source: WindowLike; + origin: string; + data: T; +} +interface PostMessageObject { + postMessage(message: T, host: string): void; +} +interface WindowLike extends PostMessageObject { + addEventListener(type: "message", handler: Action1>): void; + addEventListener(type: string, handler: Action1): void; + removeEventListener(type: "message", handler: Action1>): void; + removeEventListener(type: string, handler: Action1): void; +} +type Target = { + (type: "message", handler: Action1>): void; + (type: string, handler: Action1): void; +}; + +function f1(s: Source, t: Target) { + t = s; +} + +//// [varianceCallbacksAndIndexedAccesses.js] +function f1(s, t) { + t = s; +} diff --git a/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.symbols b/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.symbols new file mode 100644 index 00000000000..343d146b5fd --- /dev/null +++ b/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.symbols @@ -0,0 +1,121 @@ +=== tests/cases/compiler/varianceCallbacksAndIndexedAccesses.ts === +type Source = { +>Source : Symbol(Source, Decl(varianceCallbacksAndIndexedAccesses.ts, 0, 0)) + + (type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +>K : Symbol(K, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 5)) +>WindowEventMap : Symbol(WindowEventMap, Decl(lib.dom.d.ts, --, --)) +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 37)) +>K : Symbol(K, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 5)) +>listener : Symbol(listener, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 45)) +>this : Symbol(this, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 57)) +>Window : Symbol(Window, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>ev : Symbol(ev, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 70)) +>WindowEventMap : Symbol(WindowEventMap, Decl(lib.dom.d.ts, --, --)) +>K : Symbol(K, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 5)) +>options : Symbol(options, Decl(varianceCallbacksAndIndexedAccesses.ts, 1, 101)) +>AddEventListenerOptions : Symbol(AddEventListenerOptions, Decl(lib.dom.d.ts, --, --)) + + (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 2, 3)) +>listener : Symbol(listener, Decl(varianceCallbacksAndIndexedAccesses.ts, 2, 16)) +>EventListenerOrEventListenerObject : Symbol(EventListenerOrEventListenerObject, Decl(lib.dom.d.ts, --, --)) +>options : Symbol(options, Decl(varianceCallbacksAndIndexedAccesses.ts, 2, 62)) +>AddEventListenerOptions : Symbol(AddEventListenerOptions, Decl(lib.dom.d.ts, --, --)) +} + +interface Action1 { +>Action1 : Symbol(Action1, Decl(varianceCallbacksAndIndexedAccesses.ts, 3, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 5, 18)) + + (arg: T): void; +>arg : Symbol(arg, Decl(varianceCallbacksAndIndexedAccesses.ts, 6, 5)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 5, 18)) +} +interface MessageEventLike { +>MessageEventLike : Symbol(MessageEventLike, Decl(varianceCallbacksAndIndexedAccesses.ts, 7, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 8, 27)) + + source: WindowLike; +>source : Symbol(MessageEventLike.source, Decl(varianceCallbacksAndIndexedAccesses.ts, 8, 31)) +>WindowLike : Symbol(WindowLike, Decl(varianceCallbacksAndIndexedAccesses.ts, 15, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 8, 27)) + + origin: string; +>origin : Symbol(MessageEventLike.origin, Decl(varianceCallbacksAndIndexedAccesses.ts, 9, 26)) + + data: T; +>data : Symbol(MessageEventLike.data, Decl(varianceCallbacksAndIndexedAccesses.ts, 10, 19)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 8, 27)) +} +interface PostMessageObject { +>PostMessageObject : Symbol(PostMessageObject, Decl(varianceCallbacksAndIndexedAccesses.ts, 12, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 13, 28)) + + postMessage(message: T, host: string): void; +>postMessage : Symbol(PostMessageObject.postMessage, Decl(varianceCallbacksAndIndexedAccesses.ts, 13, 32)) +>message : Symbol(message, Decl(varianceCallbacksAndIndexedAccesses.ts, 14, 16)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 13, 28)) +>host : Symbol(host, Decl(varianceCallbacksAndIndexedAccesses.ts, 14, 27)) +} +interface WindowLike extends PostMessageObject { +>WindowLike : Symbol(WindowLike, Decl(varianceCallbacksAndIndexedAccesses.ts, 15, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 16, 21)) +>PostMessageObject : Symbol(PostMessageObject, Decl(varianceCallbacksAndIndexedAccesses.ts, 12, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 16, 21)) + + addEventListener(type: "message", handler: Action1>): void; +>addEventListener : Symbol(WindowLike.addEventListener, Decl(varianceCallbacksAndIndexedAccesses.ts, 16, 54), Decl(varianceCallbacksAndIndexedAccesses.ts, 17, 83)) +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 17, 21)) +>handler : Symbol(handler, Decl(varianceCallbacksAndIndexedAccesses.ts, 17, 37)) +>Action1 : Symbol(Action1, Decl(varianceCallbacksAndIndexedAccesses.ts, 3, 1)) +>MessageEventLike : Symbol(MessageEventLike, Decl(varianceCallbacksAndIndexedAccesses.ts, 7, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 16, 21)) + + addEventListener(type: string, handler: Action1): void; +>addEventListener : Symbol(WindowLike.addEventListener, Decl(varianceCallbacksAndIndexedAccesses.ts, 16, 54), Decl(varianceCallbacksAndIndexedAccesses.ts, 17, 83)) +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 18, 21)) +>handler : Symbol(handler, Decl(varianceCallbacksAndIndexedAccesses.ts, 18, 34)) +>Action1 : Symbol(Action1, Decl(varianceCallbacksAndIndexedAccesses.ts, 3, 1)) + + removeEventListener(type: "message", handler: Action1>): void; +>removeEventListener : Symbol(WindowLike.removeEventListener, Decl(varianceCallbacksAndIndexedAccesses.ts, 18, 64), Decl(varianceCallbacksAndIndexedAccesses.ts, 19, 86)) +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 19, 24)) +>handler : Symbol(handler, Decl(varianceCallbacksAndIndexedAccesses.ts, 19, 40)) +>Action1 : Symbol(Action1, Decl(varianceCallbacksAndIndexedAccesses.ts, 3, 1)) +>MessageEventLike : Symbol(MessageEventLike, Decl(varianceCallbacksAndIndexedAccesses.ts, 7, 1)) +>T : Symbol(T, Decl(varianceCallbacksAndIndexedAccesses.ts, 16, 21)) + + removeEventListener(type: string, handler: Action1): void; +>removeEventListener : Symbol(WindowLike.removeEventListener, Decl(varianceCallbacksAndIndexedAccesses.ts, 18, 64), Decl(varianceCallbacksAndIndexedAccesses.ts, 19, 86)) +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 20, 24)) +>handler : Symbol(handler, Decl(varianceCallbacksAndIndexedAccesses.ts, 20, 37)) +>Action1 : Symbol(Action1, Decl(varianceCallbacksAndIndexedAccesses.ts, 3, 1)) +} +type Target = { +>Target : Symbol(Target, Decl(varianceCallbacksAndIndexedAccesses.ts, 21, 1)) + + (type: "message", handler: Action1>): void; +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 23, 5)) +>handler : Symbol(handler, Decl(varianceCallbacksAndIndexedAccesses.ts, 23, 21)) +>Action1 : Symbol(Action1, Decl(varianceCallbacksAndIndexedAccesses.ts, 3, 1)) +>MessageEventLike : Symbol(MessageEventLike, Decl(varianceCallbacksAndIndexedAccesses.ts, 7, 1)) + + (type: string, handler: Action1): void; +>type : Symbol(type, Decl(varianceCallbacksAndIndexedAccesses.ts, 24, 5)) +>handler : Symbol(handler, Decl(varianceCallbacksAndIndexedAccesses.ts, 24, 18)) +>Action1 : Symbol(Action1, Decl(varianceCallbacksAndIndexedAccesses.ts, 3, 1)) + +}; + +function f1(s: Source, t: Target) { +>f1 : Symbol(f1, Decl(varianceCallbacksAndIndexedAccesses.ts, 25, 2)) +>s : Symbol(s, Decl(varianceCallbacksAndIndexedAccesses.ts, 27, 12)) +>Source : Symbol(Source, Decl(varianceCallbacksAndIndexedAccesses.ts, 0, 0)) +>t : Symbol(t, Decl(varianceCallbacksAndIndexedAccesses.ts, 27, 22)) +>Target : Symbol(Target, Decl(varianceCallbacksAndIndexedAccesses.ts, 21, 1)) + + t = s; +>t : Symbol(t, Decl(varianceCallbacksAndIndexedAccesses.ts, 27, 22)) +>s : Symbol(s, Decl(varianceCallbacksAndIndexedAccesses.ts, 27, 12)) +} diff --git a/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.types b/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.types new file mode 100644 index 00000000000..6b4d90767b6 --- /dev/null +++ b/tests/baselines/reference/varianceCallbacksAndIndexedAccesses.types @@ -0,0 +1,81 @@ +=== tests/cases/compiler/varianceCallbacksAndIndexedAccesses.ts === +type Source = { +>Source : Source + + (type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +>type : K +>listener : (this: Window, ev: WindowEventMap[K]) => any +>this : Window +>ev : WindowEventMap[K] +>options : boolean | AddEventListenerOptions + + (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; +>type : string +>listener : EventListenerOrEventListenerObject +>options : boolean | AddEventListenerOptions +} + +interface Action1 { + (arg: T): void; +>arg : T +} +interface MessageEventLike { + source: WindowLike; +>source : WindowLike + + origin: string; +>origin : string + + data: T; +>data : T +} +interface PostMessageObject { + postMessage(message: T, host: string): void; +>postMessage : (message: T, host: string) => void +>message : T +>host : string +} +interface WindowLike extends PostMessageObject { + addEventListener(type: "message", handler: Action1>): void; +>addEventListener : { (type: "message", handler: Action1>): void; (type: string, handler: Action1): void; } +>type : "message" +>handler : Action1> + + addEventListener(type: string, handler: Action1): void; +>addEventListener : { (type: "message", handler: Action1>): void; (type: string, handler: Action1): void; } +>type : string +>handler : Action1 + + removeEventListener(type: "message", handler: Action1>): void; +>removeEventListener : { (type: "message", handler: Action1>): void; (type: string, handler: Action1): void; } +>type : "message" +>handler : Action1> + + removeEventListener(type: string, handler: Action1): void; +>removeEventListener : { (type: "message", handler: Action1>): void; (type: string, handler: Action1): void; } +>type : string +>handler : Action1 +} +type Target = { +>Target : Target + + (type: "message", handler: Action1>): void; +>type : "message" +>handler : Action1> + + (type: string, handler: Action1): void; +>type : string +>handler : Action1 + +}; + +function f1(s: Source, t: Target) { +>f1 : (s: Source, t: Target) => void +>s : Source +>t : Target + + t = s; +>t = s : Source +>t : Target +>s : Source +} diff --git a/tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts b/tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts new file mode 100644 index 00000000000..ccacb10dd2d --- /dev/null +++ b/tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts @@ -0,0 +1,48 @@ +// @strict: true +type Omit = Pick>; + +type Shared< // Circularly self constraining type, defered thanks to mapping + InjectedProps, + DecorationTargetProps extends Shared + > = { + [P in Extract]: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; + }; + +interface ComponentClass

{ + defaultProps?: Partial

; // Inference target is also mapped _and_ optional +} + +interface InferableComponentEnhancerWithProps { +

>( + component: ComponentClass

+ ): ComponentClass> & TNeedsProps> & { WrappedComponent: ComponentClass

} +} // Then intersected with and indexed via Omit and & + +interface Connect { // Then strictly compared with another signature in its context + ( + mapStateToProps: unknown, + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: null | undefined, + mapDispatchToProps: unknown, + mergeProps: null | undefined, + options: unknown + ): InferableComponentEnhancerWithProps; +} + +declare var connect: Connect; + +const myStoreConnect: Connect = function( + mapStateToProps?: any, + mapDispatchToProps?: any, + mergeProps?: any, + options: unknown = {}, +) { + return connect( + mapStateToProps, + mapDispatchToProps, + mergeProps, + options, + ); +}; \ No newline at end of file diff --git a/tests/cases/compiler/genericIndexedAccessMethodIntersectionCanBeAccessed.ts b/tests/cases/compiler/genericIndexedAccessMethodIntersectionCanBeAccessed.ts new file mode 100644 index 00000000000..b4d604ff90a --- /dev/null +++ b/tests/cases/compiler/genericIndexedAccessMethodIntersectionCanBeAccessed.ts @@ -0,0 +1,20 @@ +// @strict: true +type ExtendedService = { + [K in keyof T]: T[K] & { + __$daemonMode?: string; + __$action?: string; + }; +}; + +type Service = { + [K in keyof T]: T[K] & {id?: string}; +}; + +export const createService = ( + ServiceCtr: ExtendedService & Service +) => { + Object.keys(ServiceCtr).forEach(key => { + const method = (ServiceCtr)[key as keyof T]; + const {__$daemonMode, __$action, id} = method; + }) +} diff --git a/tests/cases/compiler/spyComparisonChecking.ts b/tests/cases/compiler/spyComparisonChecking.ts new file mode 100644 index 00000000000..68b53de98db --- /dev/null +++ b/tests/cases/compiler/spyComparisonChecking.ts @@ -0,0 +1,23 @@ +interface Spy { + (...params: any[]): any; + + identity: string; + and: Function; + mostRecentCall: { args: any[]; }; + argsForCall: any[]; +} + +type SpyObj = T & { + [k in keyof T]: Spy; +} + +declare function createSpyObj( + name: string, names: Array): SpyObj; + +function mock(spyName: string, methodNames: Array): SpyObj { + const spyObj = createSpyObj(spyName, methodNames); + for (const methodName of methodNames) { + spyObj[methodName].and.returnValue(1); + } + return spyObj; +} \ No newline at end of file diff --git a/tests/cases/compiler/thisIndexOnExistingReadonlyFieldIsNotNever.ts b/tests/cases/compiler/thisIndexOnExistingReadonlyFieldIsNotNever.ts new file mode 100644 index 00000000000..a271cbdbc9c --- /dev/null +++ b/tests/cases/compiler/thisIndexOnExistingReadonlyFieldIsNotNever.ts @@ -0,0 +1,22 @@ +// @strict: true +declare class Component { + readonly props: Readonly<{ children?: unknown }> & Readonly

; + state: Readonly; +} +interface CoachMarkAnchorProps { + anchorRef?: (anchor: C) => void; +} +type AnchorType

= Component

; + +class CoachMarkAnchorDecorator { + decorateComponent

(anchor: P) { + return class CoachMarkAnchor extends Component> & P, {}> { + private _onAnchorRef = (anchor: AnchorType

) => { + const anchorRef = this.props.anchorRef; + if (anchorRef) { + anchorRef(anchor); + } + } + }; + } +} diff --git a/tests/cases/compiler/varianceCallbacksAndIndexedAccesses.ts b/tests/cases/compiler/varianceCallbacksAndIndexedAccesses.ts new file mode 100644 index 00000000000..471829ffd81 --- /dev/null +++ b/tests/cases/compiler/varianceCallbacksAndIndexedAccesses.ts @@ -0,0 +1,32 @@ + + +type Source = { + (type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; +} + +interface Action1 { + (arg: T): void; +} +interface MessageEventLike { + source: WindowLike; + origin: string; + data: T; +} +interface PostMessageObject { + postMessage(message: T, host: string): void; +} +interface WindowLike extends PostMessageObject { + addEventListener(type: "message", handler: Action1>): void; + addEventListener(type: string, handler: Action1): void; + removeEventListener(type: "message", handler: Action1>): void; + removeEventListener(type: string, handler: Action1): void; +} +type Target = { + (type: "message", handler: Action1>): void; + (type: string, handler: Action1): void; +}; + +function f1(s: Source, t: Target) { + t = s; +} \ No newline at end of file From b50c37de785a326752819ef85344097b38e5c81a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 27 Aug 2018 14:12:14 -0700 Subject: [PATCH 55/77] No assert for nameless typedefs (#26695) The assert is over-optimistic and should be removed until we can parse every possible thing that people might put in a JSDoc type position. Fixes #26693 --- src/compiler/utilities.ts | 12 ++++-------- .../noAssertForUnparseableTypedefs.errors.txt | 15 +++++++++++++++ .../noAssertForUnparseableTypedefs.symbols | 5 +++++ .../noAssertForUnparseableTypedefs.types | 5 +++++ .../jsdoc/noAssertForUnparseableTypedefs.ts | 7 +++++++ 5 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt create mode 100644 tests/baselines/reference/noAssertForUnparseableTypedefs.symbols create mode 100644 tests/baselines/reference/noAssertForUnparseableTypedefs.types create mode 100644 tests/cases/conformance/jsdoc/noAssertForUnparseableTypedefs.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 33dfd2617c9..87cf26a1927 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4853,13 +4853,13 @@ namespace ts { if (isDeclaration(hostNode)) { return getDeclarationIdentifier(hostNode); } - // Covers remaining cases + // Covers remaining cases (returning undefined if none match). switch (hostNode.kind) { case SyntaxKind.VariableStatement: if (hostNode.declarationList && hostNode.declarationList.declarations[0]) { return getDeclarationIdentifier(hostNode.declarationList.declarations[0]); } - return undefined; + break; case SyntaxKind.ExpressionStatement: const expr = hostNode.expression; switch (expr.kind) { @@ -4871,9 +4871,7 @@ namespace ts { return arg; } } - return undefined; - case SyntaxKind.EndOfFileToken: - return undefined; + break; case SyntaxKind.ParenthesizedExpression: { return getDeclarationIdentifier(hostNode.expression); } @@ -4881,10 +4879,8 @@ namespace ts { if (isDeclaration(hostNode.statement) || isExpression(hostNode.statement)) { return getDeclarationIdentifier(hostNode.statement); } - return undefined; + break; } - default: - Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!"); } } diff --git a/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt b/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt new file mode 100644 index 00000000000..4876d5276f7 --- /dev/null +++ b/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/jsdoc/bug26693.js(1,15): error TS2304: Cannot find name 'module'. +tests/cases/conformance/jsdoc/bug26693.js(1,21): error TS1005: '}' expected. +tests/cases/conformance/jsdoc/bug26693.js(2,22): error TS2307: Cannot find module 'nope'. + + +==== tests/cases/conformance/jsdoc/bug26693.js (3 errors) ==== + /** @typedef {module:locale} hi */ + ~~~~~~ +!!! error TS2304: Cannot find name 'module'. + ~ +!!! error TS1005: '}' expected. + import { nope } from 'nope'; + ~~~~~~ +!!! error TS2307: Cannot find module 'nope'. + \ No newline at end of file diff --git a/tests/baselines/reference/noAssertForUnparseableTypedefs.symbols b/tests/baselines/reference/noAssertForUnparseableTypedefs.symbols new file mode 100644 index 00000000000..fea0c07d003 --- /dev/null +++ b/tests/baselines/reference/noAssertForUnparseableTypedefs.symbols @@ -0,0 +1,5 @@ +=== tests/cases/conformance/jsdoc/bug26693.js === +/** @typedef {module:locale} hi */ +import { nope } from 'nope'; +>nope : Symbol(nope, Decl(bug26693.js, 1, 8)) + diff --git a/tests/baselines/reference/noAssertForUnparseableTypedefs.types b/tests/baselines/reference/noAssertForUnparseableTypedefs.types new file mode 100644 index 00000000000..3d10e4940b9 --- /dev/null +++ b/tests/baselines/reference/noAssertForUnparseableTypedefs.types @@ -0,0 +1,5 @@ +=== tests/cases/conformance/jsdoc/bug26693.js === +/** @typedef {module:locale} hi */ +import { nope } from 'nope'; +>nope : any + diff --git a/tests/cases/conformance/jsdoc/noAssertForUnparseableTypedefs.ts b/tests/cases/conformance/jsdoc/noAssertForUnparseableTypedefs.ts new file mode 100644 index 00000000000..416004c6514 --- /dev/null +++ b/tests/cases/conformance/jsdoc/noAssertForUnparseableTypedefs.ts @@ -0,0 +1,7 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: bug26693.js + +/** @typedef {module:locale} hi */ +import { nope } from 'nope'; From dfd6aa878cad344e44ea6bf7f65cafb2db1a5483 Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 27 Aug 2018 22:10:39 +0000 Subject: [PATCH 56/77] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 20256 ++++++++-------- 1 file changed, 10128 insertions(+), 10128 deletions(-) diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index e9e3bb6cf83..dc8079b6a53 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,10129 +1,10129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - ou -. Por exemplo '{0}' ou '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - Promessa global.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()' em vez disso.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + ou -. Por exemplo '{0}' ou '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + Promessa global.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()' em vez disso.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From eeabd527ca0f4e00deb16bb3ca0fee1fb57b1d08 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 27 Aug 2018 15:50:26 -0700 Subject: [PATCH 57/77] Examine all constraints of indexed access types in relations --- src/compiler/checker.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9c0f3cd643f..aad60d77f0f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6899,10 +6899,15 @@ namespace ts { } function getConstraintOfIndexedAccess(type: IndexedAccessType) { - const objectType = getBaseConstraintOfType(type.objectType) || type.objectType; - const indexType = getBaseConstraintOfType(type.indexType) || type.indexType; - const constraint = !isGenericObjectType(objectType) && !isGenericIndexType(indexType) ? getIndexedAccessType(objectType, indexType, /*accessNode*/ undefined, errorType) : undefined; - return constraint && constraint !== errorType ? constraint : undefined; + const objectType = getConstraintOfType(type.objectType) || type.objectType; + if (objectType !== type.objectType) { + const constraint = getIndexedAccessType(objectType, type.indexType, /*accessNode*/ undefined, errorType); + if (constraint && constraint !== errorType) { + return constraint; + } + } + const baseConstraint = getBaseConstraintOfType(type); + return baseConstraint && baseConstraint !== type ? baseConstraint : undefined; } function getDefaultConstraintOfConditionalType(type: ConditionalType) { @@ -7074,9 +7079,6 @@ namespace ts { if (t.flags & TypeFlags.Substitution) { return getBaseConstraint((t).substitute); } - if (isGenericMappedType(t)) { - return emptyObjectType; - } return t; } } @@ -11642,12 +11644,13 @@ namespace ts { } } else if (target.flags & TypeFlags.IndexedAccess) { - // A type S is related to a type T[K] if S is related to C, where C is the - // constraint of T[K] - const constraint = getConstraintForRelation(target); - if (constraint) { - if (result = isRelatedTo(source, constraint, reportErrors)) { - return result; + // A type S is related to a type T[K] if S is related to C, where C is the base constraint of T[K] + if (relation !== identityRelation) { + const constraint = getBaseConstraintOfType(target); + if (constraint && constraint !== target) { + if (result = isRelatedTo(source, constraint, reportErrors)) { + return result; + } } } } From 4cf5774c5e22ec5627e1f8fadca35e7d47a1b38d Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 27 Aug 2018 16:04:02 -0700 Subject: [PATCH 58/77] Add tsserver test for completions and avoid excess properties (#25622) --- src/server/protocol.ts | 2 +- src/services/codefixes/importFixes.ts | 7 +- .../unittests/tsserverProjectSystem.ts | 122 ++++++++++++++++++ .../reference/api/tsserverlibrary.d.ts | 2 +- 4 files changed, 130 insertions(+), 3 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index f8e94085c47..39a0045d97e 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1839,7 +1839,7 @@ namespace ts.server.protocol { * begin with prefix. */ export interface CompletionsRequest extends FileLocationRequest { - command: CommandTypes.Completions; + command: CommandTypes.Completions | CommandTypes.CompletionInfo; arguments: CompletionsRequestArgs; } diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 030b9286741..3c5b1d06eaf 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -168,8 +168,13 @@ namespace ts.codefix { // We sort the best codefixes first, so taking `first` is best for completions. const moduleSpecifier = first(getNewImportInfos(program, sourceFile, position, exportInfos, host, preferences)).moduleSpecifier; const fix = first(getFixForImport(exportInfos, symbolName, position, program, sourceFile, host, preferences)); - return { moduleSpecifier, codeAction: codeActionForFix({ host, formatContext }, sourceFile, symbolName, fix, getQuotePreference(sourceFile, preferences)) }; + return { moduleSpecifier, codeAction: codeFixActionToCodeAction(codeActionForFix({ host, formatContext }, sourceFile, symbolName, fix, getQuotePreference(sourceFile, preferences))) }; } + + function codeFixActionToCodeAction({ description, changes, commands }: CodeFixAction): CodeAction { + return { description, changes, commands }; + } + function getAllReExportingModules(exportedSymbol: Symbol, exportingModuleSymbol: Symbol, symbolName: string, sourceFile: SourceFile, checker: TypeChecker, allSourceFiles: ReadonlyArray): ReadonlyArray { const result: SymbolExportInfo[] = []; forEachExternalModule(checker, allSourceFiles, (moduleSymbol, moduleFile) => { diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index b99a2d9fe99..589668538c7 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -9210,6 +9210,128 @@ export function Test2() { }); }); + describe("tsserverProjectSystem completions", () => { + it("works", () => { + const aTs: File = { + path: "/a.ts", + content: "export const foo = 0;", + }; + const bTs: File = { + path: "/b.ts", + content: "foo", + }; + const tsconfig: File = { + path: "/tsconfig.json", + content: "{}", + }; + + const host = createServerHost([aTs, bTs, tsconfig]); + const session = createSession(host); + openFilesForSession([aTs, bTs], session); + + const requestLocation: protocol.FileLocationRequestArgs = { + file: bTs.path, + line: 1, + offset: 3, + }; + + const response = executeSessionRequest(session, protocol.CommandTypes.CompletionInfo, { + ...requestLocation, + includeExternalModuleExports: true, + prefix: "foo", + }); + const entry: protocol.CompletionEntry = { + hasAction: true, + insertText: undefined, + isRecommended: undefined, + kind: ScriptElementKind.constElement, + kindModifiers: ScriptElementKindModifier.exportedModifier, + name: "foo", + replacementSpan: undefined, + sortText: "0", + source: "/a", + }; + assert.deepEqual(response, { + isGlobalCompletion: true, + isMemberCompletion: false, + isNewIdentifierLocation: false, + entries: [entry], + }); + + const detailsRequestArgs: protocol.CompletionDetailsRequestArgs = { + ...requestLocation, + entryNames: [{ name: "foo", source: "/a" }], + }; + + const detailsResponse = executeSessionRequest(session, protocol.CommandTypes.CompletionDetails, detailsRequestArgs); + const detailsCommon: protocol.CompletionEntryDetails & CompletionEntryDetails = { + displayParts: [ + keywordPart(SyntaxKind.ConstKeyword), + spacePart(), + displayPart("foo", SymbolDisplayPartKind.localName), + punctuationPart(SyntaxKind.ColonToken), + spacePart(), + displayPart("0", SymbolDisplayPartKind.stringLiteral), + ], + documentation: emptyArray, + kind: ScriptElementKind.constElement, + kindModifiers: ScriptElementKindModifier.exportedModifier, + name: "foo", + source: [{ text: "./a", kind: "text" }], + tags: emptyArray, + }; + assert.deepEqual | undefined>(detailsResponse, [ + { + codeActions: [ + { + description: `Import 'foo' from module "./a"`, + changes: [ + { + fileName: "/b.ts", + textChanges: [ + { + start: { line: 1, offset: 1 }, + end: { line: 1, offset: 1 }, + newText: 'import { foo } from "./a";\n\n', + }, + ], + }, + ], + commands: undefined, + }, + ], + ...detailsCommon, + }, + ]); + + interface CompletionDetailsFullRequest extends protocol.FileLocationRequest { + readonly command: protocol.CommandTypes.CompletionDetailsFull; + readonly arguments: protocol.CompletionDetailsRequestArgs; + } + interface CompletionDetailsFullResponse extends protocol.Response { + readonly body?: ReadonlyArray; + } + const detailsFullResponse = executeSessionRequest(session, protocol.CommandTypes.CompletionDetailsFull, detailsRequestArgs); + assert.deepEqual | undefined>(detailsFullResponse, [ + { + codeActions: [ + { + description: `Import 'foo' from module "./a"`, + changes: [ + { + fileName: "/b.ts", + textChanges: [createTextChange(createTextSpan(0, 0), 'import { foo } from "./a";\n\n')], + }, + ], + commands: undefined, + } + ], + ...detailsCommon, + } + ]); + }); + }); + describe("tsserverProjectSystem project references", () => { const aTs: File = { path: "/a/a.ts", diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5e992f3847a..584557e8b0f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6948,7 +6948,7 @@ declare namespace ts.server.protocol { * begin with prefix. */ interface CompletionsRequest extends FileLocationRequest { - command: CommandTypes.Completions; + command: CommandTypes.Completions | CommandTypes.CompletionInfo; arguments: CompletionsRequestArgs; } /** From 9f83958dbe05dfaf2b3072e6cece68c7d5d7b1e9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 27 Aug 2018 16:06:17 -0700 Subject: [PATCH 59/77] Add tests --- .../types/keyof/keyofAndIndexedAccess.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index c76071f7d99..7748240f80d 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -651,3 +651,17 @@ function ff2(dd: DictDict, k1: V, k2: const d: Dict = dd[k1]; return d[k2]; } + +// Repro from #26409 + +const cf1 = (t: T, k: K) => +{ + const s: string = t[k]; + t.cool; +}; + +const cf2 = (t: T, k: K) => +{ + const s: string = t[k]; + t.cool; +}; From d369cecd101a0c7b8172fad2dec68337916d929d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 27 Aug 2018 16:06:26 -0700 Subject: [PATCH 60/77] Accept new baselines --- .../reference/keyofAndIndexedAccess.js | 27 ++++++++++ .../reference/keyofAndIndexedAccess.symbols | 51 +++++++++++++++++++ .../reference/keyofAndIndexedAccess.types | 41 +++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index cc0498fcfe2..873fa2a035a 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -649,6 +649,20 @@ function ff2(dd: DictDict, k1: V, k2: const d: Dict = dd[k1]; return d[k2]; } + +// Repro from #26409 + +const cf1 = (t: T, k: K) => +{ + const s: string = t[k]; + t.cool; +}; + +const cf2 = (t: T, k: K) => +{ + const s: string = t[k]; + t.cool; +}; //// [keyofAndIndexedAccess.js] @@ -1078,6 +1092,15 @@ function ff2(dd, k1, k2) { var d = dd[k1]; return d[k2]; } +// Repro from #26409 +var cf1 = function (t, k) { + var s = t[k]; + t.cool; +}; +var cf2 = function (t, k) { + var s = t[k]; + t.cool; +}; //// [keyofAndIndexedAccess.d.ts] @@ -1413,3 +1436,7 @@ declare type DictDict = { }; declare function ff1(dd: DictDict, k1: V, k2: T): number; declare function ff2(dd: DictDict, k1: V, k2: T): number; +declare const cf1: (t: T, k: K) => void; +declare const cf2: (t: T, k: K) => void; diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index c8bb9f14da7..15cc704c481 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -2319,3 +2319,54 @@ function ff2(dd: DictDict, k1: V, k2: >k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 646, 75)) } +// Repro from #26409 + +const cf1 = (t: T, k: K) => +>cf1 : Symbol(cf1, Decl(keyofAndIndexedAccess.ts, 653, 5)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 653, 13)) +>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 653, 26)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 653, 65)) +>cool : Symbol(cool, Decl(keyofAndIndexedAccess.ts, 653, 48)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 653, 65)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 653, 13)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 653, 85)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 653, 13)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 653, 90)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 653, 65)) +{ + const s: string = t[k]; +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 655, 9)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 653, 85)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 653, 90)) + + t.cool; +>t.cool : Symbol(cool, Decl(keyofAndIndexedAccess.ts, 653, 48)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 653, 85)) +>cool : Symbol(cool, Decl(keyofAndIndexedAccess.ts, 653, 48)) + +}; + +const cf2 = (t: T, k: K) => +>cf2 : Symbol(cf2, Decl(keyofAndIndexedAccess.ts, 659, 5)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 659, 13)) +>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 659, 26)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 659, 54)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 659, 54)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 659, 13)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 659, 74)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 659, 13)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 659, 79)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 659, 54)) +{ + const s: string = t[k]; +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 661, 9)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 659, 74)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 659, 79)) + + t.cool; +>t.cool : Symbol(cool) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 659, 74)) +>cool : Symbol(cool) + +}; + diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index 3434d003d54..58fd74f6601 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -2184,3 +2184,44 @@ function ff2(dd: DictDict, k1: V, k2: >k2 : T } +// Repro from #26409 + +const cf1 = (t: T, k: K) => +>cf1 : (t: T, k: K) => void +>(t: T, k: K) =>{ const s: string = t[k]; t.cool;} : (t: T, k: K) => void +>cool : string +>t : T +>k : K +{ + const s: string = t[k]; +>s : string +>t[k] : T[K] +>t : T +>k : K + + t.cool; +>t.cool : string +>t : T +>cool : string + +}; + +const cf2 = (t: T, k: K) => +>cf2 : (t: T, k: K) => void +>(t: T, k: K) =>{ const s: string = t[k]; t.cool;} : (t: T, k: K) => void +>t : T +>k : K +{ + const s: string = t[k]; +>s : string +>t[k] : T[K] +>t : T +>k : K + + t.cool; +>t.cool : string +>t : T +>cool : string + +}; + From a2e4a282e799fe724e86e06a18157e7aca14392e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 27 Aug 2018 16:52:35 -0700 Subject: [PATCH 61/77] Get [type] parameter types from @type tag (#26694) * Get [type] parameter types from @type tag Previously only the return type was used in cases like this: ```js /** @type {(param?: T) => T | undefined} */ function g(param) { return param; } ``` Now the type parameters from the type tag are used, and the compiler gets the type of the parameter by using the position in the signature of the type tag. Fixes #25618 * Fix split ifs according to PR comments --- src/compiler/checker.ts | 6 ++++++ src/compiler/utilities.ts | 15 ++++++++++++++- .../typeTagWithGenericSignature.symbols | 15 +++++++++++++++ .../reference/typeTagWithGenericSignature.types | 17 +++++++++++++++++ .../jsdoc/typeTagWithGenericSignature.ts | 13 +++++++++++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/typeTagWithGenericSignature.symbols create mode 100644 tests/baselines/reference/typeTagWithGenericSignature.types create mode 100644 tests/cases/conformance/jsdoc/typeTagWithGenericSignature.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9c0f3cd643f..679cb79e0cf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4699,6 +4699,12 @@ namespace ts { return getReturnTypeOfSignature(getterSignature); } } + if (isInJavaScriptFile(declaration)) { + const typeTag = getJSDocType(func); + if (typeTag && isFunctionTypeNode(typeTag)) { + return getTypeAtPosition(getSignatureFromDeclaration(typeTag), func.parameters.indexOf(declaration)); + } + } // Use contextual parameter type if one is available const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration); if (type) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 87cf26a1927..6b905ad65ca 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5116,7 +5116,20 @@ namespace ts { Debug.assert(node.parent.kind === SyntaxKind.JSDocComment); return flatMap(node.parent.tags, tag => isJSDocTemplateTag(tag) ? tag.typeParameters : undefined) as ReadonlyArray; } - return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : emptyArray); + if (node.typeParameters) { + return node.typeParameters; + } + if (isInJavaScriptFile(node)) { + const decls = getJSDocTypeParameterDeclarations(node); + if (decls.length) { + return decls; + } + const typeTag = getJSDocType(node); + if (typeTag && isFunctionTypeNode(typeTag) && typeTag.typeParameters) { + return typeTag.typeParameters; + } + } + return emptyArray; } export function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined { diff --git a/tests/baselines/reference/typeTagWithGenericSignature.symbols b/tests/baselines/reference/typeTagWithGenericSignature.symbols new file mode 100644 index 00000000000..c9a699d3b4a --- /dev/null +++ b/tests/baselines/reference/typeTagWithGenericSignature.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/jsdoc/bug25618.js === +/** @type {(param?: T) => T | undefined} */ +function typed(param) { +>typed : Symbol(typed, Decl(bug25618.js, 0, 0)) +>param : Symbol(param, Decl(bug25618.js, 1, 15)) + + return param; +>param : Symbol(param, Decl(bug25618.js, 1, 15)) +} + +var n = typed(1); +>n : Symbol(n, Decl(bug25618.js, 5, 3)) +>typed : Symbol(typed, Decl(bug25618.js, 0, 0)) + + diff --git a/tests/baselines/reference/typeTagWithGenericSignature.types b/tests/baselines/reference/typeTagWithGenericSignature.types new file mode 100644 index 00000000000..585fd49fbf4 --- /dev/null +++ b/tests/baselines/reference/typeTagWithGenericSignature.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/jsdoc/bug25618.js === +/** @type {(param?: T) => T | undefined} */ +function typed(param) { +>typed : (param: T | undefined) => T | undefined +>param : T | undefined + + return param; +>param : T | undefined +} + +var n = typed(1); +>n : number | undefined +>typed(1) : 1 | undefined +>typed : (param: T | undefined) => T | undefined +>1 : 1 + + diff --git a/tests/cases/conformance/jsdoc/typeTagWithGenericSignature.ts b/tests/cases/conformance/jsdoc/typeTagWithGenericSignature.ts new file mode 100644 index 00000000000..04ef3e5e1a0 --- /dev/null +++ b/tests/cases/conformance/jsdoc/typeTagWithGenericSignature.ts @@ -0,0 +1,13 @@ +// @checkJs: true +// @allowJs: true +// @noEmit: true +// @strict: true +// @Filename: bug25618.js + +/** @type {(param?: T) => T | undefined} */ +function typed(param) { + return param; +} + +var n = typed(1); + From 72239456667645cf5bd9a6fc06a057c42b25ff0d Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 27 Aug 2018 17:03:30 -0700 Subject: [PATCH 62/77] Use array helper in computeCommonSourceDirectory and remove two unnecessary tests (#26416) --- src/compiler/program.ts | 25 +++++++++---------------- src/compiler/utilities.ts | 2 -- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index abbc935cf65..670e2c200d8 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2319,27 +2319,20 @@ namespace ts { } function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string { - const fileNames: string[] = []; - for (const file of sourceFiles) { - if (!file.isDeclarationFile) { - fileNames.push(file.fileName); - } - } + const fileNames = mapDefined(sourceFiles, file => file.isDeclarationFile ? undefined : file.fileName); return computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName); } - function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean { + function checkSourceFilesBelongToPath(sourceFiles: ReadonlyArray, rootDirectory: string): boolean { let allFilesBelongToPath = true; - if (sourceFiles) { - const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); - for (const sourceFile of sourceFiles) { - if (!sourceFile.isDeclarationFile) { - const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); - if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, rootDirectory)); - allFilesBelongToPath = false; - } + for (const sourceFile of sourceFiles) { + if (!sourceFile.isDeclarationFile) { + const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, rootDirectory)); + allFilesBelongToPath = false; } } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6b905ad65ca..39a298329c7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -7302,8 +7302,6 @@ namespace ts { if (pathComponents.length === 0) return ""; const root = pathComponents[0] && ensureTrailingDirectorySeparator(pathComponents[0]); - if (pathComponents.length === 1) return root; - return root + pathComponents.slice(1).join(directorySeparator); } From d7580755974df4fe3d64af54462b855d3f9f8f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Thu, 9 Aug 2018 16:40:11 +0800 Subject: [PATCH 63/77] add special check for parameter initializer lookup if targeting es2015+ --- src/compiler/checker.ts | 16 ++-- ...InitializersForwardReferencing1.errors.txt | 45 ++++++++++++ ...arameterInitializersForwardReferencing1.js | 61 ++++++++++++++++ ...terInitializersForwardReferencing1.symbols | 67 +++++++++++++++++ ...meterInitializersForwardReferencing1.types | 73 +++++++++++++++++++ ...ializersForwardReferencing1_es6.errors.txt | 36 +++++++++ ...eterInitializersForwardReferencing1_es6.js | 51 +++++++++++++ ...nitializersForwardReferencing1_es6.symbols | 67 +++++++++++++++++ ...rInitializersForwardReferencing1_es6.types | 73 +++++++++++++++++++ ...arameterInitializersForwardReferencing1.ts | 27 +++++++ ...eterInitializersForwardReferencing1_es6.ts | 29 ++++++++ 11 files changed, 540 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1.js create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1.symbols create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1.types create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types create mode 100644 tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts create mode 100644 tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51eeb0fdb48..36c6d71f672 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1197,16 +1197,22 @@ namespace ts { : false; } if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) { - // parameters are visible only inside function body, parameter list and return type - // technically for parameter list case here we might mix parameters and variables declared in function, - // however it is detected separately when checking initializers of parameters - // to make sure that they reference no variables declared after them. - useResult = + // parameter initializer will lookup as normal variable scope when targeting es2015+ + if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && lastLocation.initializer === originalLocation && result.valueDeclaration !== lastLocation) { + useResult = false; + } + else { + // parameters are visible only inside function body, parameter list and return type + // technically for parameter list case here we might mix parameters and variables declared in function, + // however it is detected separately when checking initializers of parameters + // to make sure that they reference no variables declared after them. + useResult = lastLocation.kind === SyntaxKind.Parameter || ( lastLocation === (location).type && !!findAncestor(result.valueDeclaration, isParameter) ); + } } } else if (location.kind === SyntaxKind.ConditionalType) { diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt new file mode 100644 index 00000000000..9879ec320ca --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt @@ -0,0 +1,45 @@ +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(3,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(8,27): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer. + + +==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (5 errors) ==== + let foo: string = ""; + + function f1 (bar = foo) { // unexpected compiler error; works at runtime + ~~~ +!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. + var foo: number = 2; + return bar; // returns 1 + } + + function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime + ~~~ +!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. + var foo: number = 2; + return bar(); // returns 1 + } + + function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime + ~~~ +!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. + return bar; + } + + function f4 (foo, bar = foo) { + return bar + } + + function f5 (a = a) { + ~ +!!! error TS2372: Parameter 'a' cannot be referenced in its initializer. + return a + } + + function f6 (async = async) { + ~~~~~ +!!! error TS2372: Parameter 'async' cannot be referenced in its initializer. + return async + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.js b/tests/baselines/reference/parameterInitializersForwardReferencing1.js new file mode 100644 index 00000000000..43f303a94cd --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.js @@ -0,0 +1,61 @@ +//// [parameterInitializersForwardReferencing1.ts] +let foo: string = ""; + +function f1 (bar = foo) { // unexpected compiler error; works at runtime + var foo: number = 2; + return bar; // returns 1 +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime + var foo: number = 2; + return bar(); // returns 1 +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime + return bar; +} + +function f4 (foo, bar = foo) { + return bar +} + +function f5 (a = a) { + return a +} + +function f6 (async = async) { + return async +} + +//// [parameterInitializersForwardReferencing1.js] +var foo = ""; +function f1(bar) { + if (bar === void 0) { bar = foo; } + var foo = 2; + return bar; // returns 1 +} +function f2(bar) { + if (bar === void 0) { bar = function (baz) { + if (baz === void 0) { baz = foo; } + return baz; + }; } + var foo = 2; + return bar(); // returns 1 +} +function f3(bar, foo) { + if (bar === void 0) { bar = foo; } + if (foo === void 0) { foo = 2; } + return bar; +} +function f4(foo, bar) { + if (bar === void 0) { bar = foo; } + return bar; +} +function f5(a) { + if (a === void 0) { a = a; } + return a; +} +function f6(async) { + if (async === void 0) { async = async; } + return async; +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols b/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols new file mode 100644 index 00000000000..6860e39fd8d --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols @@ -0,0 +1,67 @@ +=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts === +let foo: string = ""; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 0, 3)) + +function f1 (bar = foo) { // unexpected compiler error; works at runtime +>f1 : Symbol(f1, Decl(parameterInitializersForwardReferencing1.ts, 0, 21)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 2, 13)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 3, 7)) + + var foo: number = 2; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 3, 7)) + + return bar; // returns 1 +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 2, 13)) +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime +>f2 : Symbol(f2, Decl(parameterInitializersForwardReferencing1.ts, 5, 1)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 7, 13)) +>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1.ts, 7, 20)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 8, 7)) +>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1.ts, 7, 20)) + + var foo: number = 2; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 8, 7)) + + return bar(); // returns 1 +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 7, 13)) +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime +>f3 : Symbol(f3, Decl(parameterInitializersForwardReferencing1.ts, 10, 1)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 12, 13)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 12, 23)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 12, 23)) + + return bar; +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 12, 13)) +} + +function f4 (foo, bar = foo) { +>f4 : Symbol(f4, Decl(parameterInitializersForwardReferencing1.ts, 14, 1)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 16, 13)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 16, 17)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 16, 13)) + + return bar +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 16, 17)) +} + +function f5 (a = a) { +>f5 : Symbol(f5, Decl(parameterInitializersForwardReferencing1.ts, 18, 1)) +>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13)) +>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13)) + + return a +>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13)) +} + +function f6 (async = async) { +>f6 : Symbol(f6, Decl(parameterInitializersForwardReferencing1.ts, 22, 1)) +>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13)) +>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13)) + + return async +>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13)) +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.types b/tests/baselines/reference/parameterInitializersForwardReferencing1.types new file mode 100644 index 00000000000..c33c227a37a --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts === +let foo: string = ""; +>foo : string +>"" : "" + +function f1 (bar = foo) { // unexpected compiler error; works at runtime +>f1 : (bar?: number) => number +>bar : number +>foo : number + + var foo: number = 2; +>foo : number +>2 : 2 + + return bar; // returns 1 +>bar : number +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime +>f2 : (bar?: (baz?: number) => number) => number +>bar : (baz?: number) => number +>(baz = foo) => baz : (baz?: number) => number +>baz : number +>foo : number +>baz : number + + var foo: number = 2; +>foo : number +>2 : 2 + + return bar(); // returns 1 +>bar() : number +>bar : (baz?: number) => number +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime +>f3 : (bar?: number, foo?: number) => number +>bar : number +>foo : number +>foo : number +>2 : 2 + + return bar; +>bar : number +} + +function f4 (foo, bar = foo) { +>f4 : (foo: any, bar?: any) => any +>foo : any +>bar : any +>foo : any + + return bar +>bar : any +} + +function f5 (a = a) { +>f5 : (a?: any) => any +>a : any +>a : any + + return a +>a : any +} + +function f6 (async = async) { +>f6 : (async?: any) => any +>async : any +>async : any + + return async +>async : any +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt new file mode 100644 index 00000000000..cffa83707e0 --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer. + + +==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts (2 errors) ==== + let foo: string = ""; + + function f1 (bar = foo) { // unexpected compiler error; works at runtime + var foo: number = 2; + return bar; // returns 1 + } + + function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime + var fooo: number = 2; + return bar(); // returns 1 + } + + function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime + return bar; + } + + function f4 (foo, bar = foo) { + return bar + } + + function f5 (a = a) { + ~ +!!! error TS2372: Parameter 'a' cannot be referenced in its initializer. + return a + } + + function f6 (async = async) { + ~~~~~ +!!! error TS2372: Parameter 'async' cannot be referenced in its initializer. + return async + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js new file mode 100644 index 00000000000..add0837e312 --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js @@ -0,0 +1,51 @@ +//// [parameterInitializersForwardReferencing1_es6.ts] +let foo: string = ""; + +function f1 (bar = foo) { // unexpected compiler error; works at runtime + var foo: number = 2; + return bar; // returns 1 +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime + var fooo: number = 2; + return bar(); // returns 1 +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime + return bar; +} + +function f4 (foo, bar = foo) { + return bar +} + +function f5 (a = a) { + return a +} + +function f6 (async = async) { + return async +} + +//// [parameterInitializersForwardReferencing1_es6.js] +let foo = ""; +function f1(bar = foo) { + var foo = 2; + return bar; // returns 1 +} +function f2(bar = (baz = foo) => baz) { + var fooo = 2; + return bar(); // returns 1 +} +function f3(bar = foo, foo = 2) { + return bar; +} +function f4(foo, bar = foo) { + return bar; +} +function f5(a = a) { + return a; +} +function f6(async = async) { + return async; +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols new file mode 100644 index 00000000000..c38a392c4d8 --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols @@ -0,0 +1,67 @@ +=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts === +let foo: string = ""; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) + +function f1 (bar = foo) { // unexpected compiler error; works at runtime +>f1 : Symbol(f1, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 21)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 2, 13)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) + + var foo: number = 2; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 3, 7)) + + return bar; // returns 1 +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 2, 13)) +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime +>f2 : Symbol(f2, Decl(parameterInitializersForwardReferencing1_es6.ts, 5, 1)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 13)) +>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 20)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) +>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 20)) + + var fooo: number = 2; +>fooo : Symbol(fooo, Decl(parameterInitializersForwardReferencing1_es6.ts, 8, 7)) + + return bar(); // returns 1 +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 13)) +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime +>f3 : Symbol(f3, Decl(parameterInitializersForwardReferencing1_es6.ts, 10, 1)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 12, 13)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 12, 23)) + + return bar; +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 12, 13)) +} + +function f4 (foo, bar = foo) { +>f4 : Symbol(f4, Decl(parameterInitializersForwardReferencing1_es6.ts, 14, 1)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 16, 13)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 16, 17)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) + + return bar +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 16, 17)) +} + +function f5 (a = a) { +>f5 : Symbol(f5, Decl(parameterInitializersForwardReferencing1_es6.ts, 18, 1)) +>a : Symbol(a, Decl(parameterInitializersForwardReferencing1_es6.ts, 20, 13)) +>a : Symbol(a, Decl(parameterInitializersForwardReferencing1_es6.ts, 20, 13)) + + return a +>a : Symbol(a, Decl(parameterInitializersForwardReferencing1_es6.ts, 20, 13)) +} + +function f6 (async = async) { +>f6 : Symbol(f6, Decl(parameterInitializersForwardReferencing1_es6.ts, 22, 1)) +>async : Symbol(async, Decl(parameterInitializersForwardReferencing1_es6.ts, 24, 13)) +>async : Symbol(async, Decl(parameterInitializersForwardReferencing1_es6.ts, 24, 13)) + + return async +>async : Symbol(async, Decl(parameterInitializersForwardReferencing1_es6.ts, 24, 13)) +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types new file mode 100644 index 00000000000..bd17f482335 --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts === +let foo: string = ""; +>foo : string +>"" : "" + +function f1 (bar = foo) { // unexpected compiler error; works at runtime +>f1 : (bar?: string) => string +>bar : string +>foo : string + + var foo: number = 2; +>foo : number +>2 : 2 + + return bar; // returns 1 +>bar : string +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime +>f2 : (bar?: (baz?: string) => string) => string +>bar : (baz?: string) => string +>(baz = foo) => baz : (baz?: string) => string +>baz : string +>foo : string +>baz : string + + var fooo: number = 2; +>fooo : number +>2 : 2 + + return bar(); // returns 1 +>bar() : string +>bar : (baz?: string) => string +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime +>f3 : (bar?: string, foo?: number) => string +>bar : string +>foo : string +>foo : number +>2 : 2 + + return bar; +>bar : string +} + +function f4 (foo, bar = foo) { +>f4 : (foo: any, bar?: string) => string +>foo : any +>bar : string +>foo : string + + return bar +>bar : string +} + +function f5 (a = a) { +>f5 : (a?: any) => any +>a : any +>a : any + + return a +>a : any +} + +function f6 (async = async) { +>f6 : (async?: any) => any +>async : any +>async : any + + return async +>async : any +} diff --git a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts new file mode 100644 index 00000000000..8492a053856 --- /dev/null +++ b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts @@ -0,0 +1,27 @@ +let foo: string = ""; + +function f1 (bar = foo) { // unexpected compiler error; works at runtime + var foo: number = 2; + return bar; // returns 1 +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime + var foo: number = 2; + return bar(); // returns 1 +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime + return bar; +} + +function f4 (foo, bar = foo) { + return bar +} + +function f5 (a = a) { + return a +} + +function f6 (async = async) { + return async +} \ No newline at end of file diff --git a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts new file mode 100644 index 00000000000..dfd6b8d4e1a --- /dev/null +++ b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts @@ -0,0 +1,29 @@ +// @target: es2015 + +let foo: string = ""; + +function f1 (bar = foo) { // unexpected compiler error; works at runtime + var foo: number = 2; + return bar; // returns 1 +} + +function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime + var fooo: number = 2; + return bar(); // returns 1 +} + +function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime + return bar; +} + +function f4 (foo, bar = foo) { + return bar +} + +function f5 (a = a) { + return a +} + +function f6 (async = async) { + return async +} \ No newline at end of file From 8869f39c25f8e9e7660ada38f0d33fcea714e49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Tue, 28 Aug 2018 16:41:26 +0800 Subject: [PATCH 64/77] accept more case --- src/compiler/checker.ts | 6 +++--- ...eterInitializersForwardReferencing1.errors.txt | 13 +++++++++++-- .../parameterInitializersForwardReferencing1.js | 11 ++++++++++- ...rameterInitializersForwardReferencing1.symbols | 10 ++++++++++ ...parameterInitializersForwardReferencing1.types | 11 +++++++++++ ...InitializersForwardReferencing1_es6.errors.txt | 9 +++++++-- ...arameterInitializersForwardReferencing1_es6.js | 14 +++++++++++--- ...terInitializersForwardReferencing1_es6.symbols | 14 ++++++++++++-- ...meterInitializersForwardReferencing1_es6.types | 15 +++++++++++++-- .../parameterInitializersForwardReferencing1.ts | 6 +++++- ...arameterInitializersForwardReferencing1_es6.ts | 8 ++++++-- 11 files changed, 99 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 36c6d71f672..063044eda68 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1196,12 +1196,12 @@ namespace ts { // local types not visible outside the function body : false; } - if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) { + if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.Variable) { // parameter initializer will lookup as normal variable scope when targeting es2015+ - if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && lastLocation.initializer === originalLocation && result.valueDeclaration !== lastLocation) { + if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && result.valueDeclaration !== lastLocation) { useResult = false; } - else { + else if (result.flags & SymbolFlags.FunctionScopedVariable) { // parameters are visible only inside function body, parameter list and return type // technically for parameter list case here we might mix parameters and variables declared in function, // however it is detected separately when checking initializers of parameters diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt index 9879ec320ca..055a37838f1 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt @@ -3,9 +3,10 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(8, tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer. tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29,15): error TS2448: Block-scoped variable 'foo' used before its declaration. -==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (5 errors) ==== +==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (6 errors) ==== let foo: string = ""; function f1 (bar = foo) { // unexpected compiler error; works at runtime @@ -42,4 +43,12 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25 ~~~~~ !!! error TS2372: Parameter 'async' cannot be referenced in its initializer. return async - } \ No newline at end of file + } + + function f7({[foo]: bar}: any[]) { + ~~~ +!!! error TS2448: Block-scoped variable 'foo' used before its declaration. +!!! related TS2728 tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts:30:9: 'foo' is declared here. + let foo: number = 2; + } + \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.js b/tests/baselines/reference/parameterInitializersForwardReferencing1.js index 43f303a94cd..ad68f64ca2c 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.js +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.js @@ -25,7 +25,12 @@ function f5 (a = a) { function f6 (async = async) { return async -} +} + +function f7({[foo]: bar}: any[]) { + let foo: number = 2; +} + //// [parameterInitializersForwardReferencing1.js] var foo = ""; @@ -59,3 +64,7 @@ function f6(async) { if (async === void 0) { async = async; } return async; } +function f7(_a) { + var _b = foo, bar = _a[_b]; + var foo = 2; +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols b/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols index 6860e39fd8d..f3ea0f1e7e8 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols @@ -65,3 +65,13 @@ function f6 (async = async) { return async >async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13)) } + +function f7({[foo]: bar}: any[]) { +>f7 : Symbol(f7, Decl(parameterInitializersForwardReferencing1.ts, 26, 1)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 29, 7)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 28, 13)) + + let foo: number = 2; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 29, 7)) +} + diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.types b/tests/baselines/reference/parameterInitializersForwardReferencing1.types index c33c227a37a..3a1d8d5864f 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.types +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.types @@ -71,3 +71,14 @@ function f6 (async = async) { return async >async : any } + +function f7({[foo]: bar}: any[]) { +>f7 : ({ [foo]: bar }: any[]) => void +>foo : number +>bar : any + + let foo: number = 2; +>foo : number +>2 : 2 +} + diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt index cffa83707e0..e7708894b65 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt @@ -11,7 +11,7 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.t } function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime - var fooo: number = 2; + var foo: number = 2; return bar(); // returns 1 } @@ -33,4 +33,9 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.t ~~~~~ !!! error TS2372: Parameter 'async' cannot be referenced in its initializer. return async - } \ No newline at end of file + } + + function f7({[foo]: bar}: any[]) { + let foo: number = 2; + } + \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js index add0837e312..0c89b79b764 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js @@ -7,7 +7,7 @@ function f1 (bar = foo) { // unexpected compiler error; works at runtime } function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime - var fooo: number = 2; + var foo: number = 2; return bar(); // returns 1 } @@ -25,7 +25,12 @@ function f5 (a = a) { function f6 (async = async) { return async -} +} + +function f7({[foo]: bar}: any[]) { + let foo: number = 2; +} + //// [parameterInitializersForwardReferencing1_es6.js] let foo = ""; @@ -34,7 +39,7 @@ function f1(bar = foo) { return bar; // returns 1 } function f2(bar = (baz = foo) => baz) { - var fooo = 2; + var foo = 2; return bar(); // returns 1 } function f3(bar = foo, foo = 2) { @@ -49,3 +54,6 @@ function f5(a = a) { function f6(async = async) { return async; } +function f7({ [foo]: bar }) { + let foo = 2; +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols index c38a392c4d8..f9366034aa6 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols @@ -21,8 +21,8 @@ function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at >foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) >baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 20)) - var fooo: number = 2; ->fooo : Symbol(fooo, Decl(parameterInitializersForwardReferencing1_es6.ts, 8, 7)) + var foo: number = 2; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 8, 7)) return bar(); // returns 1 >bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 13)) @@ -65,3 +65,13 @@ function f6 (async = async) { return async >async : Symbol(async, Decl(parameterInitializersForwardReferencing1_es6.ts, 24, 13)) } + +function f7({[foo]: bar}: any[]) { +>f7 : Symbol(f7, Decl(parameterInitializersForwardReferencing1_es6.ts, 26, 1)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) +>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 28, 13)) + + let foo: number = 2; +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 29, 7)) +} + diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types index bd17f482335..16bd49f1cf7 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types @@ -24,8 +24,8 @@ function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at >foo : string >baz : string - var fooo: number = 2; ->fooo : number + var foo: number = 2; +>foo : number >2 : 2 return bar(); // returns 1 @@ -71,3 +71,14 @@ function f6 (async = async) { return async >async : any } + +function f7({[foo]: bar}: any[]) { +>f7 : ({ [foo]: bar }: any[]) => void +>foo : string +>bar : any + + let foo: number = 2; +>foo : number +>2 : 2 +} + diff --git a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts index 8492a053856..640900253bd 100644 --- a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts +++ b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts @@ -24,4 +24,8 @@ function f5 (a = a) { function f6 (async = async) { return async -} \ No newline at end of file +} + +function f7({[foo]: bar}: any[]) { + let foo: number = 2; +} diff --git a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts index dfd6b8d4e1a..55afbbf7c2f 100644 --- a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts +++ b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts @@ -8,7 +8,7 @@ function f1 (bar = foo) { // unexpected compiler error; works at runtime } function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime - var fooo: number = 2; + var foo: number = 2; return bar(); // returns 1 } @@ -26,4 +26,8 @@ function f5 (a = a) { function f6 (async = async) { return async -} \ No newline at end of file +} + +function f7({[foo]: bar}: any[]) { + let foo: number = 2; +} From fb0cd6c0e03c03cfb4041036e21942e8250401ce Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 28 Aug 2018 16:10:36 +0000 Subject: [PATCH 65/77] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 20264 ++++++++-------- 1 file changed, 10132 insertions(+), 10132 deletions(-) diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 7dac9c42ec8..d2461ce0c42 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,10133 +1,10133 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - oder - erforderlich, z. B. "{0}" oder "{1}".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - " sein.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + oder - erforderlich, z. B. "{0}" oder "{1}".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + " sein.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 1b1ca9ebf00e062e1271f2c8e0290a80554e31ce Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 09:41:46 -0700 Subject: [PATCH 66/77] Memoize collecting set of all imported packages (#26263) --- src/compiler/checker.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51eeb0fdb48..01f3b5136f2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31,6 +31,18 @@ namespace ts { } export function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker { + const getPackagesSet: () => Map = memoize(() => { + const set = createMap(); + host.getSourceFiles().forEach(sf => { + if (!sf.resolvedModules) return; + + forEachEntry(sf.resolvedModules, r => { + if (r && r.packageId) set.set(r.packageId.name, true); + }); + }); + return set; + }); + // Cancellation that controls whether or not we can cancel in the middle of type checking. // In general cancelling is *not* safe for the type checker. We might be in the middle of // computing something, and we will leave our internals in an inconsistent state. Callers @@ -2265,8 +2277,7 @@ namespace ts { resolvedFileName)); } function typesPackageExists(packageName: string): boolean { - return host.getSourceFiles().some(sf => !!sf.resolvedModules && !!forEachEntry(sf.resolvedModules, r => - r && r.packageId && r.packageId.name === getTypesPackageName(packageName))); + return getPackagesSet().has(getTypesPackageName(packageName)); } // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, From 1b5de9d16e0232506983c5ea6c0292f661299fec Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 10:25:00 -0700 Subject: [PATCH 67/77] Uncomment tests fixed with #23631 (#26700) --- tests/cases/fourslash/genericFunctionReturnType.ts | 3 +-- tests/cases/fourslash/genericFunctionSignatureHelp3.ts | 9 +++------ tests/cases/fourslash/genericParameterHelp.ts | 3 --- .../fourslash/genericParameterHelpConstructorCalls.ts | 9 +++------ .../fourslash/genericParameterHelpTypeReferences.ts | 2 +- tests/cases/fourslash/staticGenericOverloads1.ts | 7 ++----- 6 files changed, 10 insertions(+), 23 deletions(-) diff --git a/tests/cases/fourslash/genericFunctionReturnType.ts b/tests/cases/fourslash/genericFunctionReturnType.ts index 9cb41a30ffb..35c566e2090 100644 --- a/tests/cases/fourslash/genericFunctionReturnType.ts +++ b/tests/cases/fourslash/genericFunctionReturnType.ts @@ -8,8 +8,7 @@ ////var /*2*/r = foo(/*1*/1, ""); ////var /*4*/r2 = r(/*3*/""); -// TODO: GH##23631 -// verify.signatureHelp({ marker: "1", text: "foo(x: number, y: string): (a: string) => number" }); +verify.signatureHelp({ marker: "1", text: "foo(x: number, y: string): (a: string) => number" }); verify.quickInfoAt("2", "var r: (a: string) => number"); diff --git a/tests/cases/fourslash/genericFunctionSignatureHelp3.ts b/tests/cases/fourslash/genericFunctionSignatureHelp3.ts index cc763f489cc..d2180219c2a 100644 --- a/tests/cases/fourslash/genericFunctionSignatureHelp3.ts +++ b/tests/cases/fourslash/genericFunctionSignatureHelp3.ts @@ -18,17 +18,14 @@ verify.signatureHelp( { marker: "1", text: "foo1(x: number, callback: (y1: {}) => number): void" }, - // TODO: GH#23631 - // { marker: "2", text: "foo2(x: number, callback: (y2: {}) => number): void" }, + { marker: "2", text: "foo2(x: number, callback: (y2: {}) => number): void" }, { marker: "3", text: "callback(y3: {}): number" }, - // TODO: GH#23631 - // { marker: "4", text: "foo4(x: number, callback: (y4: string) => number): void" }, + { marker: "4", text: "foo4(x: number, callback: (y4: string) => number): void" }, { marker: "5", text: "callback(y5: string): number" }, ); goTo.marker('6'); -// TODO: GH#23631 -// verify.signatureHelp({ text: "foo6(x: number, callback: (y6: {}) => number): void" }); +verify.signatureHelp({ text: "foo6(x: number, callback: (y6: {}) => number): void" }); edit.insert('string>(null,null);'); // need to make this line parse so we can get reasonable LS answers to later tests verify.signatureHelp({ marker: "7", text: "foo7(x: number, callback: (y7: {}) => number): void" }); diff --git a/tests/cases/fourslash/genericParameterHelp.ts b/tests/cases/fourslash/genericParameterHelp.ts index 320c159203c..698ace8a4d8 100644 --- a/tests/cases/fourslash/genericParameterHelp.ts +++ b/tests/cases/fourslash/genericParameterHelp.ts @@ -14,8 +14,6 @@ ////testFunction<, ,/*5*/>(null, null, null); verify.signatureHelp( - // TODO: GH#23631 - /* { marker: "1", text: "testFunction(a: T, b: U, c: M): M", @@ -24,7 +22,6 @@ verify.signatureHelp( parameterSpan: "T extends IFoo", }, { marker: "2", parameterName: "U", parameterSpan: "U" }, - */ { marker: "3", parameterName: "a", parameterSpan: "a: any" }, { marker: "4", parameterName: "M", parameterSpan: "M extends IFoo" }, { marker: "5", parameterName: "M", parameterSpan: "M extends IFoo" }, diff --git a/tests/cases/fourslash/genericParameterHelpConstructorCalls.ts b/tests/cases/fourslash/genericParameterHelpConstructorCalls.ts index 73ae1b91755..4c4ca62f99c 100644 --- a/tests/cases/fourslash/genericParameterHelpConstructorCalls.ts +++ b/tests/cases/fourslash/genericParameterHelpConstructorCalls.ts @@ -14,8 +14,6 @@ ////new testClass(null, null, null) verify.signatureHelp( - // TODO: GH#23631 - /* { marker: "constructor1", text: "testClass(a: T, b: U, c: M): testClass", @@ -27,8 +25,7 @@ verify.signatureHelp( parameterName: "U", parameterSpan: "U", }, - */ - { marker: "constructor3", parameterName: "T", parameterSpan: "T extends IFoo" }, - { marker: "constructor4", parameterName: "M", parameterSpan: "M extends IFoo" }, - { marker: "constructor5", parameterName: "U", parameterSpan: "U" }, + { marker: "constructor3", parameterName: "T", parameterSpan: "T extends IFoo" }, + { marker: "constructor4", parameterName: "M", parameterSpan: "M extends IFoo" }, + { marker: "constructor5", parameterName: "U", parameterSpan: "U" }, ); diff --git a/tests/cases/fourslash/genericParameterHelpTypeReferences.ts b/tests/cases/fourslash/genericParameterHelpTypeReferences.ts index 33d3d85d565..5a477d23e56 100644 --- a/tests/cases/fourslash/genericParameterHelpTypeReferences.ts +++ b/tests/cases/fourslash/genericParameterHelpTypeReferences.ts @@ -12,7 +12,7 @@ ////class Bar extends testClass; -// TODO: GH#23631 +// TODO: GH#26699 if (false) { verify.signatureHelp( diff --git a/tests/cases/fourslash/staticGenericOverloads1.ts b/tests/cases/fourslash/staticGenericOverloads1.ts index e67b9df8d2d..7b15e6e2a3e 100644 --- a/tests/cases/fourslash/staticGenericOverloads1.ts +++ b/tests/cases/fourslash/staticGenericOverloads1.ts @@ -13,11 +13,8 @@ verify.signatureHelp({ marker: "", overloadsCount: 2 }); edit.insert('a'); -verify.signatureHelp({ overloadsCount: 2 }); -// TODO: GH#23631 -// verify.signatureHelp({ text: "B(v: A): A" }); +verify.signatureHelp({ overloadsCount: 2, text: "B(v: A): A" }); edit.insert('); A.B('); verify.signatureHelp({ overloadsCount: 2, text: "B(v: A<{}>): A<{}>" }); edit.insert('a'); -// TODO: GH#23631 -// verify.signatureHelp({ text: "B(v: A): A" }); +verify.signatureHelp({ overloadsCount: 2, text: "B(v: A): A" }); From b183418124626b401ea4f7721cee455d6fd92d2f Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 11:06:14 -0700 Subject: [PATCH 68/77] Fix bug: Don't go to *any* constructor signature for jsx element (#26715) --- src/services/goToDefinition.ts | 13 ++++++++++++- .../fourslash/goToDefinitionSignatureAlias.ts | 19 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 973c040a769..02d590bb8b6 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -29,7 +29,7 @@ namespace ts.GoToDefinition { const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); // Don't go to the component constructor definition for a JSX element, just go to the component definition. - if (calledDeclaration && !(isJsxOpeningLikeElement(node.parent) && isConstructorDeclaration(calledDeclaration))) { + if (calledDeclaration && !(isJsxOpeningLikeElement(node.parent) && isConstructorLike(calledDeclaration))) { const sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration); // For a function, if this is the original function definition, return just sigInfo. // If this is the original constructor definition, parent is the class. @@ -319,4 +319,15 @@ namespace ts.GoToDefinition { // Don't go to a function type, go to the value having that type. return tryCast(signature && signature.declaration, (d): d is SignatureDeclaration => isFunctionLike(d) && !isFunctionTypeNode(d)); } + + function isConstructorLike(node: Node): boolean { + switch (node.kind) { + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + return true; + default: + return false; + } + } } diff --git a/tests/cases/fourslash/goToDefinitionSignatureAlias.ts b/tests/cases/fourslash/goToDefinitionSignatureAlias.ts index 909322582eb..4ace3635cc8 100644 --- a/tests/cases/fourslash/goToDefinitionSignatureAlias.ts +++ b/tests/cases/fourslash/goToDefinitionSignatureAlias.ts @@ -21,9 +21,20 @@ ////o.[|/*useM*/m|](); ////class Component { /*componentCtr*/constructor(props: {}) {} } +////type ComponentClass = /*ComponentClass*/new () => Component; +////interface ComponentClass2 { /*ComponentClass2*/new(): Component; } +//// ////class /*MyComponent*/MyComponent extends Component {} -////<[|/*jsxMyComponent*/MyComponent|] /> +////<[|/*jsxMyComponent*/MyComponent|] />; ////new [|/*newMyComponent*/MyComponent|]({}); +//// +////declare const /*MyComponent2*/MyComponent2: ComponentClass; +////<[|/*jsxMyComponent2*/MyComponent2|] />; +////new [|/*newMyComponent2*/MyComponent2|](); +//// +////declare const /*MyComponent3*/MyComponent3: ComponentClass2; +////<[|/*jsxMyComponent3*/MyComponent3|] />; +////new [|/*newMyComponent3*/MyComponent3|](); verify.noErrors(); @@ -38,4 +49,10 @@ verify.goToDefinition({ jsxMyComponent: "MyComponent", newMyComponent: ["MyComponent", "componentCtr"], + + jsxMyComponent2: "MyComponent2", + newMyComponent2: ["MyComponent2", "ComponentClass"], + + jsxMyComponent3: "MyComponent3", + newMyComponent3: ["MyComponent3", "ComponentClass2"], }); From 868cf3e6de627aae3e811bc0bcc40839a9b7af5f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 28 Aug 2018 11:21:35 -0700 Subject: [PATCH 69/77] renames per PR feedback --- src/compiler/tsbuild.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 5fdab168951..f038136e6a4 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -39,7 +39,7 @@ namespace ts { invalidateProject(project: ResolvedConfigFileName, dependencyGraph: DependencyGraph | undefined): void; getNextInvalidatedProject(): ResolvedConfigFileName | undefined; - pendingInvalidatedProjects(): boolean; + hasPendingInvalidatedProjects(): boolean; missingRoots: Map; } @@ -396,20 +396,21 @@ namespace ts { unchangedOutputs: createFileMap(), invalidateProject, getNextInvalidatedProject, - pendingInvalidatedProjects, + hasPendingInvalidatedProjects, missingRoots }; - function invalidateProject(proj: ResolvedConfigFileName, dependancyGraph: DependencyGraph | undefined) { + function invalidateProject(proj: ResolvedConfigFileName, dependencyGraph: DependencyGraph | undefined) { if (!projectPendingBuild.hasKey(proj)) { addProjToQueue(proj); - if (dependancyGraph) { - queueBuildForDownstreamReferences(proj, dependancyGraph); + if (dependencyGraph) { + queueBuildForDownstreamReferences(proj, dependencyGraph); } } } function addProjToQueue(proj: ResolvedConfigFileName) { + Debug.assert(!projectPendingBuild.hasKey(proj)); projectPendingBuild.setValue(proj, true); invalidatedProjectQueue.push(proj); } @@ -426,18 +427,18 @@ namespace ts { } } - function pendingInvalidatedProjects() { + function hasPendingInvalidatedProjects() { return !!projectPendingBuild.getSize(); } // Mark all downstream projects of this one needing to be built "later" - function queueBuildForDownstreamReferences(root: ResolvedConfigFileName, dependancyGraph: DependencyGraph) { - const deps = dependancyGraph.dependencyMap.getReferencesTo(root); + function queueBuildForDownstreamReferences(root: ResolvedConfigFileName, dependencyGraph: DependencyGraph) { + const deps = dependencyGraph.dependencyMap.getReferencesTo(root); for (const ref of deps) { // Can skip circular references if (!projectPendingBuild.hasKey(ref)) { addProjToQueue(ref); - queueBuildForDownstreamReferences(ref, dependancyGraph); + queueBuildForDownstreamReferences(ref, dependencyGraph); } } } @@ -810,7 +811,7 @@ namespace ts { timerToBuildInvalidatedProject = undefined; const buildProject = context.getNextInvalidatedProject(); buildSomeProjects(p => p === buildProject); - if (context.pendingInvalidatedProjects()) { + if (context.hasPendingInvalidatedProjects()) { if (!timerToBuildInvalidatedProject) { scheduleBuildInvalidatedProject(); } From 3931b72118e82884f882b7941cb275f212f3afdd Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 11:43:45 -0700 Subject: [PATCH 70/77] noUnusedLocals: Destructuring assignment is a write (#26365) * noUnusedLocals: Destructuring assignment is a write * Code review * Clarify test --- src/compiler/utilities.ts | 33 ++++++- .../noUnusedLocals_writeOnly.errors.txt | 13 ++- .../reference/noUnusedLocals_writeOnly.js | 25 +++++- .../noUnusedLocals_writeOnly.symbols | 51 +++++++++-- .../reference/noUnusedLocals_writeOnly.types | 87 ++++++++++++++++++- .../compiler/noUnusedLocals_writeOnly.ts | 12 ++- 6 files changed, 206 insertions(+), 15 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 39a298329c7..b808a1f2fd1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2331,6 +2331,13 @@ namespace ts { return node; } + function skipParenthesesUp(node: Node): Node { + while (node.kind === SyntaxKind.ParenthesizedExpression) { + node = node.parent; + } + return node; + } + // a node is delete target iff. it is PropertyAccessExpression/ElementAccessExpression with parentheses skipped export function isDeleteTarget(node: Node): boolean { if (node.kind !== SyntaxKind.PropertyAccessExpression && node.kind !== SyntaxKind.ElementAccessExpression) { @@ -4206,6 +4213,8 @@ namespace ts { if (!parent) return AccessKind.Read; switch (parent.kind) { + case SyntaxKind.ParenthesizedExpression: + return accessKind(parent); case SyntaxKind.PostfixUnaryExpression: case SyntaxKind.PrefixUnaryExpression: const { operator } = parent as PrefixUnaryExpression | PostfixUnaryExpression; @@ -4217,13 +4226,35 @@ namespace ts { : AccessKind.Read; case SyntaxKind.PropertyAccessExpression: return (parent as PropertyAccessExpression).name !== node ? AccessKind.Read : accessKind(parent); + case SyntaxKind.PropertyAssignment: { + const parentAccess = accessKind(parent.parent); + // In `({ x: varname }) = { x: 1 }`, the left `x` is a read, the right `x` is a write. + return node === (parent as PropertyAssignment).name ? reverseAccessKind(parentAccess) : parentAccess; + } + case SyntaxKind.ShorthandPropertyAssignment: + // Assume it's the local variable being accessed, since we don't check public properties for --noUnusedLocals. + return node === (parent as ShorthandPropertyAssignment).objectAssignmentInitializer ? AccessKind.Read : accessKind(parent.parent); + case SyntaxKind.ArrayLiteralExpression: + return accessKind(parent); default: return AccessKind.Read; } function writeOrReadWrite(): AccessKind { // If grandparent is not an ExpressionStatement, this is used as an expression in addition to having a side effect. - return parent.parent && parent.parent.kind === SyntaxKind.ExpressionStatement ? AccessKind.Write : AccessKind.ReadWrite; + return parent.parent && skipParenthesesUp(parent.parent).kind === SyntaxKind.ExpressionStatement ? AccessKind.Write : AccessKind.ReadWrite; + } + } + function reverseAccessKind(a: AccessKind): AccessKind { + switch (a) { + case AccessKind.Read: + return AccessKind.Write; + case AccessKind.Write: + return AccessKind.Read; + case AccessKind.ReadWrite: + return AccessKind.ReadWrite; + default: + return Debug.assertNever(a); } } diff --git a/tests/baselines/reference/noUnusedLocals_writeOnly.errors.txt b/tests/baselines/reference/noUnusedLocals_writeOnly.errors.txt index 09ebea0f654..347e181d946 100644 --- a/tests/baselines/reference/noUnusedLocals_writeOnly.errors.txt +++ b/tests/baselines/reference/noUnusedLocals_writeOnly.errors.txt @@ -1,14 +1,22 @@ tests/cases/compiler/noUnusedLocals_writeOnly.ts(1,12): error TS6133: 'x' is declared but its value is never read. -tests/cases/compiler/noUnusedLocals_writeOnly.ts(10,9): error TS6133: 'z' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_writeOnly.ts(18,9): error TS6133: 'z' is declared but its value is never read. ==== tests/cases/compiler/noUnusedLocals_writeOnly.ts (2 errors) ==== - function f(x = 0) { + function f(x = 0, b = false) { ~ !!! error TS6133: 'x' is declared but its value is never read. + // None of these statements read from 'x', so it will be marked unused. x = 1; x++; x /= 2; + ([x] = [1]); + ({ x } = { x: 1 }); + ({ x: x } = { x: 1 }); + ({ a: [{ b: x }] } = { a: [{ b: 1 }] }); + ({ x = 2 } = { x: b ? 1 : undefined }); + let used = 1; + ({ x = used } = { x: b ? 1 : undefined }); let y = 0; // This is a write access to y, but not a write-*only* access. @@ -19,4 +27,5 @@ tests/cases/compiler/noUnusedLocals_writeOnly.ts(10,9): error TS6133: 'z' is dec !!! error TS6133: 'z' is declared but its value is never read. f(z = 1); // This effectively doesn't use `z`, values just pass through it. } + function f2(_: ReadonlyArray): void {} \ No newline at end of file diff --git a/tests/baselines/reference/noUnusedLocals_writeOnly.js b/tests/baselines/reference/noUnusedLocals_writeOnly.js index bc007793042..55a927bfc2b 100644 --- a/tests/baselines/reference/noUnusedLocals_writeOnly.js +++ b/tests/baselines/reference/noUnusedLocals_writeOnly.js @@ -1,8 +1,16 @@ //// [noUnusedLocals_writeOnly.ts] -function f(x = 0) { +function f(x = 0, b = false) { + // None of these statements read from 'x', so it will be marked unused. x = 1; x++; x /= 2; + ([x] = [1]); + ({ x } = { x: 1 }); + ({ x: x } = { x: 1 }); + ({ a: [{ b: x }] } = { a: [{ b: 1 }] }); + ({ x = 2 } = { x: b ? 1 : undefined }); + let used = 1; + ({ x = used } = { x: b ? 1 : undefined }); let y = 0; // This is a write access to y, but not a write-*only* access. @@ -11,17 +19,30 @@ function f(x = 0) { let z = 0; f(z = 1); // This effectively doesn't use `z`, values just pass through it. } +function f2(_: ReadonlyArray): void {} //// [noUnusedLocals_writeOnly.js] -function f(x) { +"use strict"; +function f(x, b) { if (x === void 0) { x = 0; } + if (b === void 0) { b = false; } + var _a, _b; + // None of these statements read from 'x', so it will be marked unused. x = 1; x++; x /= 2; + (x = [1][0]); + (x = { x: 1 }.x); + (x = { x: 1 }.x); + (x = { a: [{ b: 1 }] }.a[0].b); + (_a = { x: b ? 1 : undefined }.x, x = _a === void 0 ? 2 : _a); + var used = 1; + (_b = { x: b ? 1 : undefined }.x, x = _b === void 0 ? used : _b); var y = 0; // This is a write access to y, but not a write-*only* access. f(y++); var z = 0; f(z = 1); // This effectively doesn't use `z`, values just pass through it. } +function f2(_) { } diff --git a/tests/baselines/reference/noUnusedLocals_writeOnly.symbols b/tests/baselines/reference/noUnusedLocals_writeOnly.symbols index afb13f9aa2c..a794291cadd 100644 --- a/tests/baselines/reference/noUnusedLocals_writeOnly.symbols +++ b/tests/baselines/reference/noUnusedLocals_writeOnly.symbols @@ -1,8 +1,10 @@ === tests/cases/compiler/noUnusedLocals_writeOnly.ts === -function f(x = 0) { +function f(x = 0, b = false) { >f : Symbol(f, Decl(noUnusedLocals_writeOnly.ts, 0, 0)) >x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11)) +>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 0, 17)) + // None of these statements read from 'x', so it will be marked unused. x = 1; >x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11)) @@ -12,19 +14,58 @@ function f(x = 0) { x /= 2; >x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11)) + ([x] = [1]); +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11)) + + ({ x } = { x: 1 }); +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 6, 6)) +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 6, 14)) + + ({ x: x } = { x: 1 }); +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 7, 6)) +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11)) +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 7, 17)) + + ({ a: [{ b: x }] } = { a: [{ b: 1 }] }); +>a : Symbol(a, Decl(noUnusedLocals_writeOnly.ts, 8, 6)) +>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 8, 12)) +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 0, 11)) +>a : Symbol(a, Decl(noUnusedLocals_writeOnly.ts, 8, 26)) +>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 8, 32)) + + ({ x = 2 } = { x: b ? 1 : undefined }); +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 9, 6)) +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 9, 18)) +>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 0, 17)) +>undefined : Symbol(undefined) + + let used = 1; +>used : Symbol(used, Decl(noUnusedLocals_writeOnly.ts, 10, 7)) + + ({ x = used } = { x: b ? 1 : undefined }); +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 11, 6)) +>used : Symbol(used, Decl(noUnusedLocals_writeOnly.ts, 10, 7)) +>x : Symbol(x, Decl(noUnusedLocals_writeOnly.ts, 11, 21)) +>b : Symbol(b, Decl(noUnusedLocals_writeOnly.ts, 0, 17)) +>undefined : Symbol(undefined) + let y = 0; ->y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 5, 7)) +>y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 13, 7)) // This is a write access to y, but not a write-*only* access. f(y++); >f : Symbol(f, Decl(noUnusedLocals_writeOnly.ts, 0, 0)) ->y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 5, 7)) +>y : Symbol(y, Decl(noUnusedLocals_writeOnly.ts, 13, 7)) let z = 0; ->z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 9, 7)) +>z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 17, 7)) f(z = 1); // This effectively doesn't use `z`, values just pass through it. >f : Symbol(f, Decl(noUnusedLocals_writeOnly.ts, 0, 0)) ->z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 9, 7)) +>z : Symbol(z, Decl(noUnusedLocals_writeOnly.ts, 17, 7)) } +function f2(_: ReadonlyArray): void {} +>f2 : Symbol(f2, Decl(noUnusedLocals_writeOnly.ts, 19, 1)) +>_ : Symbol(_, Decl(noUnusedLocals_writeOnly.ts, 20, 12)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) diff --git a/tests/baselines/reference/noUnusedLocals_writeOnly.types b/tests/baselines/reference/noUnusedLocals_writeOnly.types index 4b90d7b13e7..43a393a1edd 100644 --- a/tests/baselines/reference/noUnusedLocals_writeOnly.types +++ b/tests/baselines/reference/noUnusedLocals_writeOnly.types @@ -1,9 +1,12 @@ === tests/cases/compiler/noUnusedLocals_writeOnly.ts === -function f(x = 0) { ->f : (x?: number) => void +function f(x = 0, b = false) { +>f : (x?: number, b?: boolean) => void >x : number >0 : 0 +>b : boolean +>false : false + // None of these statements read from 'x', so it will be marked unused. x = 1; >x = 1 : 1 >x : number @@ -18,6 +21,79 @@ function f(x = 0) { >x : number >2 : 2 + ([x] = [1]); +>([x] = [1]) : [number] +>[x] = [1] : [number] +>[x] : [number] +>x : number +>[1] : [number] +>1 : 1 + + ({ x } = { x: 1 }); +>({ x } = { x: 1 }) : { x: number; } +>{ x } = { x: 1 } : { x: number; } +>{ x } : { x: number; } +>x : number +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 + + ({ x: x } = { x: 1 }); +>({ x: x } = { x: 1 }) : { x: number; } +>{ x: x } = { x: 1 } : { x: number; } +>{ x: x } : { x: number; } +>x : number +>x : number +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 + + ({ a: [{ b: x }] } = { a: [{ b: 1 }] }); +>({ a: [{ b: x }] } = { a: [{ b: 1 }] }) : { a: [{ b: number; }]; } +>{ a: [{ b: x }] } = { a: [{ b: 1 }] } : { a: [{ b: number; }]; } +>{ a: [{ b: x }] } : { a: [{ b: number; }]; } +>a : [{ b: number; }] +>[{ b: x }] : [{ b: number; }] +>{ b: x } : { b: number; } +>b : number +>x : number +>{ a: [{ b: 1 }] } : { a: [{ b: number; }]; } +>a : [{ b: number; }] +>[{ b: 1 }] : [{ b: number; }] +>{ b: 1 } : { b: number; } +>b : number +>1 : 1 + + ({ x = 2 } = { x: b ? 1 : undefined }); +>({ x = 2 } = { x: b ? 1 : undefined }) : { x?: number | undefined; } +>{ x = 2 } = { x: b ? 1 : undefined } : { x?: number | undefined; } +>{ x = 2 } : { x?: number; } +>x : number +>2 : 2 +>{ x: b ? 1 : undefined } : { x?: number | undefined; } +>x : number | undefined +>b ? 1 : undefined : 1 | undefined +>b : boolean +>1 : 1 +>undefined : undefined + + let used = 1; +>used : number +>1 : 1 + + ({ x = used } = { x: b ? 1 : undefined }); +>({ x = used } = { x: b ? 1 : undefined }) : { x?: number | undefined; } +>{ x = used } = { x: b ? 1 : undefined } : { x?: number | undefined; } +>{ x = used } : { x?: number; } +>x : number +>used : number +>{ x: b ? 1 : undefined } : { x?: number | undefined; } +>x : number | undefined +>b ? 1 : undefined : 1 | undefined +>b : boolean +>1 : 1 +>undefined : undefined + let y = 0; >y : number >0 : 0 @@ -25,7 +101,7 @@ function f(x = 0) { // This is a write access to y, but not a write-*only* access. f(y++); >f(y++) : void ->f : (x?: number) => void +>f : (x?: number, b?: boolean) => void >y++ : number >y : number @@ -35,9 +111,12 @@ function f(x = 0) { f(z = 1); // This effectively doesn't use `z`, values just pass through it. >f(z = 1) : void ->f : (x?: number) => void +>f : (x?: number, b?: boolean) => void >z = 1 : 1 >z : number >1 : 1 } +function f2(_: ReadonlyArray): void {} +>f2 : (_: ReadonlyArray) => void +>_ : ReadonlyArray diff --git a/tests/cases/compiler/noUnusedLocals_writeOnly.ts b/tests/cases/compiler/noUnusedLocals_writeOnly.ts index ca1df869915..8d2de0d517c 100644 --- a/tests/cases/compiler/noUnusedLocals_writeOnly.ts +++ b/tests/cases/compiler/noUnusedLocals_writeOnly.ts @@ -1,10 +1,19 @@ +// @strict: true // @noUnusedLocals: true // @noUnusedParameters: true -function f(x = 0) { +function f(x = 0, b = false) { + // None of these statements read from 'x', so it will be marked unused. x = 1; x++; x /= 2; + ([x] = [1]); + ({ x } = { x: 1 }); + ({ x: x } = { x: 1 }); + ({ a: [{ b: x }] } = { a: [{ b: 1 }] }); + ({ x = 2 } = { x: b ? 1 : undefined }); + let used = 1; + ({ x = used } = { x: b ? 1 : undefined }); let y = 0; // This is a write access to y, but not a write-*only* access. @@ -13,3 +22,4 @@ function f(x = 0) { let z = 0; f(z = 1); // This effectively doesn't use `z`, values just pass through it. } +function f2(_: ReadonlyArray): void {} From 96e61407c5e399f0dbe94c843f31c3313d98d780 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 28 Aug 2018 11:13:02 -0700 Subject: [PATCH 71/77] Add option --lazyConfiguredProjectsFromExternalProject to enable lazy load of configured projects referenced by external project Fixes #26696 --- src/server/editorServices.ts | 17 +- src/server/session.ts | 2 + .../unittests/tsserverProjectSystem.ts | 511 ++++++++++-------- src/tsserver/server.ts | 2 + .../reference/api/tsserverlibrary.d.ts | 3 + 5 files changed, 306 insertions(+), 229 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 117887d7611..c506c656de7 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -323,6 +323,7 @@ namespace ts.server { cancellationToken: HostCancellationToken; useSingleInferredProject: boolean; useInferredProjectPerProjectRoot: boolean; + lazyConfiguredProjectsFromExternalProject?: boolean; typingsInstaller: ITypingsInstaller; eventHandler?: ProjectServiceEventHandler; suppressDiagnosticEvents?: boolean; @@ -440,6 +441,7 @@ namespace ts.server { public readonly cancellationToken: HostCancellationToken; public readonly useSingleInferredProject: boolean; public readonly useInferredProjectPerProjectRoot: boolean; + private readonly lazyConfiguredProjectsFromExternalProject?: boolean; public readonly typingsInstaller: ITypingsInstaller; private readonly globalCacheLocationDirectoryPath: Path | undefined; public readonly throttleWaitMilliseconds?: number; @@ -465,6 +467,7 @@ namespace ts.server { this.cancellationToken = opts.cancellationToken; this.useSingleInferredProject = opts.useSingleInferredProject; this.useInferredProjectPerProjectRoot = opts.useInferredProjectPerProjectRoot; + this.lazyConfiguredProjectsFromExternalProject = opts.lazyConfiguredProjectsFromExternalProject; this.typingsInstaller = opts.typingsInstaller || nullTypingsInstaller; this.throttleWaitMilliseconds = opts.throttleWaitMilliseconds; this.eventHandler = opts.eventHandler; @@ -1561,6 +1564,13 @@ namespace ts.server { return project; } + /* @internal */ + private createLoadAndUpdateConfiguredProject(configFileName: NormalizedPath) { + const project = this.createAndLoadConfiguredProject(configFileName); + project.updateGraph(); + return project; + } + /** * Read the config file of the project, and update the project root file names. */ @@ -2192,8 +2202,7 @@ namespace ts.server { if (configFileName) { project = this.findConfiguredProjectByProjectName(configFileName); if (!project) { - project = this.createAndLoadConfiguredProject(configFileName); - project.updateGraph(); + project = this.createLoadAndUpdateConfiguredProject(configFileName); // Send the event only if the project got created as part of this open request and info is part of the project if (info.isOrphan()) { // Since the file isnt part of configured project, do not send config file info @@ -2633,7 +2642,9 @@ namespace ts.server { let project = this.findConfiguredProjectByProjectName(tsconfigFile); if (!project) { // errors are stored in the project, do not need to update the graph - project = this.createConfiguredProjectWithDelayLoad(tsconfigFile); + project = this.lazyConfiguredProjectsFromExternalProject ? + this.createConfiguredProjectWithDelayLoad(tsconfigFile) : + this.createLoadAndUpdateConfiguredProject(tsconfigFile); } if (project && !contains(exisingConfigFiles, tsconfigFile)) { // keep project alive even if no documents are opened - its lifetime is bound to the lifetime of containing external project diff --git a/src/server/session.ts b/src/server/session.ts index 8d2fbe9e190..69328b4c73b 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -465,6 +465,7 @@ namespace ts.server { cancellationToken: ServerCancellationToken; useSingleInferredProject: boolean; useInferredProjectPerProjectRoot: boolean; + lazyConfiguredProjectsFromExternalProject?: boolean; typingsInstaller: ITypingsInstaller; byteLength: (buf: string, encoding?: string) => number; hrtime: (start?: number[]) => number[]; @@ -536,6 +537,7 @@ namespace ts.server { cancellationToken: this.cancellationToken, useSingleInferredProject: opts.useSingleInferredProject, useInferredProjectPerProjectRoot: opts.useInferredProjectPerProjectRoot, + lazyConfiguredProjectsFromExternalProject: opts.lazyConfiguredProjectsFromExternalProject, typingsInstaller: this.typingsInstaller, throttleWaitMilliseconds, eventHandler: this.eventHandler, diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index 589668538c7..7ef838fd6ff 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -642,37 +642,53 @@ namespace ts.projectSystem { checkWatchedDirectories(host, [combinePaths(getDirectoryPath(appFile.path), nodeModulesAtTypes)], /*recursive*/ true); }); - it("can handle tsconfig file name with difference casing", () => { - const f1 = { - path: "/a/b/app.ts", - content: "let x = 1" - }; - const config = { - path: "/a/b/tsconfig.json", - content: JSON.stringify({ - include: [] - }) - }; + describe("can handle tsconfig file name with difference casing", () => { + function verifyConfigFileCasing(lazyConfiguredProjectsFromExternalProject: boolean) { + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1" + }; + const config = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({ + include: [] + }) + }; - const host = createServerHost([f1, config], { useCaseSensitiveFileNames: false }); - const service = createProjectService(host); - const upperCaseConfigFilePath = combinePaths(getDirectoryPath(config.path).toUpperCase(), getBaseFileName(config.path)); - service.openExternalProject({ - projectFileName: "/a/b/project.csproj", - rootFiles: toExternalFiles([f1.path, upperCaseConfigFilePath]), - options: {} + const host = createServerHost([f1, config], { useCaseSensitiveFileNames: false }); + const service = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); + const upperCaseConfigFilePath = combinePaths(getDirectoryPath(config.path).toUpperCase(), getBaseFileName(config.path)); + service.openExternalProject({ + projectFileName: "/a/b/project.csproj", + rootFiles: toExternalFiles([f1.path, upperCaseConfigFilePath]), + options: {} + }); + service.checkNumberOfProjects({ configuredProjects: 1 }); + const project = service.configuredProjects.get(config.path)!; + if (lazyConfiguredProjectsFromExternalProject) { + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded + checkProjectActualFiles(project, emptyArray); + } + else { + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project pending to be reloaded + checkProjectActualFiles(project, [upperCaseConfigFilePath]); + } + + service.openClientFile(f1.path); + service.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 }); + + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project is updated + checkProjectActualFiles(project, [upperCaseConfigFilePath]); + checkProjectActualFiles(service.inferredProjects[0], [f1.path]); + } + + it("when lazyConfiguredProjectsFromExternalProject not set", () => { + verifyConfigFileCasing(/*lazyConfiguredProjectsFromExternalProject*/ false); }); - service.checkNumberOfProjects({ configuredProjects: 1 }); - const project = service.configuredProjects.get(config.path)!; - assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded - checkProjectActualFiles(project, emptyArray); - service.openClientFile(f1.path); - service.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 }); - - assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project is updated - checkProjectActualFiles(project, [upperCaseConfigFilePath]); - checkProjectActualFiles(service.inferredProjects[0], [f1.path]); + it("when lazyConfiguredProjectsFromExternalProject is set", () => { + verifyConfigFileCasing(/*lazyConfiguredProjectsFromExternalProject*/ true); + }); }); it("create configured project without file list", () => { @@ -2950,45 +2966,55 @@ namespace ts.projectSystem { assert.equal(navbar[0].spans[0].length, f1.content.length); }); - it("deleting config file opened from the external project works", () => { - const site = { - path: "/user/someuser/project/js/site.js", - content: "" - }; - const configFile = { - path: "/user/someuser/project/tsconfig.json", - content: "{}" - }; - const projectFileName = "/user/someuser/project/WebApplication6.csproj"; - const host = createServerHost([libFile, site, configFile]); - const projectService = createProjectService(host); + describe("deleting config file opened from the external project works", () => { + function verifyDeletingConfigFile(lazyConfiguredProjectsFromExternalProject: boolean) { + const site = { + path: "/user/someuser/project/js/site.js", + content: "" + }; + const configFile = { + path: "/user/someuser/project/tsconfig.json", + content: "{}" + }; + const projectFileName = "/user/someuser/project/WebApplication6.csproj"; + const host = createServerHost([libFile, site, configFile]); + const projectService = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); - const externalProject: protocol.ExternalProject = { - projectFileName, - rootFiles: [toExternalFile(site.path), toExternalFile(configFile.path)], - options: { allowJs: false }, - typeAcquisition: { include: [] } - }; + const externalProject: protocol.ExternalProject = { + projectFileName, + rootFiles: [toExternalFile(site.path), toExternalFile(configFile.path)], + options: { allowJs: false }, + typeAcquisition: { include: [] } + }; - projectService.openExternalProjects([externalProject]); + projectService.openExternalProjects([externalProject]); - let knownProjects = projectService.synchronizeProjectList([]); - checkNumberOfProjects(projectService, { configuredProjects: 1, externalProjects: 0, inferredProjects: 0 }); + let knownProjects = projectService.synchronizeProjectList([]); + checkNumberOfProjects(projectService, { configuredProjects: 1, externalProjects: 0, inferredProjects: 0 }); - const configProject = configuredProjectAt(projectService, 0); - checkProjectActualFiles(configProject, []); // Since no files opened from this project, its not loaded + const configProject = configuredProjectAt(projectService, 0); + checkProjectActualFiles(configProject, lazyConfiguredProjectsFromExternalProject ? + emptyArray : // Since no files opened from this project, its not loaded + [libFile.path, configFile.path]); - host.reloadFS([libFile, site]); - host.checkTimeoutQueueLengthAndRun(1); + host.reloadFS([libFile, site]); + host.checkTimeoutQueueLengthAndRun(1); - knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info!)); // TODO: GH#18217 GH#20039 - checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 0, inferredProjects: 0 }); + knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info!)); // TODO: GH#18217 GH#20039 + checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 0, inferredProjects: 0 }); - externalProject.rootFiles.length = 1; - projectService.openExternalProjects([externalProject]); + externalProject.rootFiles.length = 1; + projectService.openExternalProjects([externalProject]); - checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 1, inferredProjects: 0 }); - checkProjectActualFiles(projectService.externalProjects[0], [site.path, libFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 1, inferredProjects: 0 }); + checkProjectActualFiles(projectService.externalProjects[0], [site.path, libFile.path]); + } + it("when lazyConfiguredProjectsFromExternalProject not set", () => { + verifyDeletingConfigFile(/*lazyConfiguredProjectsFromExternalProject*/ false); + }); + it("when lazyConfiguredProjectsFromExternalProject is set", () => { + verifyDeletingConfigFile(/*lazyConfiguredProjectsFromExternalProject*/ true); + }); }); it("Getting errors from closed script info does not throw exception (because of getting project from orphan script info)", () => { @@ -3298,49 +3324,60 @@ namespace ts.projectSystem { }); - it("includes deferred files in the project context", () => { - const file1 = { - path: "/a.deferred", - content: "const a = 1;" - }; - // Deferred extensions should not affect JS files. - const file2 = { - path: "/b.js", - content: "const b = 1;" - }; - const tsconfig = { - path: "/tsconfig.json", - content: "" - }; + describe("includes deferred files in the project context", () => { + function verifyDeferredContext(lazyConfiguredProjectsFromExternalProject: boolean) { + const file1 = { + path: "/a.deferred", + content: "const a = 1;" + }; + // Deferred extensions should not affect JS files. + const file2 = { + path: "/b.js", + content: "const b = 1;" + }; + const tsconfig = { + path: "/tsconfig.json", + content: "" + }; - const host = createServerHost([file1, file2, tsconfig]); - const session = createSession(host); - const projectService = session.getProjectService(); + const host = createServerHost([file1, file2, tsconfig]); + const session = createSession(host, { lazyConfiguredProjectsFromExternalProject }); + const projectService = session.getProjectService(); - // Configure the deferred extension. - const extraFileExtensions = [{ extension: ".deferred", scriptKind: ScriptKind.Deferred, isMixedContent: true }]; - const configureHostRequest = makeSessionRequest(CommandNames.Configure, { extraFileExtensions }); - session.executeCommand(configureHostRequest); + // Configure the deferred extension. + const extraFileExtensions = [{ extension: ".deferred", scriptKind: ScriptKind.Deferred, isMixedContent: true }]; + const configureHostRequest = makeSessionRequest(CommandNames.Configure, { extraFileExtensions }); + session.executeCommand(configureHostRequest); - // Open external project - const projectName = "/proj1"; - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([file1.path, file2.path, tsconfig.path]), - options: {} + // Open external project + const projectName = "/proj1"; + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([file1.path, file2.path, tsconfig.path]), + options: {} + }); + + // Assert + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + + const configuredProject = configuredProjectAt(projectService, 0); + if (lazyConfiguredProjectsFromExternalProject) { + // configured project is just created and not yet loaded + checkProjectActualFiles(configuredProject, emptyArray); + projectService.ensureInferredProjectsUpToDate_TestOnly(); + } + checkProjectActualFiles(configuredProject, [file1.path, tsconfig.path]); + + // Allow allowNonTsExtensions will be set to true for deferred extensions. + assert.isTrue(configuredProject.getCompilerOptions().allowNonTsExtensions); + } + + it("when lazyConfiguredProjectsFromExternalProject not set", () => { + verifyDeferredContext(/*lazyConfiguredProjectsFromExternalProject*/ false); + }); + it("when lazyConfiguredProjectsFromExternalProject is set", () => { + verifyDeferredContext(/*lazyConfiguredProjectsFromExternalProject*/ true); }); - - // Assert - checkNumberOfProjects(projectService, { configuredProjects: 1 }); - - const configuredProject = configuredProjectAt(projectService, 0); - // configured project is just created and not yet loaded - checkProjectActualFiles(configuredProject, emptyArray); - projectService.ensureInferredProjectsUpToDate_TestOnly(); - checkProjectActualFiles(configuredProject, [file1.path, tsconfig.path]); - - // Allow allowNonTsExtensions will be set to true for deferred extensions. - assert.isTrue(configuredProject.getCompilerOptions().allowNonTsExtensions); }); it("Orphan source files are handled correctly on watch trigger", () => { @@ -3943,143 +3980,165 @@ namespace ts.projectSystem { }); describe("tsserverProjectSystem external projects", () => { - it("correctly handling add/remove tsconfig - 1", () => { - const f1 = { - path: "/a/b/app.ts", - content: "let x = 1;" - }; - const f2 = { - path: "/a/b/lib.ts", - content: "" - }; - const tsconfig = { - path: "/a/b/tsconfig.json", - content: "" - }; - const host = createServerHost([f1, f2]); - const projectService = createProjectService(host); + describe("correctly handling add/remove tsconfig - 1", () => { + function verifyAddRemoveConfig(lazyConfiguredProjectsFromExternalProject: boolean) { + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1;" + }; + const f2 = { + path: "/a/b/lib.ts", + content: "" + }; + const tsconfig = { + path: "/a/b/tsconfig.json", + content: "" + }; + const host = createServerHost([f1, f2]); + const projectService = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); - // open external project - const projectName = "/a/b/proj1"; - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path, f2.path]), - options: {} + // open external project + const projectName = "/a/b/proj1"; + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path, f2.path]), + options: {} + }); + projectService.openClientFile(f1.path); + projectService.checkNumberOfProjects({ externalProjects: 1 }); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); + + // rename lib.ts to tsconfig.json + host.reloadFS([f1, tsconfig]); + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path, tsconfig.path]), + options: {} + }); + projectService.checkNumberOfProjects({ configuredProjects: 1 }); + if (lazyConfiguredProjectsFromExternalProject) { + checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed + projectService.ensureInferredProjectsUpToDate_TestOnly(); + } + checkProjectActualFiles(configuredProjectAt(projectService, 0), [f1.path, tsconfig.path]); + + // rename tsconfig.json back to lib.ts + host.reloadFS([f1, f2]); + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path, f2.path]), + options: {} + }); + + projectService.checkNumberOfProjects({ externalProjects: 1 }); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); + } + it("when lazyConfiguredProjectsFromExternalProject not set", () => { + verifyAddRemoveConfig(/*lazyConfiguredProjectsFromExternalProject*/ false); }); - projectService.openClientFile(f1.path); - projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); - - // rename lib.ts to tsconfig.json - host.reloadFS([f1, tsconfig]); - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path, tsconfig.path]), - options: {} + it("when lazyConfiguredProjectsFromExternalProject is set", () => { + verifyAddRemoveConfig(/*lazyConfiguredProjectsFromExternalProject*/ true); }); - projectService.checkNumberOfProjects({ configuredProjects: 1 }); - checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed - projectService.ensureInferredProjectsUpToDate_TestOnly(); - checkProjectActualFiles(configuredProjectAt(projectService, 0), [f1.path, tsconfig.path]); - - // rename tsconfig.json back to lib.ts - host.reloadFS([f1, f2]); - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path, f2.path]), - options: {} - }); - - projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); }); + describe("correctly handling add/remove tsconfig - 2", () => { + function verifyAddRemoveConfig(lazyConfiguredProjectsFromExternalProject: boolean) { + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1;" + }; + const cLib = { + path: "/a/b/c/lib.ts", + content: "" + }; + const cTsconfig = { + path: "/a/b/c/tsconfig.json", + content: "{}" + }; + const dLib = { + path: "/a/b/d/lib.ts", + content: "" + }; + const dTsconfig = { + path: "/a/b/d/tsconfig.json", + content: "{}" + }; + const host = createServerHost([f1, cLib, cTsconfig, dLib, dTsconfig]); + const projectService = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); - it("correctly handling add/remove tsconfig - 2", () => { - const f1 = { - path: "/a/b/app.ts", - content: "let x = 1;" - }; - const cLib = { - path: "/a/b/c/lib.ts", - content: "" - }; - const cTsconfig = { - path: "/a/b/c/tsconfig.json", - content: "{}" - }; - const dLib = { - path: "/a/b/d/lib.ts", - content: "" - }; - const dTsconfig = { - path: "/a/b/d/tsconfig.json", - content: "{}" - }; - const host = createServerHost([f1, cLib, cTsconfig, dLib, dTsconfig]); - const projectService = createProjectService(host); + // open external project + const projectName = "/a/b/proj1"; + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path]), + options: {} + }); - // open external project - const projectName = "/a/b/proj1"; - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path]), - options: {} + projectService.checkNumberOfProjects({ externalProjects: 1 }); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); + + // add two config file as root files + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), + options: {} + }); + projectService.checkNumberOfProjects({ configuredProjects: 2 }); + if (lazyConfiguredProjectsFromExternalProject) { + checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed + checkProjectActualFiles(configuredProjectAt(projectService, 1), emptyArray); // Configured project created but not loaded till actually needed + projectService.ensureInferredProjectsUpToDate_TestOnly(); + } + checkProjectActualFiles(configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); + + // remove one config file + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path, dTsconfig.path]), + options: {} + }); + + projectService.checkNumberOfProjects({ configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [dLib.path, dTsconfig.path]); + + // remove second config file + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path]), + options: {} + }); + + projectService.checkNumberOfProjects({ externalProjects: 1 }); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); + + // open two config files + // add two config file as root files + projectService.openExternalProject({ + projectFileName: projectName, + rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), + options: {} + }); + projectService.checkNumberOfProjects({ configuredProjects: 2 }); + if (lazyConfiguredProjectsFromExternalProject) { + checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed + checkProjectActualFiles(configuredProjectAt(projectService, 1), emptyArray); // Configured project created but not loaded till actually needed + projectService.ensureInferredProjectsUpToDate_TestOnly(); + } + checkProjectActualFiles(configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); + + // close all projects - no projects should be opened + projectService.closeExternalProject(projectName); + projectService.checkNumberOfProjects({}); + } + + it("when lazyConfiguredProjectsFromExternalProject not set", () => { + verifyAddRemoveConfig(/*lazyConfiguredProjectsFromExternalProject*/ false); }); - - projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); - - // add two config file as root files - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), - options: {} + it("when lazyConfiguredProjectsFromExternalProject is set", () => { + verifyAddRemoveConfig(/*lazyConfiguredProjectsFromExternalProject*/ true); }); - projectService.checkNumberOfProjects({ configuredProjects: 2 }); - checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed - checkProjectActualFiles(configuredProjectAt(projectService, 1), emptyArray); // Configured project created but not loaded till actually needed - projectService.ensureInferredProjectsUpToDate_TestOnly(); - checkProjectActualFiles(configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); - checkProjectActualFiles(configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); - - // remove one config file - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path, dTsconfig.path]), - options: {} - }); - - projectService.checkNumberOfProjects({ configuredProjects: 1 }); - checkProjectActualFiles(configuredProjectAt(projectService, 0), [dLib.path, dTsconfig.path]); - - // remove second config file - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path]), - options: {} - }); - - projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); - - // open two config files - // add two config file as root files - projectService.openExternalProject({ - projectFileName: projectName, - rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), - options: {} - }); - projectService.checkNumberOfProjects({ configuredProjects: 2 }); - checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed - checkProjectActualFiles(configuredProjectAt(projectService, 1), emptyArray); // Configured project created but not loaded till actually needed - projectService.ensureInferredProjectsUpToDate_TestOnly(); - checkProjectActualFiles(configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); - checkProjectActualFiles(configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); - - // close all projects - no projects should be opened - projectService.closeExternalProject(projectName); - projectService.checkNumberOfProjects({}); }); it("correctly handles changes in lib section of config file", () => { diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 3e5986e9408..6b8a146d8f3 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -499,6 +499,7 @@ namespace ts.server { cancellationToken, useSingleInferredProject, useInferredProjectPerProjectRoot, + lazyConfiguredProjectsFromExternalProject, typingsInstaller: typingsInstaller || nullTypingsInstaller, byteLength: Buffer.byteLength, hrtime: process.hrtime, @@ -937,6 +938,7 @@ namespace ts.server { const useSingleInferredProject = hasArgument("--useSingleInferredProject"); const useInferredProjectPerProjectRoot = hasArgument("--useInferredProjectPerProjectRoot"); + const lazyConfiguredProjectsFromExternalProject = hasArgument("--lazyConfiguredProjectsFromExternalProject"); const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); const suppressDiagnosticEvents = hasArgument("--suppressDiagnosticEvents"); const syntaxOnly = hasArgument("--syntaxOnly"); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 584557e8b0f..3194a2b79bb 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -8325,6 +8325,7 @@ declare namespace ts.server { cancellationToken: HostCancellationToken; useSingleInferredProject: boolean; useInferredProjectPerProjectRoot: boolean; + lazyConfiguredProjectsFromExternalProject?: boolean; typingsInstaller: ITypingsInstaller; eventHandler?: ProjectServiceEventHandler; suppressDiagnosticEvents?: boolean; @@ -8397,6 +8398,7 @@ declare namespace ts.server { readonly cancellationToken: HostCancellationToken; readonly useSingleInferredProject: boolean; readonly useInferredProjectPerProjectRoot: boolean; + private readonly lazyConfiguredProjectsFromExternalProject?; readonly typingsInstaller: ITypingsInstaller; private readonly globalCacheLocationDirectoryPath; readonly throttleWaitMilliseconds?: number; @@ -8598,6 +8600,7 @@ declare namespace ts.server { cancellationToken: ServerCancellationToken; useSingleInferredProject: boolean; useInferredProjectPerProjectRoot: boolean; + lazyConfiguredProjectsFromExternalProject?: boolean; typingsInstaller: ITypingsInstaller; byteLength: (buf: string, encoding?: string) => number; hrtime: (start?: number[]) => number[]; From b94061c5871195642965c2df9fa341758572098f Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 13:03:24 -0700 Subject: [PATCH 72/77] getEditsForFileRename: Avoid changing import specifier ending (#26177) * getEditsForFileRename: Avoid changing import specifier ending * Support .json and .jsx extensions * Restore typeRoots tests * Fix json test * When --jsx preserve is set, import ".tsx" file with ".jsx" extension * Support ending preference in UserPreferences --- src/compiler/checker.ts | 17 +- src/compiler/moduleSpecifiers.ts | 198 +++++++++--------- src/compiler/types.ts | 15 +- src/compiler/utilities.ts | 5 + src/services/getEditsForFileRename.ts | 9 +- src/services/types.ts | 8 - .../reference/api/tsserverlibrary.d.ts | 18 +- tests/baselines/reference/api/typescript.d.ts | 18 +- tests/cases/fourslash/fourslash.ts | 9 +- ...etEditsForFileRename_preservePathEnding.ts | 44 ++++ .../importNameCodeFixNewImportTypeRoots0.ts | 45 ++-- .../importNameCodeFixNewImportTypeRoots1.ts | 50 +++-- .../importNameCodeFix_endingPreference.ts | 26 +++ .../importNameCodeFix_jsExtension.ts | 16 +- .../importNameCodeFix_types_classic.ts | 18 +- 15 files changed, 309 insertions(+), 187 deletions(-) create mode 100644 tests/cases/fourslash/getEditsForFileRename_preservePathEnding.ts create mode 100644 tests/cases/fourslash/importNameCodeFix_endingPreference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6106505df87..26e5a6b83be 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3926,13 +3926,22 @@ namespace ts { const links = getSymbolLinks(symbol); let specifier = links.specifierCache && links.specifierCache.get(contextFile.path); if (!specifier) { - specifier = moduleSpecifiers.getModuleSpecifierForDeclarationFile( + const isBundle = (compilerOptions.out || compilerOptions.outFile); + // For declaration bundles, we need to generate absolute paths relative to the common source dir for imports, + // just like how the declaration emitter does for the ambient module declarations - we can easily accomplish this + // using the `baseUrl` compiler option (which we would otherwise never use in declaration emit) and a non-relative + // specifier preference + const { moduleResolverHost } = context.tracker; + const specifierCompilerOptions = isBundle ? { ...compilerOptions, baseUrl: moduleResolverHost.getCommonSourceDirectory() } : compilerOptions; + specifier = first(first(moduleSpecifiers.getModuleSpecifiers( symbol, - compilerOptions, + specifierCompilerOptions, contextFile, - context.tracker.moduleResolverHost, + moduleResolverHost, + host.getSourceFiles(), + { importModuleSpecifierPreference: isBundle ? "non-relative" : "relative" }, host.redirectTargetsMap, - ); + ))); links.specifierCache = links.specifierCache || createMap(); links.specifierCache.set(contextFile.path, specifier); } diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 8c695e10be2..18b2ea76b01 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -1,8 +1,52 @@ // Used by importFixes, getEditsForFileRename, and declaration emit to synthesize import module specifiers. /* @internal */ namespace ts.moduleSpecifiers { - export interface ModuleSpecifierPreferences { - readonly importModuleSpecifierPreference?: "relative" | "non-relative"; + const enum RelativePreference { Relative, NonRelative, Auto } + // See UserPreferences#importPathEnding + const enum Ending { Minimal, Index, JsExtension } + + // Processed preferences + interface Preferences { + readonly relativePreference: RelativePreference; + readonly ending: Ending; + } + + function getPreferences({ importModuleSpecifierPreference, importModuleSpecifierEnding }: UserPreferences, compilerOptions: CompilerOptions, importingSourceFile: SourceFile): Preferences { + return { + relativePreference: importModuleSpecifierPreference === "relative" ? RelativePreference.Relative : importModuleSpecifierPreference === "non-relative" ? RelativePreference.NonRelative : RelativePreference.Auto, + ending: getEnding(), + }; + function getEnding(): Ending { + switch (importModuleSpecifierEnding) { + case "minimal": return Ending.Minimal; + case "index": return Ending.Index; + case "js": return Ending.JsExtension; + default: return usesJsExtensionOnImports(importingSourceFile) ? Ending.JsExtension + : getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs ? Ending.Index : Ending.Minimal; + } + } + } + + function getPreferencesForUpdate(compilerOptions: CompilerOptions, oldImportSpecifier: string): Preferences { + return { + relativePreference: isExternalModuleNameRelative(oldImportSpecifier) ? RelativePreference.Relative : RelativePreference.NonRelative, + ending: hasJavaScriptOrJsonFileExtension(oldImportSpecifier) ? Ending.JsExtension + : getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs || endsWith(oldImportSpecifier, "index") ? Ending.Index : Ending.Minimal, + }; + } + + export function updateModuleSpecifier( + compilerOptions: CompilerOptions, + importingSourceFileName: Path, + toFileName: string, + host: ModuleSpecifierResolutionHost, + files: ReadonlyArray, + redirectTargetsMap: RedirectTargetsMap, + oldImportSpecifier: string, + ): string | undefined { + const res = getModuleSpecifierWorker(compilerOptions, importingSourceFileName, toFileName, host, files, redirectTargetsMap, getPreferencesForUpdate(compilerOptions, oldImportSpecifier)); + if (res === oldImportSpecifier) return undefined; + return res; } // Note: importingSourceFile is just for usesJsExtensionOnImports @@ -13,35 +57,25 @@ namespace ts.moduleSpecifiers { toFileName: string, host: ModuleSpecifierResolutionHost, files: ReadonlyArray, - preferences: ModuleSpecifierPreferences = {}, + preferences: UserPreferences = {}, redirectTargetsMap: RedirectTargetsMap, ): string { - const info = getInfo(compilerOptions, importingSourceFile, importingSourceFileName, host); - const modulePaths = getAllModulePaths(files, importingSourceFileName, toFileName, info.getCanonicalFileName, host, redirectTargetsMap); - return firstDefined(modulePaths, moduleFileName => getGlobalModuleSpecifier(moduleFileName, info, host, compilerOptions)) || - first(getLocalModuleSpecifiers(toFileName, info, compilerOptions, preferences)); + return getModuleSpecifierWorker(compilerOptions, importingSourceFileName, toFileName, host, files, redirectTargetsMap, getPreferences(preferences, compilerOptions, importingSourceFile)); } - export function getModuleSpecifierForDeclarationFile( - moduleSymbol: Symbol, + function getModuleSpecifierWorker( compilerOptions: CompilerOptions, - importingSourceFile: SourceFile, + importingSourceFileName: Path, + toFileName: string, host: ModuleSpecifierResolutionHost, + files: ReadonlyArray, redirectTargetsMap: RedirectTargetsMap, + preferences: Preferences ): string { - const isBundle = (compilerOptions.out || compilerOptions.outFile); - if (isBundle && host.getCommonSourceDirectory) { - // For declaration bundles, we need to generate absolute paths relative to the common source dir for imports, - // just like how the declaration emitter does for the ambient module declarations - we can easily accomplish this - // using the `baseUrl` compiler option (which we would otherwise never use in declaration emit) and a non-relative - // specifier preference - compilerOptions = { - ...compilerOptions, - baseUrl: host.getCommonSourceDirectory(), - }; - } - const preferences: ModuleSpecifierPreferences = { importModuleSpecifierPreference: isBundle ? "non-relative" : "relative" }; - return first(first(getModuleSpecifiers(moduleSymbol, compilerOptions, importingSourceFile, host, host.getSourceFiles ? host.getSourceFiles() : [importingSourceFile], preferences, redirectTargetsMap))); + const info = getInfo(importingSourceFileName, host); + const modulePaths = getAllModulePaths(files, importingSourceFileName, toFileName, info.getCanonicalFileName, host, redirectTargetsMap); + return firstDefined(modulePaths, moduleFileName => tryGetModuleNameAsNodeModule(moduleFileName, info, host, compilerOptions)) || + first(getLocalModuleSpecifiers(toFileName, info, compilerOptions, preferences)); } // For each symlink/original for a module, returns a list of ways to import that file. @@ -51,60 +85,39 @@ namespace ts.moduleSpecifiers { importingSourceFile: SourceFile, host: ModuleSpecifierResolutionHost, files: ReadonlyArray, - preferences: ModuleSpecifierPreferences, + userPreferences: UserPreferences, redirectTargetsMap: RedirectTargetsMap, ): ReadonlyArray> { const ambient = tryGetModuleNameFromAmbientModule(moduleSymbol); if (ambient) return [[ambient]]; - const info = getInfo(compilerOptions, importingSourceFile, importingSourceFile.path, host); - if (!files) { - return Debug.fail("Files list must be present to resolve symlinks in specifier resolution"); - } + const info = getInfo(importingSourceFile.path, host); const moduleSourceFile = getSourceFileOfNode(moduleSymbol.valueDeclaration || getNonAugmentationDeclaration(moduleSymbol)); const modulePaths = getAllModulePaths(files, importingSourceFile.path, moduleSourceFile.fileName, info.getCanonicalFileName, host, redirectTargetsMap); - const global = mapDefined(modulePaths, moduleFileName => getGlobalModuleSpecifier(moduleFileName, info, host, compilerOptions)); + const preferences = getPreferences(userPreferences, compilerOptions, importingSourceFile); + const global = mapDefined(modulePaths, moduleFileName => tryGetModuleNameAsNodeModule(moduleFileName, info, host, compilerOptions)); return global.length ? global.map(g => [g]) : modulePaths.map(moduleFileName => getLocalModuleSpecifiers(moduleFileName, info, compilerOptions, preferences)); } interface Info { - readonly moduleResolutionKind: ModuleResolutionKind; - readonly addJsExtension: boolean; readonly getCanonicalFileName: GetCanonicalFileName; readonly sourceDirectory: Path; } // importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path - function getInfo(compilerOptions: CompilerOptions, importingSourceFile: SourceFile, importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Info { - const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); - const addJsExtension = usesJsExtensionOnImports(importingSourceFile); + function getInfo(importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Info { const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : true); const sourceDirectory = getDirectoryPath(importingSourceFileName); - return { moduleResolutionKind, addJsExtension, getCanonicalFileName, sourceDirectory }; + return { getCanonicalFileName, sourceDirectory }; } - function getGlobalModuleSpecifier( - moduleFileName: string, - { addJsExtension, getCanonicalFileName, sourceDirectory }: Info, - host: ModuleSpecifierResolutionHost, - compilerOptions: CompilerOptions, - ) { - return tryGetModuleNameFromTypeRoots(compilerOptions, host, getCanonicalFileName, moduleFileName, addJsExtension) - || tryGetModuleNameAsNodeModule(compilerOptions, moduleFileName, host, getCanonicalFileName, sourceDirectory); - } - - function getLocalModuleSpecifiers( - moduleFileName: string, - { moduleResolutionKind, addJsExtension, getCanonicalFileName, sourceDirectory }: Info, - compilerOptions: CompilerOptions, - preferences: ModuleSpecifierPreferences, - ): ReadonlyArray { + function getLocalModuleSpecifiers(moduleFileName: string, { getCanonicalFileName, sourceDirectory }: Info, compilerOptions: CompilerOptions, { ending, relativePreference }: Preferences): ReadonlyArray { const { baseUrl, paths, rootDirs } = compilerOptions; const relativePath = rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName) || - removeExtensionAndIndexPostFix(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), moduleResolutionKind, addJsExtension); - if (!baseUrl || preferences.importModuleSpecifierPreference === "relative") { + removeExtensionAndIndexPostFix(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), ending, compilerOptions); + if (!baseUrl || relativePreference === RelativePreference.Relative) { return [relativePath]; } @@ -113,7 +126,7 @@ namespace ts.moduleSpecifiers { return [relativePath]; } - const importRelativeToBaseUrl = removeExtensionAndIndexPostFix(relativeToBaseUrl, moduleResolutionKind, addJsExtension); + const importRelativeToBaseUrl = removeExtensionAndIndexPostFix(relativeToBaseUrl, ending, compilerOptions); if (paths) { const fromPaths = tryGetModuleNameFromPaths(removeFileExtension(relativeToBaseUrl), importRelativeToBaseUrl, paths); if (fromPaths) { @@ -121,11 +134,11 @@ namespace ts.moduleSpecifiers { } } - if (preferences.importModuleSpecifierPreference === "non-relative") { + if (relativePreference === RelativePreference.NonRelative) { return [importRelativeToBaseUrl]; } - if (preferences.importModuleSpecifierPreference !== undefined) Debug.assertNever(preferences.importModuleSpecifierPreference); + if (relativePreference !== RelativePreference.Auto) Debug.assertNever(relativePreference); if (isPathRelativeToParent(relativeToBaseUrl)) { return [relativePath]; @@ -164,7 +177,7 @@ namespace ts.moduleSpecifiers { } function usesJsExtensionOnImports({ imports }: SourceFile): boolean { - return firstDefined(imports, ({ text }) => pathIsRelative(text) ? fileExtensionIs(text, Extension.Js) : undefined) || false; + return firstDefined(imports, ({ text }) => pathIsRelative(text) ? hasJavaScriptOrJsonFileExtension(text) : undefined) || false; } function stringsEqual(a: string, b: string, getCanonicalFileName: GetCanonicalFileName): boolean { @@ -283,37 +296,8 @@ namespace ts.moduleSpecifiers { return removeFileExtension(relativePath); } - function tryGetModuleNameFromTypeRoots( - options: CompilerOptions, - host: GetEffectiveTypeRootsHost, - getCanonicalFileName: (file: string) => string, - moduleFileName: string, - addJsExtension: boolean, - ): string | undefined { - const roots = getEffectiveTypeRoots(options, host); - return firstDefined(roots, unNormalizedTypeRoot => { - const typeRoot = toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName); - if (startsWith(moduleFileName, typeRoot)) { - // For a type definition, we can strip `/index` even with classic resolution. - return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), ModuleResolutionKind.NodeJs, addJsExtension); - } - }); - } - - function tryGetModuleNameAsNodeModule( - options: CompilerOptions, - moduleFileName: string, - host: ModuleSpecifierResolutionHost, - getCanonicalFileName: (file: string) => string, - sourceDirectory: Path, - ): string | undefined { - if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs) { - // nothing to do here - return undefined; - } - + function tryGetModuleNameAsNodeModule(moduleFileName: string, { getCanonicalFileName, sourceDirectory }: Info, host: ModuleSpecifierResolutionHost, options: CompilerOptions): string | undefined { const parts: NodeModulePathParts = getNodeModulePathParts(moduleFileName)!; - if (!parts) { return undefined; } @@ -325,8 +309,12 @@ namespace ts.moduleSpecifiers { // Get a path that's relative to node_modules or the importing file's path // if node_modules folder is in this folder or any of its parent folders, no need to keep it. if (!startsWith(sourceDirectory, getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)))) return undefined; + // If the module was found in @types, get the actual Node package name - return getPackageNameFromAtTypesDirectory(moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1)); + const nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); + const packageName = getPackageNameFromAtTypesDirectory(nodeModulesDirectoryName); + // For classic resolution, only allow importing from node_modules/@types, not other node_modules + return getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName; function getDirectoryOrExtensionlessFileName(path: string): string { // If the file is the main module, it can be imported by the package name @@ -440,13 +428,35 @@ namespace ts.moduleSpecifiers { }); } - function removeExtensionAndIndexPostFix(fileName: string, moduleResolutionKind: ModuleResolutionKind, addJsExtension: boolean): string { + function removeExtensionAndIndexPostFix(fileName: string, ending: Ending, options: CompilerOptions): string { const noExtension = removeFileExtension(fileName); - return addJsExtension - ? noExtension + ".js" - : moduleResolutionKind === ModuleResolutionKind.NodeJs - ? removeSuffix(noExtension, "/index") - : noExtension; + switch (ending) { + case Ending.Minimal: + return removeSuffix(noExtension, "/index"); + case Ending.Index: + return noExtension; + case Ending.JsExtension: + return noExtension + getJavaScriptExtensionForFile(fileName, options); + default: + return Debug.assertNever(ending); + } + } + + function getJavaScriptExtensionForFile(fileName: string, options: CompilerOptions): Extension { + const ext = extensionFromPath(fileName); + switch (ext) { + case Extension.Ts: + case Extension.Dts: + return Extension.Js; + case Extension.Tsx: + return options.jsx === JsxEmit.Preserve ? Extension.Jsx : Extension.Js; + case Extension.Js: + case Extension.Jsx: + case Extension.Json: + return ext; + default: + return Debug.assertNever(ext); + } } function getRelativePathIfInDirectory(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d9d57cfcf17..8977d9be281 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5331,8 +5331,6 @@ namespace ts { useCaseSensitiveFileNames?(): boolean; fileExists?(path: string): boolean; readFile?(path: string): string | undefined; - getSourceFiles?(): ReadonlyArray; // Used for cached resolutions to find symlinks without traversing the fs (again) - getCommonSourceDirectory?(): string; } // Note: this used to be deprecated in our public API, but is still used internally @@ -5345,7 +5343,7 @@ namespace ts { reportInaccessibleThisError?(): void; reportPrivateInBaseOfClassExpression?(propertyName: string): void; reportInaccessibleUniqueSymbolError?(): void; - moduleResolverHost?: ModuleSpecifierResolutionHost; + moduleResolverHost?: EmitHost; trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void; trackExternalModuleSymbolOfImportTypeNode?(symbol: Symbol): void; } @@ -5595,4 +5593,15 @@ namespace ts { get(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]; forEach(action: (value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void; } + + export interface UserPreferences { + readonly disableSuggestions?: boolean; + readonly quotePreference?: "double" | "single"; + readonly includeCompletionsForModuleExports?: boolean; + readonly includeCompletionsWithInsertText?: boolean; + readonly importModuleSpecifierPreference?: "relative" | "non-relative"; + /** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */ + readonly importModuleSpecifierEnding?: "minimal" | "index" | "js"; + readonly allowTextChangesInNewFiles?: boolean; + } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b808a1f2fd1..d04f921ec95 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -7936,6 +7936,7 @@ namespace ts { /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ export const supportedTypescriptExtensionsForExtractExtension: ReadonlyArray = [Extension.Dts, Extension.Ts, Extension.Tsx]; export const supportedJavascriptExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx]; + export const supportedJavaScriptAndJsonExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx, Extension.Json]; const allSupportedExtensions: ReadonlyArray = [...supportedTypeScriptExtensions, ...supportedJavascriptExtensions]; export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: ReadonlyArray): ReadonlyArray { @@ -7961,6 +7962,10 @@ namespace ts { return some(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension)); } + export function hasJavaScriptOrJsonFileExtension(fileName: string): boolean { + return supportedJavaScriptAndJsonExtensions.some(ext => fileExtensionIs(fileName, ext)); + } + export function hasTypeScriptFileExtension(fileName: string): boolean { return some(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension)); } diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index bd00ce5dd9e..4fe024787f3 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -6,7 +6,7 @@ namespace ts { newFileOrDirPath: string, host: LanguageServiceHost, formatContext: formatting.FormatContext, - preferences: UserPreferences, + _preferences: UserPreferences, sourceMapper: SourceMapper, ): ReadonlyArray { const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host); @@ -15,7 +15,7 @@ namespace ts { const newToOld = getPathUpdater(newFileOrDirPath, oldFileOrDirPath, getCanonicalFileName, sourceMapper); return textChanges.ChangeTracker.with({ host, formatContext }, changeTracker => { updateTsconfigFiles(program, changeTracker, oldToNew, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames); - updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName, preferences); + updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName); }); } @@ -122,7 +122,6 @@ namespace ts { newToOld: PathUpdater, host: LanguageServiceHost, getCanonicalFileName: GetCanonicalFileName, - preferences: UserPreferences, ): void { const allFiles = program.getSourceFiles(); for (const sourceFile of allFiles) { @@ -156,7 +155,7 @@ namespace ts { // Need an update if the imported file moved, or the importing file moved and was using a relative path. return toImport !== undefined && (toImport.updated || (importingSourceFileMoved && pathIsRelative(importLiteral.text))) - ? moduleSpecifiers.getModuleSpecifier(program.getCompilerOptions(), sourceFile, newImportFromPath, toImport.newFileName, host, allFiles, preferences, program.redirectTargetsMap) + ? moduleSpecifiers.updateModuleSpecifier(program.getCompilerOptions(), newImportFromPath, toImport.newFileName, host, allFiles, program.redirectTargetsMap, importLiteral.text) : undefined; }); } @@ -210,7 +209,7 @@ namespace ts { } function updateImportsWorker(sourceFile: SourceFile, changeTracker: textChanges.ChangeTracker, updateRef: (refText: string) => string | undefined, updateImport: (importLiteral: StringLiteralLike) => string | undefined) { - for (const ref of sourceFile.referencedFiles) { + for (const ref of sourceFile.referencedFiles || emptyArray) { // TODO: GH#26162 const updated = updateRef(ref.fileName); if (updated !== undefined && updated !== sourceFile.text.slice(ref.pos, ref.end)) changeTracker.replaceRangeWithText(sourceFile, ref, updated); } diff --git a/src/services/types.ts b/src/services/types.ts index 51c98724c09..9bf0edf3150 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -233,14 +233,6 @@ namespace ts { installPackage?(options: InstallPackageOptions): Promise; } - export interface UserPreferences { - readonly disableSuggestions?: boolean; - readonly quotePreference?: "double" | "single"; - readonly includeCompletionsForModuleExports?: boolean; - readonly includeCompletionsWithInsertText?: boolean; - readonly importModuleSpecifierPreference?: "relative" | "non-relative"; - readonly allowTextChangesInNewFiles?: boolean; - } /* @internal */ export const emptyOptions = {}; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5c261c55a4c..e8cda88590b 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2990,6 +2990,16 @@ declare namespace ts { Parameters = 1296, IndexSignatureParameters = 4432 } + interface UserPreferences { + readonly disableSuggestions?: boolean; + readonly quotePreference?: "double" | "single"; + readonly includeCompletionsForModuleExports?: boolean; + readonly includeCompletionsWithInsertText?: boolean; + readonly importModuleSpecifierPreference?: "relative" | "non-relative"; + /** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */ + readonly importModuleSpecifierEnding?: "minimal" | "index" | "js"; + readonly allowTextChangesInNewFiles?: boolean; + } } declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any; declare function clearTimeout(handle: any): void; @@ -4636,14 +4646,6 @@ declare namespace ts { isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; } - interface UserPreferences { - readonly disableSuggestions?: boolean; - readonly quotePreference?: "double" | "single"; - readonly includeCompletionsForModuleExports?: boolean; - readonly includeCompletionsWithInsertText?: boolean; - readonly importModuleSpecifierPreference?: "relative" | "non-relative"; - readonly allowTextChangesInNewFiles?: boolean; - } interface LanguageService { cleanupSemanticCache(): void; getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[]; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index e92e3d6e1d5..c12d797bea8 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2990,6 +2990,16 @@ declare namespace ts { Parameters = 1296, IndexSignatureParameters = 4432 } + interface UserPreferences { + readonly disableSuggestions?: boolean; + readonly quotePreference?: "double" | "single"; + readonly includeCompletionsForModuleExports?: boolean; + readonly includeCompletionsWithInsertText?: boolean; + readonly importModuleSpecifierPreference?: "relative" | "non-relative"; + /** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */ + readonly importModuleSpecifierEnding?: "minimal" | "index" | "js"; + readonly allowTextChangesInNewFiles?: boolean; + } } declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any; declare function clearTimeout(handle: any): void; @@ -4636,14 +4646,6 @@ declare namespace ts { isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; } - interface UserPreferences { - readonly disableSuggestions?: boolean; - readonly quotePreference?: "double" | "single"; - readonly includeCompletionsForModuleExports?: boolean; - readonly includeCompletionsWithInsertText?: boolean; - readonly importModuleSpecifierPreference?: "relative" | "non-relative"; - readonly allowTextChangesInNewFiles?: boolean; - } interface LanguageService { cleanupSemanticCache(): void; getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[]; diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 8a91718dd7b..2d73be1a917 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -528,10 +528,11 @@ declare namespace FourSlashInterface { filesToSearch?: ReadonlyArray; } interface UserPreferences { - quotePreference?: "double" | "single"; - includeCompletionsForModuleExports?: boolean; - includeInsertTextCompletions?: boolean; - importModuleSpecifierPreference?: "relative" | "non-relative"; + readonly quotePreference?: "double" | "single"; + readonly includeCompletionsForModuleExports?: boolean; + readonly includeInsertTextCompletions?: boolean; + readonly importModuleSpecifierPreference?: "relative" | "non-relative"; + readonly importModuleSpecifierEnding?: "minimal" | "index" | "js"; } interface CompletionsAtOptions extends UserPreferences { triggerCharacter?: string; diff --git a/tests/cases/fourslash/getEditsForFileRename_preservePathEnding.ts b/tests/cases/fourslash/getEditsForFileRename_preservePathEnding.ts new file mode 100644 index 00000000000..54b3e0e0612 --- /dev/null +++ b/tests/cases/fourslash/getEditsForFileRename_preservePathEnding.ts @@ -0,0 +1,44 @@ +/// + +// @allowJs: true +// @checkJs: true +// @strict: true +// @jsx: preserve +// @resolveJsonModule: true + +// @Filename: /index.js +////export const x = 0; + +// @Filename: /jsx.jsx +////export const y = 0; + +// @Filename: /j.jonah.json +////{ "j": 0 } + +// @Filename: /a.js +////import { x as x0 } from "."; +////import { x as x1 } from "./index"; +////import { x as x2 } from "./index.js"; +////import { y } from "./jsx.jsx"; +////import { j } from "./j.jonah.json"; + +verify.noErrors(); + +verify.getEditsForFileRename({ + oldPath: "/a.js", + newPath: "/b.js", + newFileContents: {}, // No change +}); + +verify.getEditsForFileRename({ + oldPath: "/b.js", + newPath: "/src/b.js", + newFileContents: { + "/b.js": +`import { x as x0 } from ".."; +import { x as x1 } from "../index"; +import { x as x2 } from "../index.js"; +import { y } from "../jsx.jsx"; +import { j } from "../j.jonah.json";`, + }, +}); diff --git a/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots0.ts b/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots0.ts index cb7ef465aff..ddc6d1790c7 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots0.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots0.ts @@ -1,22 +1,23 @@ -/// - -// @Filename: a/f1.ts -//// [|foo/*0*/();|] - -// @Filename: types/random/index.ts -//// export function foo() {}; - -// @Filename: tsconfig.json -//// { -//// "compilerOptions": { -//// "typeRoots": [ -//// "./types" -//// ] -//// } -//// } - -verify.importFixAtPosition([ -`import { foo } from "random"; - -foo();` -]); +/// + +// @Filename: a/f1.ts +//// [|foo/*0*/();|] + +// @Filename: types/random/index.ts +//// export function foo() {}; + +// @Filename: tsconfig.json +//// { +//// "compilerOptions": { +//// "typeRoots": [ +//// "./types" +//// ] +//// } +//// } + +// "typeRoots" does not affect module resolution. Importing from "random" would be a compile error. +verify.importFixAtPosition([ +`import { foo } from "../types/random"; + +foo();` +]); diff --git a/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots1.ts b/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots1.ts index 1398a5d7866..9743d164a9c 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots1.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportTypeRoots1.ts @@ -1,23 +1,27 @@ -/// - -// @Filename: a/f1.ts -//// [|foo/*0*/();|] - -// @Filename: types/random/index.ts -//// export function foo() {}; - -// @Filename: tsconfig.json -//// { -//// "compilerOptions": { -//// "baseUrl": ".", -//// "typeRoots": [ -//// "./types" -//// ] -//// } -//// } - -verify.importFixAtPosition([ -`import { foo } from "random"; - -foo();` -]); +/// + +// @Filename: a/f1.ts +//// [|foo/*0*/();|] + +// @Filename: types/random/index.ts +//// export function foo() {}; + +// @Filename: tsconfig.json +//// { +//// "compilerOptions": { +//// "baseUrl": ".", +//// "typeRoots": [ +//// "./types" +//// ] +//// } +//// } + +// "typeRoots" does not affect module resolution. Importing from "random" would be a compile error. +verify.importFixAtPosition([ +`import { foo } from "types/random"; + +foo();`, +`import { foo } from "../types/random"; + +foo();` +]); diff --git a/tests/cases/fourslash/importNameCodeFix_endingPreference.ts b/tests/cases/fourslash/importNameCodeFix_endingPreference.ts new file mode 100644 index 00000000000..41a96e9cf06 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_endingPreference.ts @@ -0,0 +1,26 @@ +/// + +// @moduleResolution: node + +// @Filename: /foo/index.ts +////export const foo = 0; + +// @Filename: /a.ts +////foo; + +// @Filename: /b.ts +////foo; + +// @Filename: /c.ts +////foo; + +const tests: ReadonlyArray<[string, FourSlashInterface.UserPreferences["importModuleSpecifierEnding"], string]> = [ + ["/a.ts", "js", "./foo/index.js"], + ["/b.ts", "index", "./foo/index"], + ["/c.ts", "minimal", "./foo"], +]; + +for (const [fileName, importModuleSpecifierEnding, specifier] of tests) { + goTo.file(fileName); + verify.importFixAtPosition([`import { foo } from "${specifier}";\n\nfoo;`,], /*errorCode*/ undefined, { importModuleSpecifierEnding }); +} diff --git a/tests/cases/fourslash/importNameCodeFix_jsExtension.ts b/tests/cases/fourslash/importNameCodeFix_jsExtension.ts index e719f1aeee8..b47e67d82b2 100644 --- a/tests/cases/fourslash/importNameCodeFix_jsExtension.ts +++ b/tests/cases/fourslash/importNameCodeFix_jsExtension.ts @@ -2,6 +2,7 @@ // @moduleResolution: node // @noLib: true +// @jsx: preserve // @Filename: /a.ts ////export function a() {} @@ -9,17 +10,24 @@ // @Filename: /b.ts ////export function b() {} +// @Filename: /c.tsx +////export function c() {} + // @Filename: /c.ts ////import * as g from "global"; // Global imports skipped ////import { a } from "./a.js"; ////import { a as a2 } from "./a"; // Ignored, only the first relative import is considered -////b; +////b; c; goTo.file("/c.ts"); -verify.importFixAtPosition([ +verify.codeFixAll({ + fixId: "fixMissingImport", + fixAllDescription: "Add all missing imports", + newFileContent: `import * as g from "global"; // Global imports skipped import { a } from "./a.js"; import { a as a2 } from "./a"; // Ignored, only the first relative import is considered import { b } from "./b.js"; -b;`, -]); +import { c } from "./c.jsx"; +b; c;`, +}); diff --git a/tests/cases/fourslash/importNameCodeFix_types_classic.ts b/tests/cases/fourslash/importNameCodeFix_types_classic.ts index b9ba463fada..4d3bdda4d31 100644 --- a/tests/cases/fourslash/importNameCodeFix_types_classic.ts +++ b/tests/cases/fourslash/importNameCodeFix_types_classic.ts @@ -5,12 +5,22 @@ // @Filename: /node_modules/@types/foo/index.d.ts ////export const xyz: number; +// @Filename: /node_modules/bar/index.d.ts +////export const qrs: number; + // @Filename: /a.ts -////[|xyz|] +////xyz; +////qrs; goTo.file("/a.ts"); -verify.importFixAtPosition([ +verify.codeFixAll({ + fixId: "fixMissingImport", + fixAllDescription: "Add all missing imports", + newFileContent: `import { xyz } from "foo"; -xyz` -]); +import { qrs } from "./node_modules/bar/index"; + +xyz; +qrs;`, +}); From 552bd1c8a2cba709c5161e8bd667d60c591eccef Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 13:04:11 -0700 Subject: [PATCH 73/77] Support import fix/completions for `export =` (#25708) --- src/compiler/checker.ts | 2 - src/compiler/types.ts | 4 ++ src/harness/fourslash.ts | 6 ++- src/services/codefixes/importFixes.ts | 49 +++++++++++------ src/services/completions.ts | 8 +++ .../completionsImport_default_anonymous.ts | 2 +- .../completionsImport_exportEquals.ts | 53 +++++++++++++++++++ ...mport_exportEqualsNamespace_noDuplicate.ts | 2 +- .../cases/fourslash/completionsImport_tsx.ts | 2 +- .../completionsUniqueSymbol_import.ts | 2 +- .../cases/fourslash/importNameCodeFix_all.ts | 2 +- .../importNameCodeFix_exportEquals.ts | 25 +++++++++ 12 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 tests/cases/fourslash/completionsImport_exportEquals.ts create mode 100644 tests/cases/fourslash/importNameCodeFix_exportEquals.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26e5a6b83be..41573a7a8f6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2286,8 +2286,6 @@ namespace ts { return getPackagesSet().has(getTypesPackageName(packageName)); } - // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, - // and an external module with no 'export =' declaration resolves to the module itself. function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol; function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8977d9be281..e024885d6e8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3097,6 +3097,10 @@ namespace ts { */ /* @internal */ getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined; /* @internal */ getTypePredicateOfSignature(signature: Signature): TypePredicate; + /** + * An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, + * and an external module with no 'export =' declaration resolves to the module itself. + */ /* @internal */ resolveExternalModuleSymbol(symbol: Symbol): Symbol; /** @param node A location where we might consider accessing `this`. Not necessarily a ThisExpression. */ /* @internal */ tryGetThisTypeAt(node: Node): Type | undefined; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 5d1ac5c491f..214e1f295ab 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -908,8 +908,8 @@ namespace FourSlash { } private verifyCompletionEntry(actual: ts.CompletionEntry, expected: FourSlashInterface.ExpectedCompletionEntry) { - const { insertText, replacementSpan, hasAction, isRecommended, kind, text, documentation, sourceDisplay } = typeof expected === "string" - ? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, kind: undefined, text: undefined, documentation: undefined, sourceDisplay: undefined } + const { insertText, replacementSpan, hasAction, isRecommended, kind, text, documentation, source, sourceDisplay } = typeof expected === "string" + ? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, kind: undefined, text: undefined, documentation: undefined, source: undefined, sourceDisplay: undefined } : expected; if (actual.insertText !== insertText) { @@ -927,6 +927,7 @@ namespace FourSlash { assert.equal(actual.hasAction, hasAction); assert.equal(actual.isRecommended, isRecommended); + assert.equal(actual.source, source); if (text) { const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source)!; @@ -4789,6 +4790,7 @@ namespace FourSlashInterface { export type ExpectedCompletionEntry = string | { readonly name: string, + readonly source?: string, readonly insertText?: string, readonly replacementSpan?: FourSlash.Range, readonly hasAction?: boolean, // If not specified, will assert that this is false. diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 3c5b1d06eaf..7ff5d30c954 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -163,7 +163,7 @@ namespace ts.codefix { position: number, preferences: UserPreferences, ): { readonly moduleSpecifier: string, readonly codeAction: CodeAction } { - const exportInfos = getAllReExportingModules(exportedSymbol, moduleSymbol, symbolName, sourceFile, program.getTypeChecker(), program.getSourceFiles()); + const exportInfos = getAllReExportingModules(exportedSymbol, moduleSymbol, symbolName, sourceFile, program.getCompilerOptions(), program.getTypeChecker(), program.getSourceFiles()); Debug.assert(exportInfos.some(info => info.moduleSymbol === moduleSymbol)); // We sort the best codefixes first, so taking `first` is best for completions. const moduleSpecifier = first(getNewImportInfos(program, sourceFile, position, exportInfos, host, preferences)).moduleSpecifier; @@ -175,7 +175,7 @@ namespace ts.codefix { return { description, changes, commands }; } - function getAllReExportingModules(exportedSymbol: Symbol, exportingModuleSymbol: Symbol, symbolName: string, sourceFile: SourceFile, checker: TypeChecker, allSourceFiles: ReadonlyArray): ReadonlyArray { + function getAllReExportingModules(exportedSymbol: Symbol, exportingModuleSymbol: Symbol, symbolName: string, sourceFile: SourceFile, compilerOptions: CompilerOptions, checker: TypeChecker, allSourceFiles: ReadonlyArray): ReadonlyArray { const result: SymbolExportInfo[] = []; forEachExternalModule(checker, allSourceFiles, (moduleSymbol, moduleFile) => { // Don't import from a re-export when looking "up" like to `./index` or `../index`. @@ -183,10 +183,14 @@ namespace ts.codefix { return; } + const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); + if (defaultInfo && defaultInfo.name === symbolName && skipAlias(defaultInfo.symbol, checker) === exportedSymbol) { + result.push({ moduleSymbol, importKind: defaultInfo.kind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(defaultInfo.symbol) }); + } + for (const exported of checker.getExportsOfModule(moduleSymbol)) { - if ((exported.escapedName === InternalSymbolName.Default || exported.name === symbolName) && skipAlias(exported, checker) === exportedSymbol) { - const isDefaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol) === exported; - result.push({ moduleSymbol, importKind: isDefaultExport ? ImportKind.Default : ImportKind.Named, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exported) }); + if (exported.name === symbolName && skipAlias(exported, checker) === exportedSymbol) { + result.push({ moduleSymbol, importKind: ImportKind.Named, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exported) }); } } }); @@ -400,13 +404,9 @@ namespace ts.codefix { forEachExternalModuleToImportFrom(checker, sourceFile, program.getSourceFiles(), moduleSymbol => { cancellationToken.throwIfCancellationRequested(); - // check the default export - const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol); - if (defaultExport) { - const info = getDefaultExportInfo(defaultExport, moduleSymbol, program); - if (info && info.name === symbolName && symbolHasMeaning(info.symbolForMeaning, currentTokenMeaning)) { - addSymbol(moduleSymbol, defaultExport, ImportKind.Default); - } + const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, program.getCompilerOptions()); + if (defaultInfo && defaultInfo.name === symbolName && symbolHasMeaning(defaultInfo.symbolForMeaning, currentTokenMeaning)) { + addSymbol(moduleSymbol, defaultInfo.symbol, defaultInfo.kind); } // check exports with the same name @@ -418,7 +418,24 @@ namespace ts.codefix { return originalSymbolToExportInfos; } - function getDefaultExportInfo(defaultExport: Symbol, moduleSymbol: Symbol, program: Program): { readonly symbolForMeaning: Symbol, readonly name: string } | undefined { + function getDefaultLikeExportInfo( + moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions, + ): { readonly symbol: Symbol, readonly symbolForMeaning: Symbol, readonly name: string, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined { + const exported = getDefaultLikeExportWorker(moduleSymbol, checker); + if (!exported) return undefined; + const { symbol, kind } = exported; + const info = getDefaultExportInfoWorker(symbol, moduleSymbol, checker, compilerOptions); + return info && { symbol, symbolForMeaning: info.symbolForMeaning, name: info.name, kind }; + } + + function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker): { readonly symbol: Symbol, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined { + const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol); + if (defaultExport) return { symbol: defaultExport, kind: ImportKind.Default }; + const exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol); + return exportEquals === moduleSymbol ? undefined : { symbol: exportEquals, kind: ImportKind.Equals }; + } + + function getDefaultExportInfoWorker(defaultExport: Symbol, moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions): { readonly symbolForMeaning: Symbol, readonly name: string } | undefined { const localSymbol = getLocalSymbolForExportDefault(defaultExport); if (localSymbol) return { symbolForMeaning: localSymbol, name: localSymbol.name }; @@ -426,11 +443,11 @@ namespace ts.codefix { if (name !== undefined) return { symbolForMeaning: defaultExport, name }; if (defaultExport.flags & SymbolFlags.Alias) { - const aliased = program.getTypeChecker().getImmediateAliasedSymbol(defaultExport); - return aliased && getDefaultExportInfo(aliased, Debug.assertDefined(aliased.parent), program); + const aliased = checker.getImmediateAliasedSymbol(defaultExport); + return aliased && getDefaultExportInfoWorker(aliased, Debug.assertDefined(aliased.parent), checker, compilerOptions); } else { - return { symbolForMeaning: defaultExport, name: moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target!) }; + return { symbolForMeaning: defaultExport, name: moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target!) }; } } diff --git a/src/services/completions.ts b/src/services/completions.ts index 40986543318..7f82c9e7483 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1378,6 +1378,14 @@ namespace ts.Completions { return; } + if (resolvedModuleSymbol !== moduleSymbol && + // Don't add another completion for `export =` of a symbol that's already global. + // So in `declare namespace foo {} declare module "foo" { export = foo; }`, there will just be the global completion for `foo`. + resolvedModuleSymbol.declarations.some(d => !!d.getSourceFile().externalModuleIndicator)) { + symbols.push(resolvedModuleSymbol); + symbolToOriginInfoMap[getSymbolId(resolvedModuleSymbol)] = { kind: SymbolOriginInfoKind.Export, moduleSymbol, isDefaultExport: false }; + } + for (let symbol of typeChecker.getExportsOfModule(moduleSymbol)) { // Don't add a completion for a re-export, only for the original. // The actual import fix might end up coming from a re-export -- we don't compute that until getting completion details. diff --git a/tests/cases/fourslash/completionsImport_default_anonymous.ts b/tests/cases/fourslash/completionsImport_default_anonymous.ts index c406259dd6c..82e5f07b064 100644 --- a/tests/cases/fourslash/completionsImport_default_anonymous.ts +++ b/tests/cases/fourslash/completionsImport_default_anonymous.ts @@ -11,7 +11,7 @@ ////fooB/*1*/ goTo.marker("0"); -const preferences = { includeCompletionsForModuleExports: true }; +const preferences: FourSlashInterface.UserPreferences = { includeCompletionsForModuleExports: true }; verify.completions( { marker: "0", excludes: { name: "default", source: "/src/foo-bar" }, preferences }, { marker: "1", includes: { name: "fooBar", source: "/src/foo-bar", sourceDisplay: "./foo-bar", text: "(property) default: 0", kind: "property", hasAction: true }, preferences } diff --git a/tests/cases/fourslash/completionsImport_exportEquals.ts b/tests/cases/fourslash/completionsImport_exportEquals.ts new file mode 100644 index 00000000000..37e78e09f38 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_exportEquals.ts @@ -0,0 +1,53 @@ +/// + +// @module: commonjs + +// @Filename: /a.d.ts +////declare function a(): void; +////declare namespace a { +//// export interface b {} +////} +////export = a; + +// @Filename: /b.ts +////a/*0*/; +////let x: b/*1*/; + +const preferences: FourSlashInterface.UserPreferences = { includeCompletionsForModuleExports: true }; +verify.completions( + { + marker: "0", + includes: { name: "a", source: "/a", hasAction: true, }, + preferences, + }, + { + marker: "1", + includes: { name: "b", source: "/a", hasAction: true }, + preferences, + } +); + +// Import { b } first, or it will just add a qualified name from 'a' (which isn't what we're trying to test) +verify.applyCodeActionFromCompletion("1", { + name: "b", + source: "/a", + description: `Import 'b' from module "./a"`, + newFileContent: +`import { b } from "./a"; + +a; +let x: b;`, +}); + +verify.applyCodeActionFromCompletion("0", { + name: "a", + source: "/a", + description: `Import 'a' from module "./a"`, + newFileContent: +`import { b } from "./a"; +import a = require("./a"); + +a; +let x: b;`, +}); + diff --git a/tests/cases/fourslash/completionsImport_exportEqualsNamespace_noDuplicate.ts b/tests/cases/fourslash/completionsImport_exportEqualsNamespace_noDuplicate.ts index ede97c2d810..8a687f5a191 100644 --- a/tests/cases/fourslash/completionsImport_exportEqualsNamespace_noDuplicate.ts +++ b/tests/cases/fourslash/completionsImport_exportEqualsNamespace_noDuplicate.ts @@ -18,7 +18,7 @@ verify.completions({ marker: "", // Tester will assert that it is only included once - includes: [{ name: "foo", hasAction: true }], + includes: [{ name: "foo", source: "a", hasAction: true }], preferences: { includeCompletionsForModuleExports: true, } diff --git a/tests/cases/fourslash/completionsImport_tsx.ts b/tests/cases/fourslash/completionsImport_tsx.ts index f2f8752082b..9fb4d239223 100644 --- a/tests/cases/fourslash/completionsImport_tsx.ts +++ b/tests/cases/fourslash/completionsImport_tsx.ts @@ -12,7 +12,7 @@ verify.completions({ marker: "", - includes: { name: "Foo", source: "/a.tsx", hasAction: true }, + includes: { name: "Foo", source: "/a", hasAction: true }, excludes: "Bar", preferences: { includeCompletionsForModuleExports: true, diff --git a/tests/cases/fourslash/completionsUniqueSymbol_import.ts b/tests/cases/fourslash/completionsUniqueSymbol_import.ts index df3034e56fe..7f98f8c1dd7 100644 --- a/tests/cases/fourslash/completionsUniqueSymbol_import.ts +++ b/tests/cases/fourslash/completionsUniqueSymbol_import.ts @@ -24,7 +24,7 @@ verify.completions({ marker: "", exact: [ "n", - { name: "publicSym", insertText: "[publicSym]", replacementSpan: test.ranges()[0], hasAction: true }, + { name: "publicSym", source: "/a", insertText: "[publicSym]", replacementSpan: test.ranges()[0], hasAction: true }, ], preferences: { includeInsertTextCompletions: true, diff --git a/tests/cases/fourslash/importNameCodeFix_all.ts b/tests/cases/fourslash/importNameCodeFix_all.ts index 4aa22413d5a..d5bb525900a 100644 --- a/tests/cases/fourslash/importNameCodeFix_all.ts +++ b/tests/cases/fourslash/importNameCodeFix_all.ts @@ -37,11 +37,11 @@ verify.codeFixAll({ fixId: "fixMissingImport", fixAllDescription: "Add all missing imports", newFileContent: -// TODO: GH#25135 (should import 'e') `import bd, * as b from "./b"; import cd, { c0 } from "./c"; import dd, { d0, d1 } from "./d"; import ad, { a0 } from "./a"; +import e = require("./e"); ad; ad; a0; a0; bd; bd; b.b0; b.b0; diff --git a/tests/cases/fourslash/importNameCodeFix_exportEquals.ts b/tests/cases/fourslash/importNameCodeFix_exportEquals.ts new file mode 100644 index 00000000000..4ab87df7e76 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_exportEquals.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /a.d.ts +////declare function a(): void; +////declare namespace a { +//// export interface b {} +////} +////export = a; + +// @Filename: /b.ts +////a; +////let x: b; + +goTo.file("/b.ts"); +verify.codeFixAll({ + fixId: "fixMissingImport", + fixAllDescription: "Add all missing imports", + newFileContent: +`import { b } from "./a"; + +import a = require("./a"); + +a; +let x: b;`, +}); From 9106fdbc47f4b1e7ddb6458f62c2e00c775591d0 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 14:21:09 -0700 Subject: [PATCH 74/77] Support signature help for type parameters of a type (#26702) --- src/compiler/checker.ts | 4 +- src/compiler/types.ts | 2 + src/services/signatureHelp.ts | 76 +++++++++++++++---- .../genericParameterHelpTypeReferences.ts | 50 +++++++----- 4 files changed, 99 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 41573a7a8f6..cb3fc5614fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -370,7 +370,9 @@ namespace ts { finally { cancellationToken = undefined; } - } + }, + + getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, isForSignatureHelp: boolean): Signature | undefined { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e024885d6e8..10076014d96 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3118,6 +3118,8 @@ namespace ts { * and the operation is cancelled, then it should be discarded, otherwise it is safe to keep. */ runWithCancellationToken(token: CancellationToken, cb: (checker: TypeChecker) => T): T; + + /* @internal */ getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): ReadonlyArray | undefined; } /* @internal */ diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index d1705b51048..5211b244e21 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -2,7 +2,7 @@ namespace ts.SignatureHelp { const enum InvocationKind { Call, TypeArgs, Contextual } interface CallInvocation { readonly kind: InvocationKind.Call; readonly node: CallLikeExpression; } - interface TypeArgsInvocation { readonly kind: InvocationKind.TypeArgs; readonly called: Expression; } + interface TypeArgsInvocation { readonly kind: InvocationKind.TypeArgs; readonly called: Identifier; } interface ContextualInvocation { readonly kind: InvocationKind.Contextual; readonly signature: Signature; @@ -44,7 +44,7 @@ namespace ts.SignatureHelp { cancellationToken.throwIfCancellationRequested(); // Extra syntactic and semantic filtering of signature help - const candidateInfo = getCandidateInfo(argumentInfo, typeChecker, sourceFile, startingToken, onlyUseSyntacticOwners); + const candidateInfo = getCandidateOrTypeInfo(argumentInfo, typeChecker, sourceFile, startingToken, onlyUseSyntacticOwners); cancellationToken.throwIfCancellationRequested(); if (!candidateInfo) { @@ -53,11 +53,24 @@ namespace ts.SignatureHelp { return isSourceFileJavaScript(sourceFile) ? createJavaScriptSignatureHelpItems(argumentInfo, program, cancellationToken) : undefined; } - return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => createSignatureHelpItems(candidateInfo.candidates, candidateInfo.resolvedSignature, argumentInfo, sourceFile, typeChecker)); + return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => + candidateInfo.kind === CandidateOrTypeKind.Candidate + ? createSignatureHelpItems(candidateInfo.candidates, candidateInfo.resolvedSignature, argumentInfo, sourceFile, typeChecker) + : createTypeHelpItems(candidateInfo.symbol, argumentInfo, sourceFile, typeChecker)); } - interface CandidateInfo { readonly candidates: ReadonlyArray; readonly resolvedSignature: Signature; } - function getCandidateInfo({ invocation, argumentCount }: ArgumentListInfo, checker: TypeChecker, sourceFile: SourceFile, startingToken: Node, onlyUseSyntacticOwners: boolean): CandidateInfo | undefined { + const enum CandidateOrTypeKind { Candidate, Type } + interface CandidateInfo { + readonly kind: CandidateOrTypeKind.Candidate; + readonly candidates: ReadonlyArray; + readonly resolvedSignature: Signature; + } + interface TypeInfo { + readonly kind: CandidateOrTypeKind.Type; + readonly symbol: Symbol; + } + + function getCandidateOrTypeInfo({ invocation, argumentCount }: ArgumentListInfo, checker: TypeChecker, sourceFile: SourceFile, startingToken: Node, onlyUseSyntacticOwners: boolean): CandidateInfo | TypeInfo | undefined { switch (invocation.kind) { case InvocationKind.Call: { if (onlyUseSyntacticOwners && !isSyntacticOwner(startingToken, invocation.node, sourceFile)) { @@ -65,17 +78,21 @@ namespace ts.SignatureHelp { } const candidates: Signature[] = []; const resolvedSignature = checker.getResolvedSignatureForSignatureHelp(invocation.node, candidates, argumentCount)!; // TODO: GH#18217 - return candidates.length === 0 ? undefined : { candidates, resolvedSignature }; + return candidates.length === 0 ? undefined : { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature }; } case InvocationKind.TypeArgs: { - if (onlyUseSyntacticOwners && !lessThanFollowsCalledExpression(startingToken, sourceFile, invocation.called)) { + const { called } = invocation; + if (onlyUseSyntacticOwners && !containsPrecedingToken(startingToken, sourceFile, isIdentifier(called) ? called.parent : called)) { return undefined; } - const candidates = getPossibleGenericSignatures(invocation.called, argumentCount, checker); - return candidates.length === 0 ? undefined : { candidates, resolvedSignature: first(candidates) }; + const candidates = getPossibleGenericSignatures(called, argumentCount, checker); + if (candidates.length !== 0) return { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature: first(candidates) }; + + const symbol = checker.getSymbolAtLocation(called); + return symbol && { kind: CandidateOrTypeKind.Type, symbol }; } case InvocationKind.Contextual: - return { candidates: [invocation.signature], resolvedSignature: invocation.signature }; + return { kind: CandidateOrTypeKind.Candidate, candidates: [invocation.signature], resolvedSignature: invocation.signature }; default: return Debug.assertNever(invocation); } @@ -92,7 +109,7 @@ namespace ts.SignatureHelp { return !!containingList && contains(invocationChildren, containingList); } case SyntaxKind.LessThanToken: - return lessThanFollowsCalledExpression(startingToken, sourceFile, node.expression); + return containsPrecedingToken(startingToken, sourceFile, node.expression); default: return false; } @@ -114,12 +131,12 @@ namespace ts.SignatureHelp { })); } - function lessThanFollowsCalledExpression(startingToken: Node, sourceFile: SourceFile, calledExpression: Expression) { + function containsPrecedingToken(startingToken: Node, sourceFile: SourceFile, container: Node) { const precedingToken = Debug.assertDefined( findPrecedingToken(startingToken.getFullStart(), sourceFile, startingToken.parent, /*excludeJsdoc*/ true) ); - return rangeContainsRange(calledExpression, precedingToken); + return rangeContainsRange(container, precedingToken); } export interface ArgumentInfoForCompletions { @@ -457,6 +474,10 @@ namespace ts.SignatureHelp { return invocation.kind === InvocationKind.Call ? getInvokedExpression(invocation.node) : invocation.called; } + function getEnclosingDeclarationFromInvocation(invocation: Invocation): Node { + return invocation.kind === InvocationKind.Call ? invocation.node : invocation.kind === InvocationKind.TypeArgs ? invocation.called : invocation.node; + } + const signatureHelpNodeBuilderFlags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; function createSignatureHelpItems( candidates: ReadonlyArray, @@ -465,7 +486,7 @@ namespace ts.SignatureHelp { sourceFile: SourceFile, typeChecker: TypeChecker, ): SignatureHelpItems { - const enclosingDeclaration = invocation.kind === InvocationKind.Call ? invocation.node : invocation.kind === InvocationKind.TypeArgs ? invocation.called : invocation.node; + const enclosingDeclaration = getEnclosingDeclarationFromInvocation(invocation); const callTargetSymbol = invocation.kind === InvocationKind.Contextual ? invocation.symbol : typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)); const callTargetDisplayParts = callTargetSymbol ? symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : emptyArray; const items = candidates.map(candidateSignature => getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile)); @@ -480,11 +501,36 @@ namespace ts.SignatureHelp { return { items, applicableSpan, selectedItemIndex, argumentIndex, argumentCount }; } + function createTypeHelpItems( + symbol: Symbol, + { argumentCount, argumentsSpan: applicableSpan, invocation, argumentIndex }: ArgumentListInfo, + sourceFile: SourceFile, + checker: TypeChecker + ): SignatureHelpItems | undefined { + const typeParameters = checker.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); + if (!typeParameters) return undefined; + const items = [getTypeHelpItem(symbol, typeParameters, checker, getEnclosingDeclarationFromInvocation(invocation), sourceFile)]; + return { items, applicableSpan, selectedItemIndex: 0, argumentIndex, argumentCount }; + } + + function getTypeHelpItem(symbol: Symbol, typeParameters: ReadonlyArray, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem { + const typeSymbolDisplay = symbolToDisplayParts(checker, symbol); + + const printer = createPrinter({ removeComments: true }); + const parameters = typeParameters.map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); + + const documentation = symbol.getDocumentationComment(checker); + const tags = symbol.getJsDocTags(); + const prefixDisplayParts = [...typeSymbolDisplay, punctuationPart(SyntaxKind.LessThanToken)]; + return { isVariadic: false, prefixDisplayParts, suffixDisplayParts: [punctuationPart(SyntaxKind.GreaterThanToken)], separatorDisplayParts, parameters, documentation, tags }; + } + + const separatorDisplayParts: SymbolDisplayPart[] = [punctuationPart(SyntaxKind.CommaToken), spacePart()]; + function getSignatureHelpItem(candidateSignature: Signature, callTargetDisplayParts: ReadonlyArray, isTypeParameterList: boolean, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem { const { isVariadic, parameters, prefix, suffix } = (isTypeParameterList ? itemInfoForTypeParameters : itemInfoForParameters)(candidateSignature, checker, enclosingDeclaration, sourceFile); const prefixDisplayParts = [...callTargetDisplayParts, ...prefix]; const suffixDisplayParts = [...suffix, ...returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker)]; - const separatorDisplayParts = [punctuationPart(SyntaxKind.CommaToken), spacePart()]; const documentation = candidateSignature.getDocumentationComment(checker); const tags = candidateSignature.getJsDocTags(); return { isVariadic, prefixDisplayParts, suffixDisplayParts, separatorDisplayParts, parameters, documentation, tags }; diff --git a/tests/cases/fourslash/genericParameterHelpTypeReferences.ts b/tests/cases/fourslash/genericParameterHelpTypeReferences.ts index 5a477d23e56..a5dee833248 100644 --- a/tests/cases/fourslash/genericParameterHelpTypeReferences.ts +++ b/tests/cases/fourslash/genericParameterHelpTypeReferences.ts @@ -11,21 +11,37 @@ ////var x : testClass extends testClass; +//// +////interface I {} +////let i: I; +//// +////type Ty = T; +////let t: Ty; -// TODO: GH#26699 - -if (false) { - verify.signatureHelp( - { - marker: ["type1", "type2", "type3"], - text: "testClass", - parameterName: "T", - parameterSpan: "T extends IFoo", - }, - { - marker: "type4", - parameterName: "M", - parameterSpan: "M extends IFoo", - } - ); -} +verify.signatureHelp( + { + marker: ["type1", "type2", "type3"], + text: "testClass", + parameterName: "T", + parameterSpan: "T extends IFoo", + triggerReason: { kind: "characterTyped", triggerCharacter: "<" }, + }, + { + marker: "type4", + parameterName: "M", + parameterSpan: "M extends IFoo", + triggerReason: { kind: "characterTyped", triggerCharacter: "," }, + }, + { + marker: "interface", + text: "I", + parameterName: "T", + parameterSpan: "T", + }, + { + marker: "typeAlias", + text: "Ty", + parameterName: "T", + parameterSpan: "T", + }, +); From fc90b8f98b6dbf3a4fbae22a4c310382700fc099 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 28 Aug 2018 14:08:59 -0700 Subject: [PATCH 75/77] lazyConfiguredProjectsFromExternalProject as userpreference instead of command line option --- src/server/editorServices.ts | 17 ++++-- src/server/project.ts | 5 ++ src/server/protocol.ts | 1 + src/server/session.ts | 2 - src/services/types.ts | 1 + .../unittests/tsserverProjectSystem.ts | 61 +++++++++++++++++-- src/tsserver/server.ts | 2 - 7 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index c506c656de7..d941ce2f3f4 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -323,7 +323,6 @@ namespace ts.server { cancellationToken: HostCancellationToken; useSingleInferredProject: boolean; useInferredProjectPerProjectRoot: boolean; - lazyConfiguredProjectsFromExternalProject?: boolean; typingsInstaller: ITypingsInstaller; eventHandler?: ProjectServiceEventHandler; suppressDiagnosticEvents?: boolean; @@ -441,7 +440,6 @@ namespace ts.server { public readonly cancellationToken: HostCancellationToken; public readonly useSingleInferredProject: boolean; public readonly useInferredProjectPerProjectRoot: boolean; - private readonly lazyConfiguredProjectsFromExternalProject?: boolean; public readonly typingsInstaller: ITypingsInstaller; private readonly globalCacheLocationDirectoryPath: Path | undefined; public readonly throttleWaitMilliseconds?: number; @@ -467,7 +465,6 @@ namespace ts.server { this.cancellationToken = opts.cancellationToken; this.useSingleInferredProject = opts.useSingleInferredProject; this.useInferredProjectPerProjectRoot = opts.useInferredProjectPerProjectRoot; - this.lazyConfiguredProjectsFromExternalProject = opts.lazyConfiguredProjectsFromExternalProject; this.typingsInstaller = opts.typingsInstaller || nullTypingsInstaller; this.throttleWaitMilliseconds = opts.throttleWaitMilliseconds; this.eventHandler = opts.eventHandler; @@ -1989,7 +1986,19 @@ namespace ts.server { this.logger.info("Format host information updated"); } if (args.preferences) { + const { lazyConfiguredProjectsFromExternalProject } = this.hostConfiguration.preferences; this.hostConfiguration.preferences = { ...this.hostConfiguration.preferences, ...args.preferences }; + if (lazyConfiguredProjectsFromExternalProject && !this.hostConfiguration.preferences.lazyConfiguredProjectsFromExternalProject) { + // Load configured projects for external projects that are pending reload + this.configuredProjects.forEach(project => { + if (project.hasExternalProjectRef() && + project.pendingReload === ConfigFileProgramReloadLevel.Full && + !this.pendingProjectUpdates.has(project.getProjectName())) { + this.loadConfiguredProject(project); + project.updateGraph(); + } + }); + } } if (args.extraFileExtensions) { this.hostConfiguration.extraFileExtensions = args.extraFileExtensions; @@ -2642,7 +2651,7 @@ namespace ts.server { let project = this.findConfiguredProjectByProjectName(tsconfigFile); if (!project) { // errors are stored in the project, do not need to update the graph - project = this.lazyConfiguredProjectsFromExternalProject ? + project = this.getHostPreferences().lazyConfiguredProjectsFromExternalProject ? this.createConfiguredProjectWithDelayLoad(tsconfigFile) : this.createLoadAndUpdateConfiguredProject(tsconfigFile); } diff --git a/src/server/project.ts b/src/server/project.ts index ff2c504a54a..9589108c93d 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1520,6 +1520,11 @@ namespace ts.server { ) || false; } + /*@internal*/ + hasExternalProjectRef() { + return !!this.externalProjectRefCount; + } + getEffectiveTypeRoots() { return getEffectiveTypeRoots(this.getCompilationSettings(), this.directoryStructureHost) || []; } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 39a0045d97e..441c1316c99 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2823,6 +2823,7 @@ namespace ts.server.protocol { readonly includeCompletionsWithInsertText?: boolean; readonly importModuleSpecifierPreference?: "relative" | "non-relative"; readonly allowTextChangesInNewFiles?: boolean; + readonly lazyConfiguredProjectsFromExternalProject?: boolean; } export interface CompilerOptions { diff --git a/src/server/session.ts b/src/server/session.ts index 69328b4c73b..8d2fbe9e190 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -465,7 +465,6 @@ namespace ts.server { cancellationToken: ServerCancellationToken; useSingleInferredProject: boolean; useInferredProjectPerProjectRoot: boolean; - lazyConfiguredProjectsFromExternalProject?: boolean; typingsInstaller: ITypingsInstaller; byteLength: (buf: string, encoding?: string) => number; hrtime: (start?: number[]) => number[]; @@ -537,7 +536,6 @@ namespace ts.server { cancellationToken: this.cancellationToken, useSingleInferredProject: opts.useSingleInferredProject, useInferredProjectPerProjectRoot: opts.useInferredProjectPerProjectRoot, - lazyConfiguredProjectsFromExternalProject: opts.lazyConfiguredProjectsFromExternalProject, typingsInstaller: this.typingsInstaller, throttleWaitMilliseconds, eventHandler: this.eventHandler, diff --git a/src/services/types.ts b/src/services/types.ts index 51c98724c09..73a70c786b7 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -240,6 +240,7 @@ namespace ts { readonly includeCompletionsWithInsertText?: boolean; readonly importModuleSpecifierPreference?: "relative" | "non-relative"; readonly allowTextChangesInNewFiles?: boolean; + readonly lazyConfiguredProjectsFromExternalProject?: boolean; } /* @internal */ export const emptyOptions = {}; diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index 7ef838fd6ff..cb608d26dc6 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -656,7 +656,8 @@ namespace ts.projectSystem { }; const host = createServerHost([f1, config], { useCaseSensitiveFileNames: false }); - const service = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); + const service = createProjectService(host); + service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); const upperCaseConfigFilePath = combinePaths(getDirectoryPath(config.path).toUpperCase(), getBaseFileName(config.path)); service.openExternalProject({ projectFileName: "/a/b/project.csproj", @@ -670,7 +671,7 @@ namespace ts.projectSystem { checkProjectActualFiles(project, emptyArray); } else { - assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project pending to be reloaded + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded checkProjectActualFiles(project, [upperCaseConfigFilePath]); } @@ -2978,7 +2979,8 @@ namespace ts.projectSystem { }; const projectFileName = "/user/someuser/project/WebApplication6.csproj"; const host = createServerHost([libFile, site, configFile]); - const projectService = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); + const projectService = createProjectService(host); + projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); const externalProject: protocol.ExternalProject = { projectFileName, @@ -3341,8 +3343,12 @@ namespace ts.projectSystem { }; const host = createServerHost([file1, file2, tsconfig]); - const session = createSession(host, { lazyConfiguredProjectsFromExternalProject }); + const session = createSession(host); const projectService = session.getProjectService(); + session.executeCommandSeq({ + command: protocol.CommandTypes.Configure, + arguments: { preferences: { lazyConfiguredProjectsFromExternalProject } } + }); // Configure the deferred extension. const extraFileExtensions = [{ extension: ".deferred", scriptKind: ScriptKind.Deferred, isMixedContent: true }]; @@ -3995,7 +4001,8 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f1, f2]); - const projectService = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); + const projectService = createProjectService(host); + projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); // open external project const projectName = "/a/b/proj1"; @@ -4064,7 +4071,8 @@ namespace ts.projectSystem { content: "{}" }; const host = createServerHost([f1, cLib, cTsconfig, dLib, dTsconfig]); - const projectService = createProjectService(host, /*parameters*/ undefined, { lazyConfiguredProjectsFromExternalProject }); + const projectService = createProjectService(host); + projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); // open external project const projectName = "/a/b/proj1"; @@ -4233,6 +4241,47 @@ namespace ts.projectSystem { assert.isTrue(project.hasOpenRef()); // f assert.isFalse(project.isClosed()); }); + + it("handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", () => { + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1" + }; + const config = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({}) + }; + const projectFileName = "/a/b/project.csproj"; + const host = createServerHost([f1, config]); + const service = createProjectService(host); + service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: true } }); + service.openExternalProject({ + projectFileName, + rootFiles: toExternalFiles([f1.path, config.path]), + options: {} + }); + service.checkNumberOfProjects({ configuredProjects: 1 }); + const project = service.configuredProjects.get(config.path)!; + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded + checkProjectActualFiles(project, emptyArray); + + service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: false } }); + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded + checkProjectActualFiles(project, [config.path, f1.path]); + + service.closeExternalProject(projectFileName); + service.checkNumberOfProjects({}); + + service.openExternalProject({ + projectFileName, + rootFiles: toExternalFiles([f1.path, config.path]), + options: {} + }); + service.checkNumberOfProjects({ configuredProjects: 1 }); + const project2 = service.configuredProjects.get(config.path)!; + assert.equal(project2.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded + checkProjectActualFiles(project2, [config.path, f1.path]); + }); }); describe("tsserverProjectSystem prefer typings to js", () => { diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 6b8a146d8f3..3e5986e9408 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -499,7 +499,6 @@ namespace ts.server { cancellationToken, useSingleInferredProject, useInferredProjectPerProjectRoot, - lazyConfiguredProjectsFromExternalProject, typingsInstaller: typingsInstaller || nullTypingsInstaller, byteLength: Buffer.byteLength, hrtime: process.hrtime, @@ -938,7 +937,6 @@ namespace ts.server { const useSingleInferredProject = hasArgument("--useSingleInferredProject"); const useInferredProjectPerProjectRoot = hasArgument("--useInferredProjectPerProjectRoot"); - const lazyConfiguredProjectsFromExternalProject = hasArgument("--lazyConfiguredProjectsFromExternalProject"); const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); const suppressDiagnosticEvents = hasArgument("--suppressDiagnosticEvents"); const syntaxOnly = hasArgument("--syntaxOnly"); From 03bb5d170ec721897de059514dfa03d0a9da6c60 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 28 Aug 2018 15:47:17 -0700 Subject: [PATCH 76/77] Use protocol.UserPreferences in server to store UserPreferences --- src/server/editorServices.ts | 18 +++++++++--------- src/server/scriptInfo.ts | 6 +++--- src/server/session.ts | 6 +++--- .../reference/api/tsserverlibrary.d.ts | 15 +++++---------- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 63e8ac0a937..292c8d77fc6 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1,9 +1,3 @@ -namespace ts { - export interface UserPreferences { - readonly lazyConfiguredProjectsFromExternalProject?: boolean; - } -} - namespace ts.server { export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; /*@internal*/ @@ -224,9 +218,15 @@ namespace ts.server { } } + /*@internal*/ + export function convertUserPreferences(preferences: protocol.UserPreferences): UserPreferences { + const { lazyConfiguredProjectsFromExternalProject, ...userPreferences } = preferences; + return userPreferences; + } + export interface HostConfiguration { formatCodeOptions: FormatCodeSettings; - preferences: UserPreferences; + preferences: protocol.UserPreferences; hostInfo: string; extraFileExtensions?: FileExtensionInfo[]; } @@ -808,7 +808,7 @@ namespace ts.server { return info && info.getFormatCodeSettings() || this.hostConfiguration.formatCodeOptions; } - getPreferences(file: NormalizedPath): UserPreferences { + getPreferences(file: NormalizedPath): protocol.UserPreferences { const info = this.getScriptInfoForNormalizedPath(file); return info && info.getPreferences() || this.hostConfiguration.preferences; } @@ -817,7 +817,7 @@ namespace ts.server { return this.hostConfiguration.formatCodeOptions; } - getHostPreferences(): UserPreferences { + getHostPreferences(): protocol.UserPreferences { return this.hostConfiguration.preferences; } diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index c6992e91b88..085dd6d0eef 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -234,7 +234,7 @@ namespace ts.server { */ readonly containingProjects: Project[] = []; private formatSettings: FormatCodeSettings | undefined; - private preferences: UserPreferences | undefined; + private preferences: protocol.UserPreferences | undefined; /* @internal */ fileWatcher: FileWatcher | undefined; @@ -333,7 +333,7 @@ namespace ts.server { } getFormatCodeSettings(): FormatCodeSettings | undefined { return this.formatSettings; } - getPreferences(): UserPreferences | undefined { return this.preferences; } + getPreferences(): protocol.UserPreferences | undefined { return this.preferences; } attachToProject(project: Project): boolean { const isNew = !this.isAttached(project); @@ -432,7 +432,7 @@ namespace ts.server { } } - setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences | undefined): void { + setOptions(formatSettings: FormatCodeSettings, preferences: protocol.UserPreferences | undefined): void { if (formatSettings) { if (!this.formatSettings) { this.formatSettings = getDefaultFormatCodeSettings(this.host); diff --git a/src/server/session.ts b/src/server/session.ts index 8d2fbe9e190..6c3413601d0 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1423,7 +1423,7 @@ namespace ts.server { const position = this.getPosition(args, scriptInfo); const completions = project.getLanguageService().getCompletionsAtPosition(file, position, { - ...this.getPreferences(file), + ...convertUserPreferences(this.getPreferences(file)), triggerCharacter: args.triggerCharacter, includeExternalModuleExports: args.includeExternalModuleExports, includeInsertTextCompletions: args.includeInsertTextCompletions @@ -2352,7 +2352,7 @@ namespace ts.server { return this.projectService.getFormatCodeOptions(file); } - private getPreferences(file: NormalizedPath): UserPreferences { + private getPreferences(file: NormalizedPath): protocol.UserPreferences { return this.projectService.getPreferences(file); } @@ -2360,7 +2360,7 @@ namespace ts.server { return this.projectService.getHostFormatCodeOptions(); } - private getHostPreferences(): UserPreferences { + private getHostPreferences(): protocol.UserPreferences { return this.projectService.getHostPreferences(); } } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5ef55512f97..186f3eeff1c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7929,14 +7929,14 @@ declare namespace ts.server { getSnapshot(): IScriptSnapshot; private ensureRealPath; getFormatCodeSettings(): FormatCodeSettings | undefined; - getPreferences(): UserPreferences | undefined; + getPreferences(): protocol.UserPreferences | undefined; attachToProject(project: Project): boolean; isAttached(project: Project): boolean; detachFromProject(project: Project): void; detachAllProjects(): void; getDefaultProject(): Project; registerFileUpdate(): void; - setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences | undefined): void; + setOptions(formatSettings: FormatCodeSettings, preferences: protocol.UserPreferences | undefined): void; getLatestVersion(): string; saveTo(fileName: string): void; reloadFromFile(tempFileName?: NormalizedPath): boolean; @@ -8201,11 +8201,6 @@ declare namespace ts.server { setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void; } } -declare namespace ts { - interface UserPreferences { - readonly lazyConfiguredProjectsFromExternalProject?: boolean; - } -} declare namespace ts.server { const maxProgramSizeForNonTsFiles: number; const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground"; @@ -8319,7 +8314,7 @@ declare namespace ts.server { function convertScriptKindName(scriptKindName: protocol.ScriptKindName): ScriptKind.Unknown | ScriptKind.JS | ScriptKind.JSX | ScriptKind.TS | ScriptKind.TSX; interface HostConfiguration { formatCodeOptions: FormatCodeSettings; - preferences: UserPreferences; + preferences: protocol.UserPreferences; hostInfo: string; extraFileExtensions?: FileExtensionInfo[]; } @@ -8438,9 +8433,9 @@ declare namespace ts.server { */ private ensureProjectStructuresUptoDate; getFormatCodeOptions(file: NormalizedPath): FormatCodeSettings; - getPreferences(file: NormalizedPath): UserPreferences; + getPreferences(file: NormalizedPath): protocol.UserPreferences; getHostFormatCodeOptions(): FormatCodeSettings; - getHostPreferences(): UserPreferences; + getHostPreferences(): protocol.UserPreferences; private onSourceFileChanged; private handleDeletedFile; private onConfigChangedForConfiguredProject; From cff04e6050143696203f233407fce93f5086e89e Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 28 Aug 2018 16:43:14 -0700 Subject: [PATCH 77/77] Ensure JsonSourceFile has all the non-optional properties of SourceFile (#26162) * Ensure JsonSourceFile has all the non-optional properties of SourceFile * Set properties in parseSourceFile --- src/compiler/moduleSpecifiers.ts | 1 + src/compiler/parser.ts | 7 +++++-- src/compiler/types.ts | 10 ++++++++-- src/compiler/utilities.ts | 2 +- .../getEditsForFileRename_resolveJsonModule.ts | 17 +++++++++++++++++ 5 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 tests/cases/fourslash/getEditsForFileRename_resolveJsonModule.ts diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 18b2ea76b01..b34471a107a 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -429,6 +429,7 @@ namespace ts.moduleSpecifiers { } function removeExtensionAndIndexPostFix(fileName: string, ending: Ending, options: CompilerOptions): string { + if (fileExtensionIs(fileName, Extension.Json)) return fileName; const noExtension = removeFileExtension(fileName); switch (ending) { case Ending.Minimal: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 096c3f16354..e9eb953d22a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -515,7 +515,7 @@ namespace ts { performance.mark("beforeParse"); let result: SourceFile; if (languageVersion === ScriptTarget.JSON) { - result = Parser.parseJsonText(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes); + result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ScriptKind.JSON); } else { result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); @@ -689,8 +689,12 @@ namespace ts { if (scriptKind === ScriptKind.JSON) { const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); convertToObjectWorker(result, result.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); + result.referencedFiles = emptyArray; result.typeReferenceDirectives = emptyArray; + result.libReferenceDirectives = emptyArray; result.amdDependencies = emptyArray; + result.hasNoDefaultLib = false; + result.pragmas = emptyMap; return result; } @@ -7754,7 +7758,6 @@ namespace ts { } } - /*@internal*/ type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void; /*@internal*/ diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 10076014d96..54e19154376 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2632,7 +2632,7 @@ namespace ts { /* @internal */ ambientModuleNames: ReadonlyArray; /* @internal */ checkJsDirective?: CheckJsDirective; /* @internal */ version: string; - /* @internal */ pragmas: PragmaMap; + /* @internal */ pragmas: ReadonlyPragmaMap; /* @internal */ localJsxNamespace?: __String; /* @internal */ localJsxFactory?: EntityName; @@ -5588,13 +5588,19 @@ namespace ts { /* @internal */ export type PragmaPsuedoMapEntry = {[K in keyof PragmaPsuedoMap]: {name: K, args: PragmaPsuedoMap[K]}}[keyof PragmaPsuedoMap]; + /* @internal */ + export interface ReadonlyPragmaMap extends ReadonlyMap { + get(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]; + forEach(action: (value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void; + } + /** * A strongly-typed es6 map of pragma entries, the values of which are either a single argument * value (if only one was found), or an array of multiple argument values if the pragma is present * in multiple places */ /* @internal */ - export interface PragmaMap extends Map { + export interface PragmaMap extends Map, ReadonlyPragmaMap { set(key: TKey, value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]): this; get(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]; forEach(action: (value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index d04f921ec95..0e92bad7f55 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -16,7 +16,7 @@ namespace ts { namespace ts { export const emptyArray: never[] = [] as never[]; export const resolvingEmptyArray: never[] = [] as never[]; - export const emptyMap: ReadonlyMap = createMap(); + export const emptyMap = createMap() as ReadonlyMap & ReadonlyPragmaMap; export const emptyUnderscoreEscapedMap: ReadonlyUnderscoreEscapedMap = emptyMap as ReadonlyUnderscoreEscapedMap; export const externalHelpersModuleNameText = "tslib"; diff --git a/tests/cases/fourslash/getEditsForFileRename_resolveJsonModule.ts b/tests/cases/fourslash/getEditsForFileRename_resolveJsonModule.ts new file mode 100644 index 00000000000..3aa86c6aad0 --- /dev/null +++ b/tests/cases/fourslash/getEditsForFileRename_resolveJsonModule.ts @@ -0,0 +1,17 @@ +/// + +// @resolveJsonModule: true + +// @Filename: /a.ts +////import text from "./message.json"; + +// @Filename: /message.json +////{} + +verify.getEditsForFileRename({ + oldPath: "/a.ts", + newPath: "/src/a.ts", + newFileContents: { + "/a.ts": 'import text from "../message.json";', + }, +});