From d1459f7e9cab507d1e5c860faf79ae05d95dd38f Mon Sep 17 00:00:00 2001 From: vvakame Date: Tue, 25 Jul 2017 18:24:04 +0900 Subject: [PATCH 01/51] Add SpaceBetweenOpenParens rule --- src/services/formatting/rules.ts | 4 +++- .../fourslash/formattingSpaceBetweenParent.ts | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/formattingSpaceBetweenParent.ts diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 15bbf5041d3..2daf8d9d284 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -195,6 +195,7 @@ namespace ts.formatting { // Insert space after opening and before closing nonempty parenthesis public SpaceAfterOpenParen: Rule; public SpaceBeforeCloseParen: Rule; + public SpaceBetweenOpenParens: Rule; public NoSpaceBetweenParens: Rule; public NoSpaceAfterOpenParen: Rule; public NoSpaceBeforeCloseParen: Rule; @@ -457,6 +458,7 @@ namespace ts.formatting { // Insert space after opening and before closing nonempty parenthesis this.SpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); this.SpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); + this.SpaceBetweenOpenParens = new Rule(RuleDescriptor.create1(SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); this.NoSpaceBetweenParens = new Rule(RuleDescriptor.create1(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); this.NoSpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); this.NoSpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); @@ -544,7 +546,7 @@ namespace ts.formatting { this.SpaceAfterComma, this.NoSpaceAfterComma, this.SpaceAfterAnonymousFunctionKeyword, this.NoSpaceAfterAnonymousFunctionKeyword, this.SpaceAfterKeywordInControl, this.NoSpaceAfterKeywordInControl, - this.SpaceAfterOpenParen, this.SpaceBeforeCloseParen, this.NoSpaceBetweenParens, this.NoSpaceAfterOpenParen, this.NoSpaceBeforeCloseParen, + this.SpaceAfterOpenParen, this.SpaceBeforeCloseParen, this.SpaceBetweenOpenParens, this.NoSpaceBetweenParens, this.NoSpaceAfterOpenParen, this.NoSpaceBeforeCloseParen, this.SpaceAfterOpenBracket, this.SpaceBeforeCloseBracket, this.NoSpaceBetweenBrackets, this.NoSpaceAfterOpenBracket, this.NoSpaceBeforeCloseBracket, this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NoSpaceBetweenEmptyBraceBrackets, this.NoSpaceAfterOpenBrace, this.NoSpaceBeforeCloseBrace, this.SpaceAfterTemplateHeadAndMiddle, this.SpaceBeforeTemplateMiddleAndTail, this.NoSpaceAfterTemplateHeadAndMiddle, this.NoSpaceBeforeTemplateMiddleAndTail, diff --git a/tests/cases/fourslash/formattingSpaceBetweenParent.ts b/tests/cases/fourslash/formattingSpaceBetweenParent.ts new file mode 100644 index 00000000000..60ec632f59c --- /dev/null +++ b/tests/cases/fourslash/formattingSpaceBetweenParent.ts @@ -0,0 +1,14 @@ +/// + +/////*1*/foo(() => 1); +/////*2*/foo(1); +/////*3*/if((true)){} + +format.setOption("InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis", true); +format.document(); +goTo.marker("1"); +verify.currentLineContentIs("foo( () => 1 );"); +goTo.marker("2"); +verify.currentLineContentIs("foo( 1 );"); +goTo.marker("3"); +verify.currentLineContentIs("if ( ( true ) ) { }"); From 43981eaa48b70017666875d7c6f325fd9bf5aa6b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 25 Jul 2017 09:38:55 -0700 Subject: [PATCH 02/51] Use type param constraints for computed prop types --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c2f40c169dc..6da61b974f1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13330,10 +13330,13 @@ namespace ts { const links = getNodeLinks(node.expression); if (!links.resolvedType) { links.resolvedType = checkExpression(node.expression); + const t = links.resolvedType.flags & TypeFlags.TypeVariable ? + getBaseConstraintOfType(links.resolvedType) || emptyObjectType : + links.resolvedType; // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). - if (!isTypeAnyOrAllConstituentTypesHaveKind(links.resolvedType, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) { + if (!isTypeAnyOrAllConstituentTypesHaveKind(t, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) { error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } else { From 1fb6d349f1148ab87fbe43cabf099790a4657530 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 25 Jul 2017 09:39:54 -0700 Subject: [PATCH 03/51] Test:use type param constraints for computed prop types --- .../computedPropertyNames51_ES5.errors.txt | 15 +++++++++++++ .../reference/computedPropertyNames51_ES5.js | 21 +++++++++++++++++++ .../computedPropertyNames51_ES6.errors.txt | 15 +++++++++++++ .../reference/computedPropertyNames51_ES6.js | 20 ++++++++++++++++++ .../computedPropertyNames8_ES5.errors.txt | 5 +---- .../computedPropertyNames8_ES6.errors.txt | 5 +---- .../computedPropertyNames51_ES5.ts | 8 +++++++ .../computedPropertyNames51_ES6.ts | 9 ++++++++ 8 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/computedPropertyNames51_ES5.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNames51_ES5.js create mode 100644 tests/baselines/reference/computedPropertyNames51_ES6.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNames51_ES6.js create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES5.ts create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES6.ts diff --git a/tests/baselines/reference/computedPropertyNames51_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames51_ES5.errors.txt new file mode 100644 index 00000000000..3ee876feaed --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames51_ES5.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES5.ts(5,9): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES5.ts (1 errors) ==== + function f() { + var t: T; + var k: K; + var v = { + [t]: 0, + ~~~ +!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. + [k]: 1 + }; + } + \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames51_ES5.js b/tests/baselines/reference/computedPropertyNames51_ES5.js new file mode 100644 index 00000000000..9f138b37f3d --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames51_ES5.js @@ -0,0 +1,21 @@ +//// [computedPropertyNames51_ES5.ts] +function f() { + var t: T; + var k: K; + var v = { + [t]: 0, + [k]: 1 + }; +} + + +//// [computedPropertyNames51_ES5.js] +function f() { + var t; + var k; + var v = (_a = {}, + _a[t] = 0, + _a[k] = 1, + _a); + var _a; +} diff --git a/tests/baselines/reference/computedPropertyNames51_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames51_ES6.errors.txt new file mode 100644 index 00000000000..b85ae8f48d0 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames51_ES6.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES6.ts(5,9): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES6.ts (1 errors) ==== + function f() { + var t: T; + var k: K; + var v = { + [t]: 0, + ~~~ +!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. + [k]: 1 + }; + } + \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames51_ES6.js b/tests/baselines/reference/computedPropertyNames51_ES6.js new file mode 100644 index 00000000000..361af9cc15a --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames51_ES6.js @@ -0,0 +1,20 @@ +//// [computedPropertyNames51_ES6.ts] +function f() { + var t: T; + var k: K; + var v = { + [t]: 0, + [k]: 1 + }; +} + + +//// [computedPropertyNames51_ES6.js] +function f() { + var t; + var k; + var v = { + [t]: 0, + [k]: 1 + }; +} diff --git a/tests/baselines/reference/computedPropertyNames8_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames8_ES5.errors.txt index 9fbd14a92fb..56dbe16a523 100644 --- a/tests/baselines/reference/computedPropertyNames8_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames8_ES5.errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES5.ts(5,9): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES5.ts(6,9): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -==== tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES5.ts (2 errors) ==== +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES5.ts (1 errors) ==== function f() { var t: T; var u: U; @@ -11,7 +10,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES5.ts(6,9 ~~~ !!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. [u]: 1 - ~~~ -!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. }; } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames8_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames8_ES6.errors.txt index 22674a3992c..9996f35f063 100644 --- a/tests/baselines/reference/computedPropertyNames8_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames8_ES6.errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES6.ts(5,9): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES6.ts(6,9): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -==== tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES6.ts (2 errors) ==== +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES6.ts (1 errors) ==== function f() { var t: T; var u: U; @@ -11,7 +10,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames8_ES6.ts(6,9 ~~~ !!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. [u]: 1 - ~~~ -!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. }; } \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES5.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES5.ts new file mode 100644 index 00000000000..1d467245fb2 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES5.ts @@ -0,0 +1,8 @@ +function f() { + var t: T; + var k: K; + var v = { + [t]: 0, + [k]: 1 + }; +} diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES6.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES6.ts new file mode 100644 index 00000000000..ca209996c4c --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames51_ES6.ts @@ -0,0 +1,9 @@ +// @target: es6 +function f() { + var t: T; + var k: K; + var v = { + [t]: 0, + [k]: 1 + }; +} From 838fbdd9ca5902308af91ce6dee45e2a66f8c719 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 26 Jul 2017 16:28:24 -0700 Subject: [PATCH 04/51] Make isTypeOfKind delegate to isTypeAssignableTo This improves a number of error messages to do with adding 'null' or 'undefined' with other types. It also allows you to add two type parameters that both extend `number`. --- src/compiler/checker.ts | 89 ++++++++++--------- ...WithNullValueAndInvalidOperator.errors.txt | 66 +++++++------- ...orWithNullValueAndValidOperator.errors.txt | 60 ++++++------- ...thOnlyNullValueOrUndefinedValue.errors.txt | 38 +++----- ...ditionOperatorWithTypeParameter.errors.txt | 12 +-- ...ndefinedValueAndInvalidOperands.errors.txt | 66 +++++++------- ...hUndefinedValueAndValidOperator.errors.txt | 60 ++++++------- ...wiseNotOperatorWithAnyOtherType.errors.txt | 29 +++--- ...itionAssignmentLHSCanBeAssigned.errors.txt | 24 ++--- ...onAssignmentWithInvalidOperands.errors.txt | 36 ++++---- ...thAnyOtherTypeInvalidOperations.errors.txt | 56 ++++-------- .../deleteOperatorWithAnyOtherType.errors.txt | 29 +++--- ...thAnyOtherTypeInvalidOperations.errors.txt | 56 ++++-------- ...icalNotOperatorWithAnyOtherType.errors.txt | 29 +++--- tests/baselines/reference/null.errors.txt | 6 +- .../operatorAddNullUndefined.errors.txt | 86 ++++++++---------- .../plusOperatorWithAnyOtherType.errors.txt | 29 +++--- .../reference/typeParamExtendsNumber.js | 19 ++++ .../reference/typeParamExtendsNumber.symbols | 20 +++++ .../reference/typeParamExtendsNumber.types | 23 +++++ .../typeofOperatorWithAnyOtherType.errors.txt | 29 +++--- .../voidOperatorWithAnyOtherType.errors.txt | 29 +++--- .../cases/compiler/typeParamExtendsNumber.ts | 7 ++ 23 files changed, 429 insertions(+), 469 deletions(-) create mode 100644 tests/baselines/reference/typeParamExtendsNumber.js create mode 100644 tests/baselines/reference/typeParamExtendsNumber.symbols create mode 100644 tests/baselines/reference/typeParamExtendsNumber.types create mode 100644 tests/cases/compiler/typeParamExtendsNumber.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6da61b974f1..d1c18ef61d8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7526,11 +7526,11 @@ namespace ts { return getTypeOfSymbol(prop); } } - if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { + if (!(indexType.flags & TypeFlags.Nullable) && isTypeOfKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { if (isTypeAny(objectType)) { return anyType; } - const indexInfo = isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || + const indexInfo = isTypeOfKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || getIndexInfoOfType(objectType, IndexKind.String) || undefined; if (indexInfo) { @@ -11286,7 +11286,7 @@ namespace ts { (parent.parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent.parent).left === parent && !isAssignmentTarget(parent.parent) && - isTypeAnyOrAllConstituentTypesHaveKind(getTypeOfExpression((parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined); + isTypeOfKind(getTypeOfExpression((parent).argumentExpression), TypeFlags.NumberLike); return isLengthPushOrUnshift || isElementAssignment; } @@ -11458,7 +11458,7 @@ namespace ts { } else { const indexType = getTypeOfExpression(((node).left).argumentExpression); - if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike | TypeFlags.Undefined)) { + if (isTypeOfKind(indexType, TypeFlags.NumberLike)) { evolvedType = addEvolvingArrayElementType(evolvedType, (node).right); } } @@ -13290,11 +13290,7 @@ namespace ts { function isNumericComputedName(name: ComputedPropertyName): boolean { // It seems odd to consider an expression of type Any to result in a numeric name, // but this behavior is consistent with checkIndexedAccess - return isTypeAnyOrAllConstituentTypesHaveKind(checkComputedPropertyName(name), TypeFlags.NumberLike); - } - - function isTypeAnyOrAllConstituentTypesHaveKind(type: Type, kind: TypeFlags): boolean { - return isTypeAny(type) || isTypeOfKind(type, kind); + return isTypeOfKind(checkComputedPropertyName(name), TypeFlags.NumberLike); } function isInfinityOrNaNString(name: string | __String): boolean { @@ -13330,13 +13326,9 @@ namespace ts { const links = getNodeLinks(node.expression); if (!links.resolvedType) { links.resolvedType = checkExpression(node.expression); - const t = links.resolvedType.flags & TypeFlags.TypeVariable ? - getBaseConstraintOfType(links.resolvedType) || emptyObjectType : - links.resolvedType; - // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). - if (!isTypeAnyOrAllConstituentTypesHaveKind(t, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) { + if (links.resolvedType.flags & TypeFlags.Nullable || !isTypeOfKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } else { @@ -16821,7 +16813,7 @@ namespace ts { } function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean { - if (!isTypeAnyOrAllConstituentTypesHaveKind(type, TypeFlags.NumberLike)) { + if (!isTypeOfKind(type, TypeFlags.NumberLike)) { error(operand, diagnostic); return false; } @@ -16994,31 +16986,43 @@ namespace ts { return false; } - // Return true if type is of the given kind. A union type is of a given kind if all constituent types - // are of the given kind. An intersection type is of a given kind if at least one constituent type is - // of the given kind. - function isTypeOfKind(type: Type, kind: TypeFlags): boolean { - if (type.flags & kind) { + function isTypeOfKind(source: Type, kind: TypeFlags, excludeAny?: boolean) { + if (source.flags & kind) { return true; } - if (type.flags & TypeFlags.Union) { - const types = (type).types; - for (const t of types) { - if (!isTypeOfKind(t, kind)) { - return false; - } - } - return true; + if (excludeAny && source.flags & (TypeFlags.Any | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { + // TODO: The callers who want this should really handle these cases FIRST + return false; } - if (type.flags & TypeFlags.Intersection) { - const types = (type).types; - for (const t of types) { - if (isTypeOfKind(t, kind)) { - return true; - } - } + const targets = []; + if (kind & TypeFlags.NumberLike) { + targets.push(numberType); } - return false; + if (kind & TypeFlags.StringLike) { + targets.push(stringType); + } + if (kind & TypeFlags.BooleanLike) { + targets.push(booleanType); + } + if (kind & TypeFlags.Void) { + targets.push(voidType); + } + if (kind & TypeFlags.Never) { + targets.push(neverType); + } + if (kind & TypeFlags.Null) { + targets.push(nullType); + } + if (kind & TypeFlags.Undefined) { + targets.push(undefinedType); + } + if (kind & TypeFlags.ESSymbol) { + targets.push(esSymbolType); + } + if (kind & TypeFlags.NonPrimitive) { + targets.push(nonPrimitiveType); + } + return isTypeAssignableTo(source, getUnionType(targets)); } function isConstEnumObjectType(type: Type): boolean { @@ -17038,7 +17042,7 @@ namespace ts { // and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature. // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported - if (isTypeOfKind(leftType, TypeFlags.Primitive)) { + if (isTypeOfKind(leftType, TypeFlags.Primitive, /*excludeAny*/ true)) { error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } // NOTE: do not raise error if right is unknown as related error was already reported @@ -17064,7 +17068,7 @@ namespace ts { if (!(isTypeComparableTo(leftType, stringType) || isTypeOfKind(leftType, TypeFlags.NumberLike | TypeFlags.ESSymbol))) { error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } - if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeVariable | TypeFlags.NonPrimitive)) { + if (!isTypeOfKind(rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) { error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -17373,25 +17377,26 @@ namespace ts { return silentNeverType; } - if (!isTypeOfKind(leftType, TypeFlags.Any | TypeFlags.StringLike) && !isTypeOfKind(rightType, TypeFlags.Any | TypeFlags.StringLike)) { + if (!isTypeOfKind(leftType, TypeFlags.StringLike) && !isTypeOfKind(rightType, TypeFlags.StringLike)) { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); } let resultType: Type; - if (isTypeOfKind(leftType, TypeFlags.NumberLike) && isTypeOfKind(rightType, TypeFlags.NumberLike)) { + if (isTypeOfKind(leftType, TypeFlags.NumberLike, /*excludeAny*/ true) && isTypeOfKind(rightType, TypeFlags.NumberLike, /*excludeAny*/ true)) { // Operands of an enum type are treated as having the primitive type Number. // If both operands are of the Number primitive type, the result is of the Number primitive type. resultType = numberType; } else { - if (isTypeOfKind(leftType, TypeFlags.StringLike) || isTypeOfKind(rightType, TypeFlags.StringLike)) { + if (isTypeOfKind(leftType, TypeFlags.StringLike, /*excludeAny*/ true) || isTypeOfKind(rightType, TypeFlags.StringLike, /*excludeAny*/ true)) { // If one or both operands are of the String primitive type, the result is of the String primitive type. resultType = stringType; } else if (isTypeAny(leftType) || isTypeAny(rightType)) { // Otherwise, the result is of type Any. // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we. + // TODO: Reorder this to check for any (plus void/undefined/null) first resultType = leftType === unknownType || rightType === unknownType ? unknownType : anyType; } @@ -20317,7 +20322,7 @@ namespace ts { // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeVariable | TypeFlags.NonPrimitive)) { + if (!isTypeOfKind(rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } diff --git a/tests/baselines/reference/additionOperatorWithNullValueAndInvalidOperator.errors.txt b/tests/baselines/reference/additionOperatorWithNullValueAndInvalidOperator.errors.txt index 5f0d78c59d5..891fe86dcd1 100644 --- a/tests/baselines/reference/additionOperatorWithNullValueAndInvalidOperator.errors.txt +++ b/tests/baselines/reference/additionOperatorWithNullValueAndInvalidOperator.errors.txt @@ -1,14 +1,14 @@ -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(11,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(12,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(13,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(14,14): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(15,14): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(16,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(19,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(20,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(21,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(22,11): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(23,11): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(11,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'boolean'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(12,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'Object'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(13,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'void'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(14,10): error TS2365: Operator '+' cannot be applied to types 'boolean' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(15,10): error TS2365: Operator '+' cannot be applied to types 'Object' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(16,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'void'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(19,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'Number'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(20,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'true'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(21,10): error TS2365: Operator '+' cannot be applied to types 'null' and '{ a: string; }'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(22,11): error TS2365: Operator '+' cannot be applied to types 'null' and 'void'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts(23,11): error TS2365: Operator '+' cannot be applied to types 'null' and '() => void'. ==== tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndInvalidOperator.ts (11 errors) ==== @@ -23,37 +23,37 @@ tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOpe // null + boolean/Object var r1 = null + a; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'boolean'. var r2 = null + b; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'Object'. var r3 = null + c; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'void'. var r4 = a + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'boolean' and 'null'. var r5 = b + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'Object' and 'null'. var r6 = null + c; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'void'. // other cases var r7 = null + d; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'Number'. var r8 = null + true; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'true'. var r9 = null + { a: '' }; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and '{ a: string; }'. var r10 = null + foo(); - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'void'. var r11 = null + (() => { }); - ~~~~ -!!! error TS2531: Object is possibly 'null'. \ No newline at end of file + ~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and '() => void'. \ No newline at end of file diff --git a/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.errors.txt b/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.errors.txt index db01a42c8bd..b722fd1be46 100644 --- a/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.errors.txt +++ b/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.errors.txt @@ -1,13 +1,13 @@ -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(15,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(16,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(17,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(18,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(19,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(20,14): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(21,14): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(22,15): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(23,17): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(24,20): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(15,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'number'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(16,10): error TS2365: Operator '+' cannot be applied to types 'null' and '1'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(17,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'E'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(18,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'E.a'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(19,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'E.a'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(20,10): error TS2365: Operator '+' cannot be applied to types 'number' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(21,10): error TS2365: Operator '+' cannot be applied to types '1' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(22,11): error TS2365: Operator '+' cannot be applied to types 'E' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(23,11): error TS2365: Operator '+' cannot be applied to types 'E.a' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts(24,11): error TS2365: Operator '+' cannot be applied to types 'E.a' and 'null'. ==== tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithNullValueAndValidOperator.ts (10 errors) ==== @@ -26,35 +26,35 @@ tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOpe // null + number/enum var r3 = null + b; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'number'. var r4 = null + 1; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and '1'. var r5 = null + c; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'E'. var r6 = null + E.a; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'E.a'. var r7 = null + E['a']; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'E.a'. var r8 = b + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'number' and 'null'. var r9 = 1 + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types '1' and 'null'. var r10 = c + null - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E' and 'null'. var r11 = E.a + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E.a' and 'null'. var r12 = E['a'] + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E.a' and 'null'. // null + string var r13 = null + d; diff --git a/tests/baselines/reference/additionOperatorWithOnlyNullValueOrUndefinedValue.errors.txt b/tests/baselines/reference/additionOperatorWithOnlyNullValueOrUndefinedValue.errors.txt index aef66891be0..b4746ff1e68 100644 --- a/tests/baselines/reference/additionOperatorWithOnlyNullValueOrUndefinedValue.errors.txt +++ b/tests/baselines/reference/additionOperatorWithOnlyNullValueOrUndefinedValue.errors.txt @@ -1,32 +1,20 @@ -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(2,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(2,17): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(3,10): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(3,17): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(4,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(4,22): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(5,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(5,22): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(2,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(3,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(4,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts(5,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. -==== tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts (8 errors) ==== +==== tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithOnlyNullValueOrUndefinedValue.ts (4 errors) ==== // bug 819721 var r1 = null + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var r2 = null + undefined; - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var r3 = undefined + null; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'null'. var r4 = undefined + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. \ No newline at end of file + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. \ No newline at end of file diff --git a/tests/baselines/reference/additionOperatorWithTypeParameter.errors.txt b/tests/baselines/reference/additionOperatorWithTypeParameter.errors.txt index 478c4fdee3f..bdb81190b50 100644 --- a/tests/baselines/reference/additionOperatorWithTypeParameter.errors.txt +++ b/tests/baselines/reference/additionOperatorWithTypeParameter.errors.txt @@ -8,8 +8,8 @@ tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOpe tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(27,15): error TS2365: Operator '+' cannot be applied to types 'Object' and 'T'. tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(28,15): error TS2365: Operator '+' cannot be applied to types 'E' and 'T'. tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(29,15): error TS2365: Operator '+' cannot be applied to types 'void' and 'T'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(32,19): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(33,19): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(32,15): error TS2365: Operator '+' cannot be applied to types 'T' and 'null'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(33,15): error TS2365: Operator '+' cannot be applied to types 'T' and 'undefined'. tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(34,15): error TS2365: Operator '+' cannot be applied to types 'T' and 'T'. tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(35,15): error TS2365: Operator '+' cannot be applied to types 'T' and 'U'. tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithTypeParameter.ts(36,15): error TS2365: Operator '+' cannot be applied to types 'T' and '() => void'. @@ -69,11 +69,11 @@ tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOpe // other cases var r15 = t + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'T' and 'null'. var r16 = t + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'T' and 'undefined'. var r17 = t + t; ~~~~~ !!! error TS2365: Operator '+' cannot be applied to types 'T' and 'T'. diff --git a/tests/baselines/reference/additionOperatorWithUndefinedValueAndInvalidOperands.errors.txt b/tests/baselines/reference/additionOperatorWithUndefinedValueAndInvalidOperands.errors.txt index 06e8c67b105..6be41e81fd5 100644 --- a/tests/baselines/reference/additionOperatorWithUndefinedValueAndInvalidOperands.errors.txt +++ b/tests/baselines/reference/additionOperatorWithUndefinedValueAndInvalidOperands.errors.txt @@ -1,14 +1,14 @@ -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(11,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(12,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(13,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(14,14): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(15,14): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(16,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(19,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(20,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(21,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(22,11): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(23,11): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(11,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'boolean'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(12,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'Object'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(13,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'void'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(14,10): error TS2365: Operator '+' cannot be applied to types 'boolean' and 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(15,10): error TS2365: Operator '+' cannot be applied to types 'Object' and 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(16,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'void'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(19,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'Number'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(20,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'true'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(21,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and '{ a: string; }'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(22,11): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'void'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts(23,11): error TS2365: Operator '+' cannot be applied to types 'undefined' and '() => void'. ==== tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndInvalidOperands.ts (11 errors) ==== @@ -23,37 +23,37 @@ tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOpe // undefined + boolean/Object var r1 = undefined + a; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'boolean'. var r2 = undefined + b; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'Object'. var r3 = undefined + c; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'void'. var r4 = a + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'boolean' and 'undefined'. var r5 = b + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'Object' and 'undefined'. var r6 = undefined + c; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'void'. // other cases var r7 = undefined + d; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'Number'. var r8 = undefined + true; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'true'. var r9 = undefined + { a: '' }; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and '{ a: string; }'. var r10 = undefined + foo(); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'void'. var r11 = undefined + (() => { }); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. \ No newline at end of file + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and '() => void'. \ No newline at end of file diff --git a/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.errors.txt b/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.errors.txt index 04c0e2f3266..db2446aa3f9 100644 --- a/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.errors.txt +++ b/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.errors.txt @@ -1,13 +1,13 @@ -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(15,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(16,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(17,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(18,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(19,10): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(20,14): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(21,14): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(22,15): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(23,17): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(24,20): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(15,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'number'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(16,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and '1'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(17,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(18,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E.a'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(19,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E.a'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(20,10): error TS2365: Operator '+' cannot be applied to types 'number' and 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(21,10): error TS2365: Operator '+' cannot be applied to types '1' and 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(22,11): error TS2365: Operator '+' cannot be applied to types 'E' and 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(23,11): error TS2365: Operator '+' cannot be applied to types 'E.a' and 'undefined'. +tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts(24,11): error TS2365: Operator '+' cannot be applied to types 'E.a' and 'undefined'. ==== tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithUndefinedValueAndValidOperator.ts (10 errors) ==== @@ -26,35 +26,35 @@ tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOpe // undefined + number/enum var r3 = undefined + b; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'number'. var r4 = undefined + 1; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and '1'. var r5 = undefined + c; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E'. var r6 = undefined + E.a; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E.a'. var r7 = undefined + E['a']; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E.a'. var r8 = b + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'number' and 'undefined'. var r9 = 1 + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types '1' and 'undefined'. var r10 = c + undefined - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E' and 'undefined'. var r11 = E.a + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E.a' and 'undefined'. var r12 = E['a'] + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E.a' and 'undefined'. // undefined + string var r13 = undefined + d; diff --git a/tests/baselines/reference/bitwiseNotOperatorWithAnyOtherType.errors.txt b/tests/baselines/reference/bitwiseNotOperatorWithAnyOtherType.errors.txt index 411c7099f11..795a9f0863d 100644 --- a/tests/baselines/reference/bitwiseNotOperatorWithAnyOtherType.errors.txt +++ b/tests/baselines/reference/bitwiseNotOperatorWithAnyOtherType.errors.txt @@ -1,14 +1,11 @@ tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(34,24): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(35,24): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(46,26): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(46,33): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(47,26): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(47,33): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(48,26): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(48,38): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(46,26): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. +tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(47,26): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. +tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts(48,26): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. -==== tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts (8 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNotOperatorWithAnyOtherType.ts (5 errors) ==== // ~ operator on any type var ANY: any; @@ -59,20 +56,14 @@ tests/cases/conformance/expressions/unaryOperators/bitwiseNotOperator/bitwiseNot var ResultIsNumber14 = ~A.foo(); var ResultIsNumber15 = ~(ANY + ANY1); var ResultIsNumber16 = ~(null + undefined); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsNumber17 = ~(null + null); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsNumber18 = ~(undefined + undefined); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. // multiple ~ operators var ResultIsNumber19 = ~~ANY; diff --git a/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.errors.txt b/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.errors.txt index 08d8fd0c6d3..f7df532b20e 100644 --- a/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.errors.txt +++ b/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(32,7): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(33,7): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(39,7): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(40,7): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(32,1): error TS2365: Operator '+=' cannot be applied to types 'number' and 'null'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(33,1): error TS2365: Operator '+=' cannot be applied to types 'number' and 'undefined'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(39,1): error TS2365: Operator '+=' cannot be applied to types 'E' and 'null'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts(40,1): error TS2365: Operator '+=' cannot be applied to types 'E' and 'undefined'. ==== tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentLHSCanBeAssigned.ts (4 errors) ==== @@ -37,22 +37,22 @@ tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmen x3 += 0; x3 += E.a; x3 += null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'number' and 'null'. x3 += undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'number' and 'undefined'. var x4: E; x4 += a; x4 += 0; x4 += E.a; x4 += null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'E' and 'null'. x4 += undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'E' and 'undefined'. var x5: boolean; x5 += a; diff --git a/tests/baselines/reference/compoundAdditionAssignmentWithInvalidOperands.errors.txt b/tests/baselines/reference/compoundAdditionAssignmentWithInvalidOperands.errors.txt index 1812065f149..e570f2f6cf0 100644 --- a/tests/baselines/reference/compoundAdditionAssignmentWithInvalidOperands.errors.txt +++ b/tests/baselines/reference/compoundAdditionAssignmentWithInvalidOperands.errors.txt @@ -3,22 +3,22 @@ tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmen tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(8,1): error TS2365: Operator '+=' cannot be applied to types 'boolean' and '0'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(9,1): error TS2365: Operator '+=' cannot be applied to types 'boolean' and 'E.a'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(10,1): error TS2365: Operator '+=' cannot be applied to types 'boolean' and '{}'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(11,7): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(12,7): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(11,1): error TS2365: Operator '+=' cannot be applied to types 'boolean' and 'null'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(12,1): error TS2365: Operator '+=' cannot be applied to types 'boolean' and 'undefined'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(15,1): error TS2365: Operator '+=' cannot be applied to types '{}' and 'void'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(16,1): error TS2365: Operator '+=' cannot be applied to types '{}' and 'true'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(17,1): error TS2365: Operator '+=' cannot be applied to types '{}' and '0'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(18,1): error TS2365: Operator '+=' cannot be applied to types '{}' and 'E.a'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(19,1): error TS2365: Operator '+=' cannot be applied to types '{}' and '{}'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(20,7): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(21,7): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(20,1): error TS2365: Operator '+=' cannot be applied to types '{}' and 'null'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(21,1): error TS2365: Operator '+=' cannot be applied to types '{}' and 'undefined'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(24,1): error TS2365: Operator '+=' cannot be applied to types 'void' and 'void'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(25,1): error TS2365: Operator '+=' cannot be applied to types 'void' and 'true'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(26,1): error TS2365: Operator '+=' cannot be applied to types 'void' and '0'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(27,1): error TS2365: Operator '+=' cannot be applied to types 'void' and 'E.a'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(28,1): error TS2365: Operator '+=' cannot be applied to types 'void' and '{}'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(29,7): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(30,7): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(29,1): error TS2365: Operator '+=' cannot be applied to types 'void' and 'null'. +tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(30,1): error TS2365: Operator '+=' cannot be applied to types 'void' and 'undefined'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(33,1): error TS2365: Operator '+=' cannot be applied to types 'number' and 'void'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(34,1): error TS2365: Operator '+=' cannot be applied to types 'number' and 'true'. tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmentWithInvalidOperands.ts(35,1): error TS2365: Operator '+=' cannot be applied to types 'number' and '{}'. @@ -49,11 +49,11 @@ tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmen ~~~~~~~~ !!! error TS2365: Operator '+=' cannot be applied to types 'boolean' and '{}'. x1 += null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'boolean' and 'null'. x1 += undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'boolean' and 'undefined'. var x2: {}; x2 += a; @@ -72,11 +72,11 @@ tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmen ~~~~~~~~ !!! error TS2365: Operator '+=' cannot be applied to types '{}' and '{}'. x2 += null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types '{}' and 'null'. x2 += undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types '{}' and 'undefined'. var x3: void; x3 += a; @@ -95,11 +95,11 @@ tests/cases/conformance/expressions/assignmentOperator/compoundAdditionAssignmen ~~~~~~~~ !!! error TS2365: Operator '+=' cannot be applied to types 'void' and '{}'. x3 += null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'void' and 'null'. x3 += undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+=' cannot be applied to types 'void' and 'undefined'. var x4: number; x4 += a; diff --git a/tests/baselines/reference/decrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt b/tests/baselines/reference/decrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt index 33e31bc9478..ff54b4d52c6 100644 --- a/tests/baselines/reference/decrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt +++ b/tests/baselines/reference/decrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt @@ -19,27 +19,21 @@ tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOp tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(46,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(47,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,34): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,34): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,27): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,39): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,27): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(51,26): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(52,26): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(54,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(55,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,25): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,32): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,25): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,25): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,32): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,25): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,25): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,37): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,25): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(59,24): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(60,24): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(63,3): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. @@ -58,7 +52,7 @@ tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOp tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts(72,12): error TS1109: Expression expected. -==== tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts (58 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithAnyOtherTypeInvalidOperations.ts (52 errors) ==== // -- operator on any type var ANY1: any; var ANY2: any[] = ["", ""]; @@ -149,24 +143,18 @@ tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOp var ResultIsNumber19 = --(null + undefined); ~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsNumber20 = --(null + null); ~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsNumber21 = --(undefined + undefined); ~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. var ResultIsNumber22 = --obj1.x; ~~~~~~ !!! error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. @@ -183,24 +171,18 @@ tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOp var ResultIsNumber26 = (null + undefined)--; ~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsNumber27 = (null + null)--; ~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsNumber28 = (undefined + undefined)--; ~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. var ResultIsNumber29 = obj1.x--; ~~~~~~ !!! error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. diff --git a/tests/baselines/reference/deleteOperatorWithAnyOtherType.errors.txt b/tests/baselines/reference/deleteOperatorWithAnyOtherType.errors.txt index f2260b11036..5ea3f6135c1 100644 --- a/tests/baselines/reference/deleteOperatorWithAnyOtherType.errors.txt +++ b/tests/baselines/reference/deleteOperatorWithAnyOtherType.errors.txt @@ -9,15 +9,12 @@ tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperator tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(42,32): error TS2703: The operand of a delete operator must be a property reference. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(43,32): error TS2703: The operand of a delete operator must be a property reference. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(44,33): error TS2703: The operand of a delete operator must be a property reference. -tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(45,33): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(45,33): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(45,33): error TS2703: The operand of a delete operator must be a property reference. -tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(45,40): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(46,33): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(46,33): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(46,33): error TS2703: The operand of a delete operator must be a property reference. -tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(46,40): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(47,33): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(47,33): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(47,33): error TS2703: The operand of a delete operator must be a property reference. -tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(47,45): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(50,32): error TS2703: The operand of a delete operator must be a property reference. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(50,39): error TS2703: The operand of a delete operator must be a property reference. tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(51,32): error TS2703: The operand of a delete operator must be a property reference. @@ -28,7 +25,7 @@ tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperator tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts(57,8): error TS2703: The operand of a delete operator must be a property reference. -==== tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts (28 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperatorWithAnyOtherType.ts (25 errors) ==== // delete operator on any type var ANY: any; @@ -96,26 +93,20 @@ tests/cases/conformance/expressions/unaryOperators/deleteOperator/deleteOperator ~~~~~~~~~~ !!! error TS2703: The operand of a delete operator must be a property reference. var ResultIsBoolean17 = delete (null + undefined); - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. ~~~~~~~~~~~~~~~~ !!! error TS2703: The operand of a delete operator must be a property reference. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. var ResultIsBoolean18 = delete (null + null); - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. ~~~~~~~~~~~ !!! error TS2703: The operand of a delete operator must be a property reference. - ~~~~ -!!! error TS2531: Object is possibly 'null'. var ResultIsBoolean19 = delete (undefined + undefined); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2703: The operand of a delete operator must be a property reference. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. // multiple delete operators var ResultIsBoolean20 = delete delete ANY; diff --git a/tests/baselines/reference/incrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt b/tests/baselines/reference/incrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt index afdddab86a7..690f3391933 100644 --- a/tests/baselines/reference/incrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt +++ b/tests/baselines/reference/incrementOperatorWithAnyOtherTypeInvalidOperations.errors.txt @@ -19,27 +19,21 @@ tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOp tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(46,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(47,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,34): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(48,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,34): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(49,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,26): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,27): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,39): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(50,27): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(51,26): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(52,26): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(54,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(55,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,25): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,32): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(56,25): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,25): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,32): error TS2531: Object is possibly 'null'. +tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(57,25): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,24): error TS2357: The operand of an increment or decrement operator must be a variable or a property access. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,25): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,37): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(58,25): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(59,24): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(60,24): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(63,3): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. @@ -53,7 +47,7 @@ tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOp tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts(69,12): error TS1109: Expression expected. -==== tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts (53 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOperatorWithAnyOtherTypeInvalidOperations.ts (47 errors) ==== // ++ operator on any type var ANY1: any; var ANY2: any[] = [1, 2]; @@ -144,24 +138,18 @@ tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOp var ResultIsNumber19 = ++(null + undefined); ~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsNumber20 = ++(null + null); ~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsNumber21 = ++(undefined + undefined); ~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. var ResultIsNumber22 = ++obj1.x; ~~~~~~ !!! error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. @@ -178,24 +166,18 @@ tests/cases/conformance/expressions/unaryOperators/incrementOperator/incrementOp var ResultIsNumber26 = (null + undefined)++; ~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsNumber27 = (null + null)++; ~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsNumber28 = (undefined + undefined)++; ~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2357: The operand of an increment or decrement operator must be a variable or a property access. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. var ResultIsNumber29 = obj1.x++; ~~~~~~ !!! error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. diff --git a/tests/baselines/reference/logicalNotOperatorWithAnyOtherType.errors.txt b/tests/baselines/reference/logicalNotOperatorWithAnyOtherType.errors.txt index 0cb9869ca4c..ad951adf5f7 100644 --- a/tests/baselines/reference/logicalNotOperatorWithAnyOtherType.errors.txt +++ b/tests/baselines/reference/logicalNotOperatorWithAnyOtherType.errors.txt @@ -1,13 +1,10 @@ -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(45,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(45,34): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(46,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(46,34): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(47,27): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(47,39): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(45,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. +tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(46,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. +tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(47,27): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts(57,1): error TS2695: Left side of comma operator is unused and has no side effects. -==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts (7 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorWithAnyOtherType.ts (4 errors) ==== // ! operator on any type var ANY: any; @@ -53,20 +50,14 @@ tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNot var ResultIsBoolean15 = !A.foo(); var ResultIsBoolean16 = !(ANY + ANY1); var ResultIsBoolean17 = !(null + undefined); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsBoolean18 = !(null + null); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsBoolean19 = !(undefined + undefined); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. // multiple ! operators var ResultIsBoolean20 = !!ANY; diff --git a/tests/baselines/reference/null.errors.txt b/tests/baselines/reference/null.errors.txt index 6b05bfb94d1..ed6db12d99b 100644 --- a/tests/baselines/reference/null.errors.txt +++ b/tests/baselines/reference/null.errors.txt @@ -1,12 +1,12 @@ -tests/cases/compiler/null.ts(3,9): error TS2531: Object is possibly 'null'. +tests/cases/compiler/null.ts(3,7): error TS2365: Operator '+' cannot be applied to types '3' and 'null'. ==== tests/cases/compiler/null.ts (1 errors) ==== var x=null; var y=3+x; var z=3+null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types '3' and 'null'. class C { } function f() { diff --git a/tests/baselines/reference/operatorAddNullUndefined.errors.txt b/tests/baselines/reference/operatorAddNullUndefined.errors.txt index 871ef3fc98f..c6a74080394 100644 --- a/tests/baselines/reference/operatorAddNullUndefined.errors.txt +++ b/tests/baselines/reference/operatorAddNullUndefined.errors.txt @@ -1,68 +1,56 @@ -tests/cases/compiler/operatorAddNullUndefined.ts(2,10): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(2,17): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(3,10): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(3,17): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/operatorAddNullUndefined.ts(4,10): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/operatorAddNullUndefined.ts(4,22): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(5,10): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/operatorAddNullUndefined.ts(5,22): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/operatorAddNullUndefined.ts(6,14): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(7,14): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/operatorAddNullUndefined.ts(8,10): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(9,10): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/operatorAddNullUndefined.ts(14,11): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(15,11): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/operatorAddNullUndefined.ts(16,17): error TS2531: Object is possibly 'null'. -tests/cases/compiler/operatorAddNullUndefined.ts(17,17): error TS2532: Object is possibly 'undefined'. +tests/cases/compiler/operatorAddNullUndefined.ts(2,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. +tests/cases/compiler/operatorAddNullUndefined.ts(3,10): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. +tests/cases/compiler/operatorAddNullUndefined.ts(4,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'null'. +tests/cases/compiler/operatorAddNullUndefined.ts(5,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. +tests/cases/compiler/operatorAddNullUndefined.ts(6,10): error TS2365: Operator '+' cannot be applied to types '1' and 'null'. +tests/cases/compiler/operatorAddNullUndefined.ts(7,10): error TS2365: Operator '+' cannot be applied to types '1' and 'undefined'. +tests/cases/compiler/operatorAddNullUndefined.ts(8,10): error TS2365: Operator '+' cannot be applied to types 'null' and '1'. +tests/cases/compiler/operatorAddNullUndefined.ts(9,10): error TS2365: Operator '+' cannot be applied to types 'undefined' and '1'. +tests/cases/compiler/operatorAddNullUndefined.ts(14,11): error TS2365: Operator '+' cannot be applied to types 'null' and 'E'. +tests/cases/compiler/operatorAddNullUndefined.ts(15,11): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E'. +tests/cases/compiler/operatorAddNullUndefined.ts(16,11): error TS2365: Operator '+' cannot be applied to types 'E' and 'null'. +tests/cases/compiler/operatorAddNullUndefined.ts(17,11): error TS2365: Operator '+' cannot be applied to types 'E' and 'undefined'. -==== tests/cases/compiler/operatorAddNullUndefined.ts (16 errors) ==== +==== tests/cases/compiler/operatorAddNullUndefined.ts (12 errors) ==== enum E { x } var x1 = null + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var x2 = null + undefined; - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var x3 = undefined + null; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'null'. var x4 = undefined + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. var x5 = 1 + null; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types '1' and 'null'. var x6 = 1 + undefined; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types '1' and 'undefined'. var x7 = null + 1; - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and '1'. var x8 = undefined + 1; - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and '1'. var x9 = "test" + null; var x10 = "test" + undefined; var x11 = null + "test"; var x12 = undefined + "test"; var x13 = null + E.x - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'E'. var x14 = undefined + E.x - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'E'. var x15 = E.x + null - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E' and 'null'. var x16 = E.x + undefined - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. \ No newline at end of file + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'E' and 'undefined'. \ No newline at end of file diff --git a/tests/baselines/reference/plusOperatorWithAnyOtherType.errors.txt b/tests/baselines/reference/plusOperatorWithAnyOtherType.errors.txt index d693aaa17d9..561215bbd95 100644 --- a/tests/baselines/reference/plusOperatorWithAnyOtherType.errors.txt +++ b/tests/baselines/reference/plusOperatorWithAnyOtherType.errors.txt @@ -1,15 +1,12 @@ tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(34,24): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(35,24): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(46,26): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(46,33): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(47,26): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(47,33): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(48,26): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(48,38): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(46,26): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. +tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(47,26): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. +tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(48,26): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts(54,1): error TS2695: Left side of comma operator is unused and has no side effects. -==== tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts (9 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWithAnyOtherType.ts (6 errors) ==== // + operator on any type var ANY: any; @@ -60,20 +57,14 @@ tests/cases/conformance/expressions/unaryOperators/plusOperator/plusOperatorWith var ResultIsNumber15 = +A.foo(); var ResultIsNumber16 = +(ANY + ANY1); var ResultIsNumber17 = +(null + undefined); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsNumber18 = +(null + null); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsNumber19 = +(undefined + undefined); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. // miss assignment operators +ANY; diff --git a/tests/baselines/reference/typeParamExtendsNumber.js b/tests/baselines/reference/typeParamExtendsNumber.js new file mode 100644 index 00000000000..70548e79856 --- /dev/null +++ b/tests/baselines/reference/typeParamExtendsNumber.js @@ -0,0 +1,19 @@ +//// [typeParamExtendsNumber.ts] +function f() { + var t: T; + var v = { + [t]: 0 + } + return t + t; +} + + +//// [typeParamExtendsNumber.js] +function f() { + var t; + var v = (_a = {}, + _a[t] = 0, + _a); + return t + t; + var _a; +} diff --git a/tests/baselines/reference/typeParamExtendsNumber.symbols b/tests/baselines/reference/typeParamExtendsNumber.symbols new file mode 100644 index 00000000000..032f08bd58c --- /dev/null +++ b/tests/baselines/reference/typeParamExtendsNumber.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/typeParamExtendsNumber.ts === +function f() { +>f : Symbol(f, Decl(typeParamExtendsNumber.ts, 0, 0)) +>T : Symbol(T, Decl(typeParamExtendsNumber.ts, 0, 11)) + + var t: T; +>t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) +>T : Symbol(T, Decl(typeParamExtendsNumber.ts, 0, 11)) + + var v = { +>v : Symbol(v, Decl(typeParamExtendsNumber.ts, 2, 7)) + + [t]: 0 +>t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) + } + return t + t; +>t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) +>t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) +} + diff --git a/tests/baselines/reference/typeParamExtendsNumber.types b/tests/baselines/reference/typeParamExtendsNumber.types new file mode 100644 index 00000000000..9034e23ee23 --- /dev/null +++ b/tests/baselines/reference/typeParamExtendsNumber.types @@ -0,0 +1,23 @@ +=== tests/cases/compiler/typeParamExtendsNumber.ts === +function f() { +>f : () => number +>T : T + + var t: T; +>t : T +>T : T + + var v = { +>v : { [x: number]: number; } +>{ [t]: 0 } : { [x: number]: number; } + + [t]: 0 +>t : T +>0 : 0 + } + return t + t; +>t + t : number +>t : T +>t : T +} + diff --git a/tests/baselines/reference/typeofOperatorWithAnyOtherType.errors.txt b/tests/baselines/reference/typeofOperatorWithAnyOtherType.errors.txt index 3680b1be60f..9357cf4e4cc 100644 --- a/tests/baselines/reference/typeofOperatorWithAnyOtherType.errors.txt +++ b/tests/baselines/reference/typeofOperatorWithAnyOtherType.errors.txt @@ -1,9 +1,6 @@ -tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(46,32): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(46,39): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(47,32): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(47,39): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(48,32): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(48,44): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(46,32): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. +tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(47,32): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. +tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(48,32): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(58,1): error TS2695: Left side of comma operator is unused and has no side effects. tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(68,1): error TS7028: Unused label. tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(69,1): error TS7028: Unused label. @@ -14,7 +11,7 @@ tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperator tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts(74,1): error TS7028: Unused label. -==== tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts (14 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperatorWithAnyOtherType.ts (11 errors) ==== // typeof operator on any type var ANY: any; @@ -61,20 +58,14 @@ tests/cases/conformance/expressions/unaryOperators/typeofOperator/typeofOperator var ResultIsString15 = typeof A.foo(); var ResultIsString16 = typeof (ANY + ANY1); var ResultIsString17 = typeof (null + undefined); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsString18 = typeof (null + null); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsString19 = typeof (undefined + undefined); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. // multiple typeof operators var ResultIsString20 = typeof typeof ANY; diff --git a/tests/baselines/reference/voidOperatorWithAnyOtherType.errors.txt b/tests/baselines/reference/voidOperatorWithAnyOtherType.errors.txt index 5867a7ad6f5..7230f90c4f3 100644 --- a/tests/baselines/reference/voidOperatorWithAnyOtherType.errors.txt +++ b/tests/baselines/reference/voidOperatorWithAnyOtherType.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(46,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(46,34): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(47,27): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(47,34): error TS2531: Object is possibly 'null'. -tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(48,27): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(48,39): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(46,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. +tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(47,27): error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. +tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts(48,27): error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. -==== tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts (6 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWithAnyOtherType.ts (3 errors) ==== // void operator on any type var ANY: any; @@ -53,20 +50,14 @@ tests/cases/conformance/expressions/unaryOperators/voidOperator/voidOperatorWith var ResultIsAny15 = void A.foo(); var ResultIsAny16 = void (ANY + ANY1); var ResultIsAny17 = void (null + undefined); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'undefined'. var ResultIsAny18 = void (null + null); - ~~~~ -!!! error TS2531: Object is possibly 'null'. - ~~~~ -!!! error TS2531: Object is possibly 'null'. + ~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'null' and 'null'. var ResultIsAny19 = void (undefined + undefined); - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'undefined' and 'undefined'. // multiple void operators var ResultIsAny20 = void void ANY; diff --git a/tests/cases/compiler/typeParamExtendsNumber.ts b/tests/cases/compiler/typeParamExtendsNumber.ts new file mode 100644 index 00000000000..89b60c990a2 --- /dev/null +++ b/tests/cases/compiler/typeParamExtendsNumber.ts @@ -0,0 +1,7 @@ +function f() { + var t: T; + var v = { + [t]: 0 + } + return t + t; +} From b17bd97e71aee2c8b1bceb1ea94533b0d272aafe Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:29:09 +0200 Subject: [PATCH 05/51] Clean up --- src/compiler/checker.ts | 2 +- src/compiler/types.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4de0c7a2a6c..f3979d80441 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -481,7 +481,7 @@ namespace ts { Type, ResolvedBaseConstructorType, DeclaredType, - ResolvedReturnType + ResolvedReturnType, } const enum CheckMode { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 09f1b5cfcc5..fb7a6745d0c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4001,7 +4001,6 @@ namespace ts { ContainsBindingPattern = 1 << 23, ContainsYield = 1 << 24, ContainsHoistedDeclarationOrCompletion = 1 << 25, - ContainsDynamicImport = 1 << 26, // Please leave this as 1 << 29. From 99c662b5e4e2548ea6607c027ba7d2373ec2ff45 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:29:30 +0200 Subject: [PATCH 06/51] Add diagnostics --- src/compiler/diagnosticMessages.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3b4b0ddf667..fbd91f33905 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2196,6 +2196,10 @@ "category": "Error", "code": 2713 }, + "Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions.": { + "category": "Error", + "code": 2714 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", From b917eb022558af24b7a8e01f8bff4c249480f012 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:30:59 +0200 Subject: [PATCH 07/51] Adds optional catch parameter into the compiler --- src/compiler/binder.ts | 5 ++++- src/compiler/checker.ts | 12 ++++++++++++ src/compiler/emitter.ts | 10 ++++++---- src/compiler/parser.ts | 5 +++-- src/compiler/types.ts | 4 ++-- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2fbd0c3e141..aa42d1b251b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2921,7 +2921,10 @@ namespace ts { function computeCatchClause(node: CatchClause, subtreeFlags: TransformFlags) { let transformFlags = subtreeFlags; - if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) { + if (!node.variableDeclaration) { + transformFlags |= TransformFlags.AssertESNext; + } + else if (/* node.variableDeclaration && */ isBindingPattern(node.variableDeclaration.name)) { transformFlags |= TransformFlags.AssertES2015; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f3979d80441..8c7e7abef1c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20885,6 +20885,18 @@ namespace ts { } } } + else if (/* !catchClause.variableDeclaration && */ languageVersion < ScriptTarget.ESNext) { + const blockLocals = catchClause.block.locals; + debugger; + if (blockLocals) { + forEachKey(blockLocals, caughtName => { + if (caughtName === "_ignoredCatchParameter") { + const localSymbol = blockLocals.get(caughtName); + grammarErrorOnNode(localSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_ignoredCatchParameter_Compiler_uses_the_parameter_declaration_ignoredCatchParameter_to_bind_ignored_catched_exceptions); + } + }); + } + } checkBlock(catchClause.block); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index de08b209d3e..1c5194054ca 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2131,10 +2131,12 @@ namespace ts { function emitCatchClause(node: CatchClause) { const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emit(node.variableDeclaration); - writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); - write(" "); + if (node.variableDeclaration) { + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emit(node.variableDeclaration); + writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + write(" "); + } emit(node.block); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 34670cd2834..12c516c88b0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4778,11 +4778,12 @@ namespace ts { function parseCatchClause(): CatchClause { const result = createNode(SyntaxKind.CatchClause); parseExpected(SyntaxKind.CatchKeyword); - if (parseExpected(SyntaxKind.OpenParenToken)) { + + if (parseOptional(SyntaxKind.OpenParenToken)) { result.variableDeclaration = parseVariableDeclaration(); + parseExpected(SyntaxKind.CloseParenToken); } - parseExpected(SyntaxKind.CloseParenToken); result.block = parseBlock(/*ignoreMissingOpenBrace*/ false); return finishNode(result); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fb7a6745d0c..5210b89eb1f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1807,8 +1807,8 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; - variableDeclaration: VariableDeclaration; + parent: TryStatement; + variableDeclaration?: VariableDeclaration; block: Block; } From 148a494c90d0849ad94de02f34975dd8960e22be Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:31:31 +0200 Subject: [PATCH 08/51] Adds transformers for ignored catch parameter --- src/compiler/transformers/es2015.ts | 2 +- src/compiler/transformers/esnext.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index f97de018d4a..ebfd0b0069f 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3173,7 +3173,7 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes); let updated: CatchClause; - if (isBindingPattern(node.variableDeclaration.name)) { + if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) { const temp = createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = createVariableDeclaration(temp); setTextRange(newVariableDeclaration, node.variableDeclaration); diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 3d884001932..597b9d55b16 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -101,6 +101,8 @@ namespace ts { return visitExpressionStatement(node as ExpressionStatement); case SyntaxKind.ParenthesizedExpression: return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue); + case SyntaxKind.CatchClause: + return visitCatchClause(node as CatchClause); default: return visitEachChild(node, visitor, context); } @@ -212,6 +214,13 @@ namespace ts { return visitEachChild(node, noDestructuringValue ? visitorNoDestructuringValue : visitor, context); } + function visitCatchClause(node: CatchClause): CatchClause { + if (!node.variableDeclaration) { + return updateCatchClause(node, createVariableDeclaration("_ignoredCatchParameter"), node.block); + } + return visitEachChild(node, visitor, context); + } + /** * Visits a BinaryExpression that contains a destructuring assignment. * From e349943c07e4f0ca52110d109705ba4797c86e74 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:32:39 +0200 Subject: [PATCH 09/51] Add tests --- .../statements/tryStatements/invalidTryStatements.ts | 5 +++++ .../statements/tryStatements/tryStatements.ts | 11 +++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts index c838cf45f69..6ecdfe10656 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts @@ -8,5 +8,10 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } + + + try { } catch { + let _ignoredCatchParameter; // Should error since we downlevel emit this variable. + } } diff --git a/tests/cases/conformance/statements/tryStatements/tryStatements.ts b/tests/cases/conformance/statements/tryStatements/tryStatements.ts index 691c046d6d1..42f549e6911 100644 --- a/tests/cases/conformance/statements/tryStatements/tryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/tryStatements.ts @@ -1,11 +1,10 @@ -function fn() { - try { - } catch (x) { - var x: any; - } +function fn() { + try { } catch { } + + try { } catch (x) { var x: any; } try { } finally { } - try { }catch(z){ } finally { } + try { } catch(z) { } finally { } } \ No newline at end of file From 90ea10e45e7fb49f1fe3eb26e4f5bbc634256d07 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:33:22 +0200 Subject: [PATCH 10/51] Accept baselines --- ...tructorWithIncompleteTypeAnnotation.errors.txt | 4 ++-- .../constructorWithIncompleteTypeAnnotation.js | 2 +- .../emitter.ignoredCatchParameter.esnext.js | 11 +++++++++++ .../emitter.ignoredCatchParameter.esnext.symbols | 7 +++++++ .../emitter.ignoredCatchParameter.esnext.types | 7 +++++++ .../reference/invalidTryStatements.errors.txt | 10 +++++++++- tests/baselines/reference/invalidTryStatements.js | 9 +++++++++ .../reference/invalidTryStatements2.errors.txt | 5 +---- .../baselines/reference/invalidTryStatements2.js | 2 +- tests/baselines/reference/tryStatements.js | 13 ++++++------- tests/baselines/reference/tryStatements.symbols | 15 ++++++--------- tests/baselines/reference/tryStatements.types | 9 +++------ 12 files changed, 63 insertions(+), 31 deletions(-) create mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js create mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols create mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt index 1d37b20a3b3..708f175c002 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt @@ -34,7 +34,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(138,13): error T tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(141,32): error TS1005: '{' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(143,13): error TS1005: 'try' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,24): error TS1109: Expression expected. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,30): error TS1005: '(' expected. +tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,30): error TS1005: '{' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,31): error TS2304: Cannot find name 'Property'. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(166,13): error TS2365: Operator '+=' cannot be applied to types 'number' and 'void'. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(180,40): error TS2447: The '^' operator is not allowed for boolean types. Consider using '!==' instead. @@ -323,7 +323,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(261,1): error TS ~~~~~ !!! error TS1109: Expression expected. ~ -!!! error TS1005: '(' expected. +!!! error TS1005: '{' expected. ~~~~~~~~ !!! error TS2304: Cannot find name 'Property'. retVal += c.Member(); diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js index 8e9dc6da688..013692a4889 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js @@ -441,7 +441,7 @@ var BasicFeatures = (function () { var xx = c; retVal += ; try { } - catch () { } + catch (_ignoredCatchParameter) { } Property; retVal += c.Member(); retVal += xx.Foo() ? 0 : 1; diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js new file mode 100644 index 00000000000..0f9254fd3cb --- /dev/null +++ b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js @@ -0,0 +1,11 @@ +//// [emitter.ignoredCatchParameter.esnext.ts] +function fn() { + try {} catch {} +} + + +//// [emitter.ignoredCatchParameter.esnext.js] +function fn() { + try { } + catch { } +} diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols new file mode 100644 index 00000000000..78838a33011 --- /dev/null +++ b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === +function fn() { +>fn : Symbol(fn, Decl(emitter.ignoredCatchParameter.esnext.ts, 0, 0)) + + try {} catch {} +} + diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types new file mode 100644 index 00000000000..06bf4ab2682 --- /dev/null +++ b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types @@ -0,0 +1,7 @@ +=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === +function fn() { +>fn : () => void + + try {} catch {} +} + diff --git a/tests/baselines/reference/invalidTryStatements.errors.txt b/tests/baselines/reference/invalidTryStatements.errors.txt index a2f8a7bac0c..08dc5f1dfa0 100644 --- a/tests/baselines/reference/invalidTryStatements.errors.txt +++ b/tests/baselines/reference/invalidTryStatements.errors.txt @@ -1,9 +1,10 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(8,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(9,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): error TS1196: Catch clause variable cannot have a type annotation. +tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(14,13): error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (3 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (4 errors) ==== function fn() { try { } catch (x) { @@ -20,6 +21,13 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): try { } catch (y: string) { } ~~~~~~ !!! error TS1196: Catch clause variable cannot have a type annotation. + + + try { } catch { + let _ignoredCatchParameter; // Should error since we downlevel emit this variable. + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. + } } \ No newline at end of file diff --git a/tests/baselines/reference/invalidTryStatements.js b/tests/baselines/reference/invalidTryStatements.js index 343ad6e0584..1436c83ae07 100644 --- a/tests/baselines/reference/invalidTryStatements.js +++ b/tests/baselines/reference/invalidTryStatements.js @@ -9,6 +9,11 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } + + + try { } catch { + let _ignoredCatchParameter; // Should error since we downlevel emit this variable. + } } @@ -27,4 +32,8 @@ function fn() { catch (a) { } try { } catch (y) { } + try { } + catch (_ignoredCatchParameter) { + var _ignoredCatchParameter = void 0; // Should error since we downlevel emit this variable. + } } diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index f2e88cfdc22..e1d285b8c88 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -1,4 +1,3 @@ -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(3,13): error TS1005: '(' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(6,5): error TS1005: 'try' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(12,5): error TS1005: 'try' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(13,5): error TS1005: 'try' expected. @@ -6,12 +5,10 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(26,5): error TS1005: 'try' expected. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (6 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (5 errors) ==== function fn() { try { } catch { // syntax error, missing '(x)' - ~ -!!! error TS1005: '(' expected. } catch(x) { } // error missing try diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 118b607817a..44fb6bb7071 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -32,7 +32,7 @@ function fn2() { function fn() { try { } - catch () { + catch (_ignoredCatchParameter) { } try { } diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index 723014c1b52..da126cbcc6c 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -1,20 +1,19 @@ //// [tryStatements.ts] function fn() { - try { + try { } catch { } - } catch (x) { - var x: any; - } + try { } catch (x) { var x: any; } try { } finally { } - try { }catch(z){ } finally { } + try { } catch(z) { } finally { } } //// [tryStatements.js] function fn() { - try { - } + try { } + catch (_ignoredCatchParameter) { } + try { } catch (x) { var x; } diff --git a/tests/baselines/reference/tryStatements.symbols b/tests/baselines/reference/tryStatements.symbols index 945ca2d9d88..cc014772665 100644 --- a/tests/baselines/reference/tryStatements.symbols +++ b/tests/baselines/reference/tryStatements.symbols @@ -2,17 +2,14 @@ function fn() { >fn : Symbol(fn, Decl(tryStatements.ts, 0, 0)) - try { + try { } catch { } - } catch (x) { ->x : Symbol(x, Decl(tryStatements.ts, 3, 13)) - - var x: any; ->x : Symbol(x, Decl(tryStatements.ts, 4, 11)) - } + try { } catch (x) { var x: any; } +>x : Symbol(x, Decl(tryStatements.ts, 3, 19)) +>x : Symbol(x, Decl(tryStatements.ts, 3, 27)) try { } finally { } - try { }catch(z){ } finally { } ->z : Symbol(z, Decl(tryStatements.ts, 9, 17)) + try { } catch(z) { } finally { } +>z : Symbol(z, Decl(tryStatements.ts, 7, 18)) } diff --git a/tests/baselines/reference/tryStatements.types b/tests/baselines/reference/tryStatements.types index 07bc3997d83..49e89dd79c0 100644 --- a/tests/baselines/reference/tryStatements.types +++ b/tests/baselines/reference/tryStatements.types @@ -2,17 +2,14 @@ function fn() { >fn : () => void - try { + try { } catch { } - } catch (x) { + try { } catch (x) { var x: any; } >x : any - - var x: any; >x : any - } try { } finally { } - try { }catch(z){ } finally { } + try { } catch(z) { } finally { } >z : any } From c65e5a1d137a99de621a91ed9a2507beb8a6477f Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 11:03:43 +0200 Subject: [PATCH 11/51] Removes valid test cases from invalid test case file --- src/compiler/types.ts | 2 +- .../reference/invalidTryStatements2.errors.txt | 12 ++++-------- tests/baselines/reference/invalidTryStatements2.js | 8 -------- .../tryStatements/invalidTryStatements2.ts | 4 ---- 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5210b89eb1f..c97020c1142 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1807,7 +1807,7 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent: TryStatement; + parent?: TryStatement; // We parse missing try statements variableDeclaration?: VariableDeclaration; block: Block; } diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index e1d285b8c88..38c30fb32ab 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -1,16 +1,12 @@ -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(6,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(12,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(13,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(2,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(8,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(9,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(18,5): error TS1005: 'try' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(26,5): error TS1005: 'try' expected. ==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (5 errors) ==== function fn() { - try { - } catch { // syntax error, missing '(x)' - } - catch(x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 44fb6bb7071..45b150b4094 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -1,9 +1,5 @@ //// [invalidTryStatements2.ts] function fn() { - try { - } catch { // syntax error, missing '(x)' - } - catch(x) { } // error missing try finally{ } // potential error; can be absorbed by the 'catch' @@ -30,10 +26,6 @@ function fn2() { //// [invalidTryStatements2.js] function fn() { - try { - } - catch (_ignoredCatchParameter) { - } try { } catch (x) { } // error missing try diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts index 6937e509845..205d6f3f193 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts @@ -1,8 +1,4 @@ function fn() { - try { - } catch { // syntax error, missing '(x)' - } - catch(x) { } // error missing try finally{ } // potential error; can be absorbed by the 'catch' From de38ef74a4bfe79656a21a6d78f2a7802d2e8324 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 11:06:11 +0200 Subject: [PATCH 12/51] remove debugger --- src/compiler/checker.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8c7e7abef1c..6d07025a41f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20887,7 +20887,6 @@ namespace ts { } else if (/* !catchClause.variableDeclaration && */ languageVersion < ScriptTarget.ESNext) { const blockLocals = catchClause.block.locals; - debugger; if (blockLocals) { forEachKey(blockLocals, caughtName => { if (caughtName === "_ignoredCatchParameter") { From 58c8a2c03dcbfda2430039a623c0a13ae1425ea4 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 11:32:17 +0200 Subject: [PATCH 13/51] adds test for try-catch-finally --- tests/baselines/reference/tryStatements.js | 5 +++++ tests/baselines/reference/tryStatements.symbols | 4 +++- tests/baselines/reference/tryStatements.types | 2 ++ .../conformance/statements/tryStatements/tryStatements.ts | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index da126cbcc6c..d99d0f91b35 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -6,6 +6,8 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } } @@ -20,6 +22,9 @@ function fn() { try { } finally { } try { } + catch (_ignoredCatchParameter) { } + finally { } + try { } catch (z) { } finally { } } diff --git a/tests/baselines/reference/tryStatements.symbols b/tests/baselines/reference/tryStatements.symbols index cc014772665..5bcb897d193 100644 --- a/tests/baselines/reference/tryStatements.symbols +++ b/tests/baselines/reference/tryStatements.symbols @@ -10,6 +10,8 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } ->z : Symbol(z, Decl(tryStatements.ts, 7, 18)) +>z : Symbol(z, Decl(tryStatements.ts, 9, 18)) } diff --git a/tests/baselines/reference/tryStatements.types b/tests/baselines/reference/tryStatements.types index 49e89dd79c0..cdc0a7c981d 100644 --- a/tests/baselines/reference/tryStatements.types +++ b/tests/baselines/reference/tryStatements.types @@ -10,6 +10,8 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } >z : any } diff --git a/tests/cases/conformance/statements/tryStatements/tryStatements.ts b/tests/cases/conformance/statements/tryStatements/tryStatements.ts index 42f549e6911..3fb395ca0ea 100644 --- a/tests/cases/conformance/statements/tryStatements/tryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/tryStatements.ts @@ -6,5 +6,7 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } } \ No newline at end of file From 81fb3f702a9322139d433570d01f1dcde9abb729 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 1 Aug 2017 22:10:12 +0200 Subject: [PATCH 14/51] Addresses CR feedback --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 11 ----------- src/compiler/diagnosticMessages.json | 4 ---- src/compiler/transformers/es2015.ts | 3 ++- src/compiler/transformers/esnext.ts | 2 +- src/compiler/types.ts | 2 +- .../statements/tryStatements/invalidTryStatements.ts | 5 ----- 7 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index aa42d1b251b..45880f855fd 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2924,7 +2924,7 @@ namespace ts { if (!node.variableDeclaration) { transformFlags |= TransformFlags.AssertESNext; } - else if (/* node.variableDeclaration && */ isBindingPattern(node.variableDeclaration.name)) { + else if (isBindingPattern(node.variableDeclaration.name)) { transformFlags |= TransformFlags.AssertES2015; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6d07025a41f..f3979d80441 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20885,17 +20885,6 @@ namespace ts { } } } - else if (/* !catchClause.variableDeclaration && */ languageVersion < ScriptTarget.ESNext) { - const blockLocals = catchClause.block.locals; - if (blockLocals) { - forEachKey(blockLocals, caughtName => { - if (caughtName === "_ignoredCatchParameter") { - const localSymbol = blockLocals.get(caughtName); - grammarErrorOnNode(localSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_ignoredCatchParameter_Compiler_uses_the_parameter_declaration_ignoredCatchParameter_to_bind_ignored_catched_exceptions); - } - }); - } - } checkBlock(catchClause.block); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index fbd91f33905..3b4b0ddf667 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2196,10 +2196,6 @@ "category": "Error", "code": 2713 }, - "Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions.": { - "category": "Error", - "code": 2714 - }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index ebfd0b0069f..41e68baa523 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3173,7 +3173,8 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes); let updated: CatchClause; - if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) { + Debug.assert(!!node.variableDeclaration, "Catch clauses should always be present when downleveling ES2015 code."); + if (isBindingPattern(node.variableDeclaration.name)) { const temp = createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = createVariableDeclaration(temp); setTextRange(newVariableDeclaration, node.variableDeclaration); diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 597b9d55b16..11e79ae9eeb 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -216,7 +216,7 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { if (!node.variableDeclaration) { - return updateCatchClause(node, createVariableDeclaration("_ignoredCatchParameter"), node.block); + return updateCatchClause(node, createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)), node.block); } return visitEachChild(node, visitor, context); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c97020c1142..9cf8e6fdf00 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1807,7 +1807,7 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; // We parse missing try statements + parent?: TryStatement; // We make this optional to parse missing try statements variableDeclaration?: VariableDeclaration; block: Block; } diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts index 6ecdfe10656..c838cf45f69 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts @@ -8,10 +8,5 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } - - - try { } catch { - let _ignoredCatchParameter; // Should error since we downlevel emit this variable. - } } From dbdbb05c66d3255e0b13a94a24c5ccb46a71ad08 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 1 Aug 2017 22:23:34 +0200 Subject: [PATCH 15/51] Accept baselines --- .../constructorWithIncompleteTypeAnnotation.js | 2 +- .../reference/invalidTryStatements.errors.txt | 10 +--------- tests/baselines/reference/invalidTryStatements.js | 9 --------- tests/baselines/reference/tryStatements.js | 4 ++-- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js index 013692a4889..f33c4b6d316 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js @@ -441,7 +441,7 @@ var BasicFeatures = (function () { var xx = c; retVal += ; try { } - catch (_ignoredCatchParameter) { } + catch (_a) { } Property; retVal += c.Member(); retVal += xx.Foo() ? 0 : 1; diff --git a/tests/baselines/reference/invalidTryStatements.errors.txt b/tests/baselines/reference/invalidTryStatements.errors.txt index 08dc5f1dfa0..a2f8a7bac0c 100644 --- a/tests/baselines/reference/invalidTryStatements.errors.txt +++ b/tests/baselines/reference/invalidTryStatements.errors.txt @@ -1,10 +1,9 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(8,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(9,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): error TS1196: Catch clause variable cannot have a type annotation. -tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(14,13): error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (4 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (3 errors) ==== function fn() { try { } catch (x) { @@ -21,13 +20,6 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(14,13): try { } catch (y: string) { } ~~~~~~ !!! error TS1196: Catch clause variable cannot have a type annotation. - - - try { } catch { - let _ignoredCatchParameter; // Should error since we downlevel emit this variable. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. - } } \ No newline at end of file diff --git a/tests/baselines/reference/invalidTryStatements.js b/tests/baselines/reference/invalidTryStatements.js index 1436c83ae07..343ad6e0584 100644 --- a/tests/baselines/reference/invalidTryStatements.js +++ b/tests/baselines/reference/invalidTryStatements.js @@ -9,11 +9,6 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } - - - try { } catch { - let _ignoredCatchParameter; // Should error since we downlevel emit this variable. - } } @@ -32,8 +27,4 @@ function fn() { catch (a) { } try { } catch (y) { } - try { } - catch (_ignoredCatchParameter) { - var _ignoredCatchParameter = void 0; // Should error since we downlevel emit this variable. - } } diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index d99d0f91b35..fa5c9b5c92b 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -14,7 +14,7 @@ function fn() { //// [tryStatements.js] function fn() { try { } - catch (_ignoredCatchParameter) { } + catch (_a) { } try { } catch (x) { var x; @@ -22,7 +22,7 @@ function fn() { try { } finally { } try { } - catch (_ignoredCatchParameter) { } + catch (_b) { } finally { } try { } catch (z) { } From 192628510fc2494e8843ccc4d797d7b1a168f1d5 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 12:05:10 +0200 Subject: [PATCH 16/51] Fixes CR comments --- src/compiler/transformers/es2015.ts | 2 +- src/compiler/transformers/esnext.ts | 6 +++++- .../reference/emitter.ignoredCatchParameter.esnext.js | 11 ----------- .../emitter.ignoredCatchParameter.esnext.symbols | 7 ------- .../emitter.ignoredCatchParameter.esnext.types | 7 ------- .../noCatchBinding/emitter.noCatchBinding.esnext.ts | 8 ++++++++ .../statements/tryStatements/tryStatements.ts | 9 ++++++++- 7 files changed, 22 insertions(+), 28 deletions(-) delete mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js delete mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols delete mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types create mode 100644 tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 41e68baa523..51733524699 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -2491,7 +2491,7 @@ namespace ts { const catchVariable = getGeneratedNameForNode(errorRecord); const returnMethod = createTempVariable(/*recordTempVariable*/ undefined); const values = createValuesHelper(context, expression, node.expression); - const next = createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, []); + const next = createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 11e79ae9eeb..8d71016b051 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -216,7 +216,11 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { if (!node.variableDeclaration) { - return updateCatchClause(node, createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)), node.block); + return updateCatchClause( + node, + createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)), + visitNode(node.block, visitor, isBlock) + ); } return visitEachChild(node, visitor, context); } diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js deleted file mode 100644 index 0f9254fd3cb..00000000000 --- a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js +++ /dev/null @@ -1,11 +0,0 @@ -//// [emitter.ignoredCatchParameter.esnext.ts] -function fn() { - try {} catch {} -} - - -//// [emitter.ignoredCatchParameter.esnext.js] -function fn() { - try { } - catch { } -} diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols deleted file mode 100644 index 78838a33011..00000000000 --- a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === -function fn() { ->fn : Symbol(fn, Decl(emitter.ignoredCatchParameter.esnext.ts, 0, 0)) - - try {} catch {} -} - diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types deleted file mode 100644 index 06bf4ab2682..00000000000 --- a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === -function fn() { ->fn : () => void - - try {} catch {} -} - diff --git a/tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts b/tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts new file mode 100644 index 00000000000..8e87b3c8c8f --- /dev/null +++ b/tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts @@ -0,0 +1,8 @@ +// @target: esnext +function f() { + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} \ No newline at end of file diff --git a/tests/cases/conformance/statements/tryStatements/tryStatements.ts b/tests/cases/conformance/statements/tryStatements/tryStatements.ts index 3fb395ca0ea..0a47ba7a94b 100644 --- a/tests/cases/conformance/statements/tryStatements/tryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/tryStatements.ts @@ -2,11 +2,18 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } try { } finally { } try { } catch { } finally { } - try { } catch(z) { } finally { } + try { } catch (z) { } finally { } } \ No newline at end of file From 053b708bf136295af812a97fb93b1554285d60bf Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 17:53:46 +0200 Subject: [PATCH 17/51] Accept baseline --- .../emitter.noCatchBinding.esnext.js | 22 +++++++++++++++++++ .../emitter.noCatchBinding.esnext.symbols | 10 +++++++++ .../emitter.noCatchBinding.esnext.types | 10 +++++++++ tests/baselines/reference/tryStatements.js | 21 ++++++++++++++++-- .../baselines/reference/tryStatements.symbols | 15 +++++++++---- tests/baselines/reference/tryStatements.types | 9 +++++++- 6 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/emitter.noCatchBinding.esnext.js create mode 100644 tests/baselines/reference/emitter.noCatchBinding.esnext.symbols create mode 100644 tests/baselines/reference/emitter.noCatchBinding.esnext.types diff --git a/tests/baselines/reference/emitter.noCatchBinding.esnext.js b/tests/baselines/reference/emitter.noCatchBinding.esnext.js new file mode 100644 index 00000000000..f47a947ca1a --- /dev/null +++ b/tests/baselines/reference/emitter.noCatchBinding.esnext.js @@ -0,0 +1,22 @@ +//// [emitter.noCatchBinding.esnext.ts] +function f() { + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} + +//// [emitter.noCatchBinding.esnext.js] +function f() { + try { } + catch { } + try { } + catch { + try { } + catch { } + } + try { } + catch { } + finally { } +} diff --git a/tests/baselines/reference/emitter.noCatchBinding.esnext.symbols b/tests/baselines/reference/emitter.noCatchBinding.esnext.symbols new file mode 100644 index 00000000000..91242f5b01c --- /dev/null +++ b/tests/baselines/reference/emitter.noCatchBinding.esnext.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts === +function f() { +>f : Symbol(f, Decl(emitter.noCatchBinding.esnext.ts, 0, 0)) + + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} diff --git a/tests/baselines/reference/emitter.noCatchBinding.esnext.types b/tests/baselines/reference/emitter.noCatchBinding.esnext.types new file mode 100644 index 00000000000..70c2b728a5d --- /dev/null +++ b/tests/baselines/reference/emitter.noCatchBinding.esnext.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts === +function f() { +>f : () => void + + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index fa5c9b5c92b..64fe2cf06a7 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -2,13 +2,20 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } try { } finally { } try { } catch { } finally { } - try { } catch(z) { } finally { } + try { } catch (z) { } finally { } } //// [tryStatements.js] @@ -16,13 +23,23 @@ function fn() { try { } catch (_a) { } try { } + catch (_b) { + try { } + catch (_c) { + try { } + catch (_d) { } + } + try { } + catch (_e) { } + } + try { } catch (x) { var x; } try { } finally { } try { } - catch (_b) { } + catch (_f) { } finally { } try { } catch (z) { } diff --git a/tests/baselines/reference/tryStatements.symbols b/tests/baselines/reference/tryStatements.symbols index 5bcb897d193..69e9918a98b 100644 --- a/tests/baselines/reference/tryStatements.symbols +++ b/tests/baselines/reference/tryStatements.symbols @@ -4,14 +4,21 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } ->x : Symbol(x, Decl(tryStatements.ts, 3, 19)) ->x : Symbol(x, Decl(tryStatements.ts, 3, 27)) +>x : Symbol(x, Decl(tryStatements.ts, 10, 19)) +>x : Symbol(x, Decl(tryStatements.ts, 10, 27)) try { } finally { } try { } catch { } finally { } - try { } catch(z) { } finally { } ->z : Symbol(z, Decl(tryStatements.ts, 9, 18)) + try { } catch (z) { } finally { } +>z : Symbol(z, Decl(tryStatements.ts, 16, 19)) } diff --git a/tests/baselines/reference/tryStatements.types b/tests/baselines/reference/tryStatements.types index cdc0a7c981d..05c02568135 100644 --- a/tests/baselines/reference/tryStatements.types +++ b/tests/baselines/reference/tryStatements.types @@ -4,6 +4,13 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } >x : any >x : any @@ -12,6 +19,6 @@ function fn() { try { } catch { } finally { } - try { } catch(z) { } finally { } + try { } catch (z) { } finally { } >z : any } From d07eca72a36bd4031b54b238698f23fa6590a155 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 2 Aug 2017 09:38:44 -0700 Subject: [PATCH 18/51] Improve name:isTypeAssignableToKind+cleanup TODOs --- src/compiler/checker.ts | 68 +++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d1c18ef61d8..419a93994e6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7526,11 +7526,11 @@ namespace ts { return getTypeOfSymbol(prop); } } - if (!(indexType.flags & TypeFlags.Nullable) && isTypeOfKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { + if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { if (isTypeAny(objectType)) { return anyType; } - const indexInfo = isTypeOfKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || + const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || getIndexInfoOfType(objectType, IndexKind.String) || undefined; if (indexInfo) { @@ -11286,7 +11286,7 @@ namespace ts { (parent.parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent.parent).left === parent && !isAssignmentTarget(parent.parent) && - isTypeOfKind(getTypeOfExpression((parent).argumentExpression), TypeFlags.NumberLike); + isTypeAssignableToKind(getTypeOfExpression((parent).argumentExpression), TypeFlags.NumberLike); return isLengthPushOrUnshift || isElementAssignment; } @@ -11458,7 +11458,7 @@ namespace ts { } else { const indexType = getTypeOfExpression(((node).left).argumentExpression); - if (isTypeOfKind(indexType, TypeFlags.NumberLike)) { + if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { evolvedType = addEvolvingArrayElementType(evolvedType, (node).right); } } @@ -13290,7 +13290,7 @@ namespace ts { function isNumericComputedName(name: ComputedPropertyName): boolean { // It seems odd to consider an expression of type Any to result in a numeric name, // but this behavior is consistent with checkIndexedAccess - return isTypeOfKind(checkComputedPropertyName(name), TypeFlags.NumberLike); + return isTypeAssignableToKind(checkComputedPropertyName(name), TypeFlags.NumberLike); } function isInfinityOrNaNString(name: string | __String): boolean { @@ -13328,7 +13328,7 @@ namespace ts { links.resolvedType = checkExpression(node.expression); // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). - if (links.resolvedType.flags & TypeFlags.Nullable || !isTypeOfKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { + if (links.resolvedType.flags & TypeFlags.Nullable || !isTypeAssignableToKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } else { @@ -15431,7 +15431,7 @@ namespace ts { case SyntaxKind.ComputedPropertyName: const nameType = checkComputedPropertyName(element.name); - if (isTypeOfKind(nameType, TypeFlags.ESSymbol)) { + if (isTypeAssignableToKind(nameType, TypeFlags.ESSymbol)) { return nameType; } else { @@ -16813,7 +16813,7 @@ namespace ts { } function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean { - if (!isTypeOfKind(type, TypeFlags.NumberLike)) { + if (!isTypeAssignableToKind(type, TypeFlags.NumberLike)) { error(operand, diagnostic); return false; } @@ -16986,12 +16986,11 @@ namespace ts { return false; } - function isTypeOfKind(source: Type, kind: TypeFlags, excludeAny?: boolean) { + function isTypeAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean) { if (source.flags & kind) { return true; } - if (excludeAny && source.flags & (TypeFlags.Any | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { - // TODO: The callers who want this should really handle these cases FIRST + if (strict && source.flags & (TypeFlags.Any | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { return false; } const targets = []; @@ -17042,7 +17041,7 @@ namespace ts { // and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature. // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported - if (isTypeOfKind(leftType, TypeFlags.Primitive, /*excludeAny*/ true)) { + if (!(leftType.flags & TypeFlags.Any) && isTypeAssignableToKind(leftType, TypeFlags.Primitive)) { error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } // NOTE: do not raise error if right is unknown as related error was already reported @@ -17065,10 +17064,10 @@ namespace ts { // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, // and the right operand to be of type Any, an object type, or a type parameter type. // The result is always of the Boolean primitive type. - if (!(isTypeComparableTo(leftType, stringType) || isTypeOfKind(leftType, TypeFlags.NumberLike | TypeFlags.ESSymbol))) { + if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind(leftType, TypeFlags.NumberLike | TypeFlags.ESSymbol))) { error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } - if (!isTypeOfKind(rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) { + if (!isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) { error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -17377,33 +17376,30 @@ namespace ts { return silentNeverType; } - if (!isTypeOfKind(leftType, TypeFlags.StringLike) && !isTypeOfKind(rightType, TypeFlags.StringLike)) { + if (!isTypeAssignableToKind(leftType, TypeFlags.StringLike) && !isTypeAssignableToKind(rightType, TypeFlags.StringLike)) { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); } let resultType: Type; - if (isTypeOfKind(leftType, TypeFlags.NumberLike, /*excludeAny*/ true) && isTypeOfKind(rightType, TypeFlags.NumberLike, /*excludeAny*/ true)) { + if (isTypeAssignableToKind(leftType, TypeFlags.NumberLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.NumberLike, /*strict*/ true)) { // Operands of an enum type are treated as having the primitive type Number. // If both operands are of the Number primitive type, the result is of the Number primitive type. resultType = numberType; } - else { - if (isTypeOfKind(leftType, TypeFlags.StringLike, /*excludeAny*/ true) || isTypeOfKind(rightType, TypeFlags.StringLike, /*excludeAny*/ true)) { + else if (isTypeAssignableToKind(leftType, TypeFlags.StringLike, /*strict*/ true) || isTypeAssignableToKind(rightType, TypeFlags.StringLike, /*strict*/ true)) { // If one or both operands are of the String primitive type, the result is of the String primitive type. resultType = stringType; - } - else if (isTypeAny(leftType) || isTypeAny(rightType)) { - // Otherwise, the result is of type Any. - // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we. - // TODO: Reorder this to check for any (plus void/undefined/null) first - resultType = leftType === unknownType || rightType === unknownType ? unknownType : anyType; - } + } + else if (isTypeAny(leftType) || isTypeAny(rightType)) { + // Otherwise, the result is of type Any. + // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we. + resultType = leftType === unknownType || rightType === unknownType ? unknownType : anyType; + } - // Symbols are not allowed at all in arithmetic expressions - if (resultType && !checkForDisallowedESSymbolOperand(operator)) { - return resultType; - } + // Symbols are not allowed at all in arithmetic expressions + if (resultType && !checkForDisallowedESSymbolOperand(operator)) { + return resultType; } if (!resultType) { @@ -18620,7 +18616,7 @@ namespace ts { } // Check if we're indexing with a numeric type and the object type is a generic // type with a constraint that has a numeric index signature. - if (maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && isTypeOfKind(indexType, TypeFlags.NumberLike)) { + if (maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { const constraint = getBaseConstraintOfType(objectType); if (constraint && getIndexInfoOfType(constraint, IndexKind.Number)) { return type; @@ -20322,7 +20318,7 @@ namespace ts { // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!isTypeOfKind(rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) { + if (!isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } @@ -23303,22 +23299,22 @@ namespace ts { else if (type.flags & TypeFlags.Any) { return TypeReferenceSerializationKind.ObjectType; } - else if (isTypeOfKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) { + else if (isTypeAssignableToKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) { return TypeReferenceSerializationKind.VoidNullableOrNeverType; } - else if (isTypeOfKind(type, TypeFlags.BooleanLike)) { + else if (isTypeAssignableToKind(type, TypeFlags.BooleanLike)) { return TypeReferenceSerializationKind.BooleanType; } - else if (isTypeOfKind(type, TypeFlags.NumberLike)) { + else if (isTypeAssignableToKind(type, TypeFlags.NumberLike)) { return TypeReferenceSerializationKind.NumberLikeType; } - else if (isTypeOfKind(type, TypeFlags.StringLike)) { + else if (isTypeAssignableToKind(type, TypeFlags.StringLike)) { return TypeReferenceSerializationKind.StringLikeType; } else if (isTupleType(type)) { return TypeReferenceSerializationKind.ArrayLikeType; } - else if (isTypeOfKind(type, TypeFlags.ESSymbol)) { + else if (isTypeAssignableToKind(type, TypeFlags.ESSymbol)) { return TypeReferenceSerializationKind.ESSymbolType; } else if (isFunctionType(type)) { From 011f712d980305c990c237dd46e9a9e1c1f2ce4c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 2 Aug 2017 09:58:01 -0700 Subject: [PATCH 19/51] isTypeAssignableToKind:Chain isTypeAssignableTo calls Instead of building up a list and creating a union type. --- src/compiler/checker.ts | 44 ++++++++++++----------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 419a93994e6..e67ee72ffca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13328,7 +13328,9 @@ namespace ts { links.resolvedType = checkExpression(node.expression); // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). - if (links.resolvedType.flags & TypeFlags.Nullable || !isTypeAssignableToKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { + if (links.resolvedType.flags & TypeFlags.Nullable || + !isTypeAssignableToKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol) && + !isTypeAssignableTo(links.resolvedType, getUnionType([stringType, numberType, esSymbolType]))) { error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } else { @@ -16986,42 +16988,22 @@ namespace ts { return false; } - function isTypeAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean) { + function isTypeAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean { if (source.flags & kind) { return true; } if (strict && source.flags & (TypeFlags.Any | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { return false; } - const targets = []; - if (kind & TypeFlags.NumberLike) { - targets.push(numberType); - } - if (kind & TypeFlags.StringLike) { - targets.push(stringType); - } - if (kind & TypeFlags.BooleanLike) { - targets.push(booleanType); - } - if (kind & TypeFlags.Void) { - targets.push(voidType); - } - if (kind & TypeFlags.Never) { - targets.push(neverType); - } - if (kind & TypeFlags.Null) { - targets.push(nullType); - } - if (kind & TypeFlags.Undefined) { - targets.push(undefinedType); - } - if (kind & TypeFlags.ESSymbol) { - targets.push(esSymbolType); - } - if (kind & TypeFlags.NonPrimitive) { - targets.push(nonPrimitiveType); - } - return isTypeAssignableTo(source, getUnionType(targets)); + return kind & TypeFlags.NumberLike && isTypeAssignableTo(source, numberType) || + kind & TypeFlags.StringLike && isTypeAssignableTo(source, stringType) || + kind & TypeFlags.BooleanLike && isTypeAssignableTo(source, booleanType) || + kind & TypeFlags.Void && isTypeAssignableTo(source, voidType) || + kind & TypeFlags.Never && isTypeAssignableTo(source, neverType) || + kind & TypeFlags.Null && isTypeAssignableTo(source, nullType) || + kind & TypeFlags.Undefined && isTypeAssignableTo(source, undefinedType) || + kind & TypeFlags.ESSymbol && isTypeAssignableTo(source, esSymbolType) || + kind & TypeFlags.NonPrimitive && isTypeAssignableTo(source, nonPrimitiveType); } function isConstEnumObjectType(type: Type): boolean { From aed386c796046153e76196af8ed4135cbeaebc8c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 2 Aug 2017 10:33:15 -0700 Subject: [PATCH 20/51] Add regression test cases and rename test --- .../reference/typeParamExtendsNumber.js | 19 ---- .../reference/typeParamExtendsNumber.symbols | 20 ----- .../reference/typeParamExtendsNumber.types | 23 ----- .../typeParameterExtendsPrimitive.js | 51 +++++++++++ .../typeParameterExtendsPrimitive.symbols | 82 +++++++++++++++++ .../typeParameterExtendsPrimitive.types | 90 +++++++++++++++++++ .../cases/compiler/typeParamExtendsNumber.ts | 7 -- .../compiler/typeParameterExtendsPrimitive.ts | 25 ++++++ 8 files changed, 248 insertions(+), 69 deletions(-) delete mode 100644 tests/baselines/reference/typeParamExtendsNumber.js delete mode 100644 tests/baselines/reference/typeParamExtendsNumber.symbols delete mode 100644 tests/baselines/reference/typeParamExtendsNumber.types create mode 100644 tests/baselines/reference/typeParameterExtendsPrimitive.js create mode 100644 tests/baselines/reference/typeParameterExtendsPrimitive.symbols create mode 100644 tests/baselines/reference/typeParameterExtendsPrimitive.types delete mode 100644 tests/cases/compiler/typeParamExtendsNumber.ts create mode 100644 tests/cases/compiler/typeParameterExtendsPrimitive.ts diff --git a/tests/baselines/reference/typeParamExtendsNumber.js b/tests/baselines/reference/typeParamExtendsNumber.js deleted file mode 100644 index 70548e79856..00000000000 --- a/tests/baselines/reference/typeParamExtendsNumber.js +++ /dev/null @@ -1,19 +0,0 @@ -//// [typeParamExtendsNumber.ts] -function f() { - var t: T; - var v = { - [t]: 0 - } - return t + t; -} - - -//// [typeParamExtendsNumber.js] -function f() { - var t; - var v = (_a = {}, - _a[t] = 0, - _a); - return t + t; - var _a; -} diff --git a/tests/baselines/reference/typeParamExtendsNumber.symbols b/tests/baselines/reference/typeParamExtendsNumber.symbols deleted file mode 100644 index 032f08bd58c..00000000000 --- a/tests/baselines/reference/typeParamExtendsNumber.symbols +++ /dev/null @@ -1,20 +0,0 @@ -=== tests/cases/compiler/typeParamExtendsNumber.ts === -function f() { ->f : Symbol(f, Decl(typeParamExtendsNumber.ts, 0, 0)) ->T : Symbol(T, Decl(typeParamExtendsNumber.ts, 0, 11)) - - var t: T; ->t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) ->T : Symbol(T, Decl(typeParamExtendsNumber.ts, 0, 11)) - - var v = { ->v : Symbol(v, Decl(typeParamExtendsNumber.ts, 2, 7)) - - [t]: 0 ->t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) - } - return t + t; ->t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) ->t : Symbol(t, Decl(typeParamExtendsNumber.ts, 1, 7)) -} - diff --git a/tests/baselines/reference/typeParamExtendsNumber.types b/tests/baselines/reference/typeParamExtendsNumber.types deleted file mode 100644 index 9034e23ee23..00000000000 --- a/tests/baselines/reference/typeParamExtendsNumber.types +++ /dev/null @@ -1,23 +0,0 @@ -=== tests/cases/compiler/typeParamExtendsNumber.ts === -function f() { ->f : () => number ->T : T - - var t: T; ->t : T ->T : T - - var v = { ->v : { [x: number]: number; } ->{ [t]: 0 } : { [x: number]: number; } - - [t]: 0 ->t : T ->0 : 0 - } - return t + t; ->t + t : number ->t : T ->t : T -} - diff --git a/tests/baselines/reference/typeParameterExtendsPrimitive.js b/tests/baselines/reference/typeParameterExtendsPrimitive.js new file mode 100644 index 00000000000..1774db19f6e --- /dev/null +++ b/tests/baselines/reference/typeParameterExtendsPrimitive.js @@ -0,0 +1,51 @@ +//// [typeParameterExtendsPrimitive.ts] +// #14473 +function f() { + var t: T; + var v = { + [t]: 0 + } + return t + t; +} + +// #15501 +interface I { x: number } +type IdMap = { [P in keyof T]: T[P] }; +function g(i: IdMap) { + const n: number = i.x; + return i.x * 2; +} + +// #17069 +function h, K extends string>(array: T[], prop: K): number { + let result = 0; + for (const v of array) { + result += v[prop]; + } + return result; +} + + +//// [typeParameterExtendsPrimitive.js] +// #14473 +function f() { + var t; + var v = (_a = {}, + _a[t] = 0, + _a); + return t + t; + var _a; +} +function g(i) { + var n = i.x; + return i.x * 2; +} +// #17069 +function h(array, prop) { + var result = 0; + for (var _i = 0, array_1 = array; _i < array_1.length; _i++) { + var v = array_1[_i]; + result += v[prop]; + } + return result; +} diff --git a/tests/baselines/reference/typeParameterExtendsPrimitive.symbols b/tests/baselines/reference/typeParameterExtendsPrimitive.symbols new file mode 100644 index 00000000000..acac75272ac --- /dev/null +++ b/tests/baselines/reference/typeParameterExtendsPrimitive.symbols @@ -0,0 +1,82 @@ +=== tests/cases/compiler/typeParameterExtendsPrimitive.ts === +// #14473 +function f() { +>f : Symbol(f, Decl(typeParameterExtendsPrimitive.ts, 0, 0)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 1, 11)) + + var t: T; +>t : Symbol(t, Decl(typeParameterExtendsPrimitive.ts, 2, 7)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 1, 11)) + + var v = { +>v : Symbol(v, Decl(typeParameterExtendsPrimitive.ts, 3, 7)) + + [t]: 0 +>t : Symbol(t, Decl(typeParameterExtendsPrimitive.ts, 2, 7)) + } + return t + t; +>t : Symbol(t, Decl(typeParameterExtendsPrimitive.ts, 2, 7)) +>t : Symbol(t, Decl(typeParameterExtendsPrimitive.ts, 2, 7)) +} + +// #15501 +interface I { x: number } +>I : Symbol(I, Decl(typeParameterExtendsPrimitive.ts, 7, 1)) +>x : Symbol(I.x, Decl(typeParameterExtendsPrimitive.ts, 10, 13)) + +type IdMap = { [P in keyof T]: T[P] }; +>IdMap : Symbol(IdMap, Decl(typeParameterExtendsPrimitive.ts, 10, 25)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 11, 11)) +>P : Symbol(P, Decl(typeParameterExtendsPrimitive.ts, 11, 19)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 11, 11)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 11, 11)) +>P : Symbol(P, Decl(typeParameterExtendsPrimitive.ts, 11, 19)) + +function g(i: IdMap) { +>g : Symbol(g, Decl(typeParameterExtendsPrimitive.ts, 11, 41)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 12, 11)) +>I : Symbol(I, Decl(typeParameterExtendsPrimitive.ts, 7, 1)) +>i : Symbol(i, Decl(typeParameterExtendsPrimitive.ts, 12, 24)) +>IdMap : Symbol(IdMap, Decl(typeParameterExtendsPrimitive.ts, 10, 25)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 12, 11)) + + const n: number = i.x; +>n : Symbol(n, Decl(typeParameterExtendsPrimitive.ts, 13, 9)) +>i.x : Symbol(x, Decl(typeParameterExtendsPrimitive.ts, 10, 13)) +>i : Symbol(i, Decl(typeParameterExtendsPrimitive.ts, 12, 24)) +>x : Symbol(x, Decl(typeParameterExtendsPrimitive.ts, 10, 13)) + + return i.x * 2; +>i.x : Symbol(x, Decl(typeParameterExtendsPrimitive.ts, 10, 13)) +>i : Symbol(i, Decl(typeParameterExtendsPrimitive.ts, 12, 24)) +>x : Symbol(x, Decl(typeParameterExtendsPrimitive.ts, 10, 13)) +} + +// #17069 +function h, K extends string>(array: T[], prop: K): number { +>h : Symbol(h, Decl(typeParameterExtendsPrimitive.ts, 15, 1)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 18, 11)) +>Record : Symbol(Record, Decl(lib.d.ts, --, --)) +>K : Symbol(K, Decl(typeParameterExtendsPrimitive.ts, 18, 39)) +>K : Symbol(K, Decl(typeParameterExtendsPrimitive.ts, 18, 39)) +>array : Symbol(array, Decl(typeParameterExtendsPrimitive.ts, 18, 58)) +>T : Symbol(T, Decl(typeParameterExtendsPrimitive.ts, 18, 11)) +>prop : Symbol(prop, Decl(typeParameterExtendsPrimitive.ts, 18, 69)) +>K : Symbol(K, Decl(typeParameterExtendsPrimitive.ts, 18, 39)) + + let result = 0; +>result : Symbol(result, Decl(typeParameterExtendsPrimitive.ts, 19, 7)) + + for (const v of array) { +>v : Symbol(v, Decl(typeParameterExtendsPrimitive.ts, 20, 14)) +>array : Symbol(array, Decl(typeParameterExtendsPrimitive.ts, 18, 58)) + + result += v[prop]; +>result : Symbol(result, Decl(typeParameterExtendsPrimitive.ts, 19, 7)) +>v : Symbol(v, Decl(typeParameterExtendsPrimitive.ts, 20, 14)) +>prop : Symbol(prop, Decl(typeParameterExtendsPrimitive.ts, 18, 69)) + } + return result; +>result : Symbol(result, Decl(typeParameterExtendsPrimitive.ts, 19, 7)) +} + diff --git a/tests/baselines/reference/typeParameterExtendsPrimitive.types b/tests/baselines/reference/typeParameterExtendsPrimitive.types new file mode 100644 index 00000000000..1e8eb7f40e0 --- /dev/null +++ b/tests/baselines/reference/typeParameterExtendsPrimitive.types @@ -0,0 +1,90 @@ +=== tests/cases/compiler/typeParameterExtendsPrimitive.ts === +// #14473 +function f() { +>f : () => number +>T : T + + var t: T; +>t : T +>T : T + + var v = { +>v : { [x: number]: number; } +>{ [t]: 0 } : { [x: number]: number; } + + [t]: 0 +>t : T +>0 : 0 + } + return t + t; +>t + t : number +>t : T +>t : T +} + +// #15501 +interface I { x: number } +>I : I +>x : number + +type IdMap = { [P in keyof T]: T[P] }; +>IdMap : IdMap +>T : T +>P : P +>T : T +>T : T +>P : P + +function g(i: IdMap) { +>g : (i: IdMap) => number +>T : T +>I : I +>i : IdMap +>IdMap : IdMap +>T : T + + const n: number = i.x; +>n : number +>i.x : T["x"] +>i : IdMap +>x : T["x"] + + return i.x * 2; +>i.x * 2 : number +>i.x : T["x"] +>i : IdMap +>x : T["x"] +>2 : 2 +} + +// #17069 +function h, K extends string>(array: T[], prop: K): number { +>h : , K extends string>(array: T[], prop: K) => number +>T : T +>Record : Record +>K : K +>K : K +>array : T[] +>T : T +>prop : K +>K : K + + let result = 0; +>result : number +>0 : 0 + + for (const v of array) { +>v : T +>array : T[] + + result += v[prop]; +>result += v[prop] : number +>result : number +>v[prop] : T[K] +>v : T +>prop : K + } + return result; +>result : number +} + diff --git a/tests/cases/compiler/typeParamExtendsNumber.ts b/tests/cases/compiler/typeParamExtendsNumber.ts deleted file mode 100644 index 89b60c990a2..00000000000 --- a/tests/cases/compiler/typeParamExtendsNumber.ts +++ /dev/null @@ -1,7 +0,0 @@ -function f() { - var t: T; - var v = { - [t]: 0 - } - return t + t; -} diff --git a/tests/cases/compiler/typeParameterExtendsPrimitive.ts b/tests/cases/compiler/typeParameterExtendsPrimitive.ts new file mode 100644 index 00000000000..b94a44b4660 --- /dev/null +++ b/tests/cases/compiler/typeParameterExtendsPrimitive.ts @@ -0,0 +1,25 @@ +// #14473 +function f() { + var t: T; + var v = { + [t]: 0 + } + return t + t; +} + +// #15501 +interface I { x: number } +type IdMap = { [P in keyof T]: T[P] }; +function g(i: IdMap) { + const n: number = i.x; + return i.x * 2; +} + +// #17069 +function h, K extends string>(array: T[], prop: K): number { + let result = 0; + for (const v of array) { + result += v[prop]; + } + return result; +} From d5c24f3cd3bd0d5375a92ffc5a9b1620ed1d6571 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 20:13:43 +0200 Subject: [PATCH 21/51] Addresses CR comment --- src/compiler/emitter.ts | 2 +- src/compiler/factory.ts | 4 ++-- src/compiler/parser.ts | 4 ++++ src/compiler/transformers/es2015.ts | 2 +- src/compiler/types.ts | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1c5194054ca..24769afd5d4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2134,7 +2134,7 @@ namespace ts { if (node.variableDeclaration) { writeToken(SyntaxKind.OpenParenToken, openParenPos); emit(node.variableDeclaration); - writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration.end); write(" "); } emit(node.block); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 34727e4c414..47df0a9bdc2 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2128,14 +2128,14 @@ namespace ts { : node; } - export function createCatchClause(variableDeclaration: string | VariableDeclaration, block: Block) { + export function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block) { const node = createSynthesizedNode(SyntaxKind.CatchClause); node.variableDeclaration = typeof variableDeclaration === "string" ? createVariableDeclaration(variableDeclaration) : variableDeclaration; node.block = block; return node; } - export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration, block: Block) { + export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) { return node.variableDeclaration !== variableDeclaration || node.block !== block ? updateNode(createCatchClause(variableDeclaration, block), node) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 12c516c88b0..4547df15790 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4783,6 +4783,10 @@ namespace ts { result.variableDeclaration = parseVariableDeclaration(); parseExpected(SyntaxKind.CloseParenToken); } + else { + // Keep shape of node to not avoid degrading performance. + result.variableDeclaration = undefined; + } result.block = parseBlock(/*ignoreMissingOpenBrace*/ false); return finishNode(result); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 51733524699..2b0b175e2a5 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3173,7 +3173,7 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes); let updated: CatchClause; - Debug.assert(!!node.variableDeclaration, "Catch clauses should always be present when downleveling ES2015 code."); + Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015."); if (isBindingPattern(node.variableDeclaration.name)) { const temp = createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = createVariableDeclaration(temp); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9cf8e6fdf00..ca70a6fe209 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1807,7 +1807,7 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; // We make this optional to parse missing try statements + parent?: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; } From f9e85ec0917342727957f160acf43e3890f46762 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 20:48:31 +0200 Subject: [PATCH 22/51] Adds missing test cases --- .../invalidTryStatements2.errors.txt | 40 +++++++++--------- .../reference/invalidTryStatements2.js | 42 ++++++++----------- .../tryStatements/invalidTryStatements2.ts | 22 ++++------ 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index 38c30fb32ab..d43c33e55a3 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -1,17 +1,23 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(2,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(8,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(9,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(18,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(6,12): error TS1005: 'finally' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(10,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(11,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(15,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(17,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(19,20): error TS1003: Identifier expected. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (5 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (7 errors) ==== function fn() { catch(x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. - finally{ } // potential error; can be absorbed by the 'catch' + finally { } // potential error; can be absorbed by the 'catch' + + try { }; // missing finally + ~ +!!! error TS1005: 'finally' expected. } function fn2() { @@ -21,22 +27,18 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): catch (x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. + + try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below - // no error - try { - } - finally { - } - - // error missing try - finally { + finally { } // error missing try ~~~~~~~ !!! error TS1005: 'try' expected. - } - - // error missing try - catch (x) { + + catch (x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. - } + + try { } catch () { } // error missing catch binding + ~ +!!! error TS1003: Identifier expected. } \ No newline at end of file diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 45b150b4094..25d411ca484 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -2,26 +2,22 @@ function fn() { catch(x) { } // error missing try - finally{ } // potential error; can be absorbed by the 'catch' + finally { } // potential error; can be absorbed by the 'catch' + + try { }; // missing finally } function fn2() { finally { } // error missing try catch (x) { } // error missing try + + try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below - // no error - try { - } - finally { - } + finally { } // error missing try + + catch (x) { } // error missing try - // error missing try - finally { - } - - // error missing try - catch (x) { - } + try { } catch () { } // error missing catch binding } //// [invalidTryStatements2.js] @@ -30,6 +26,9 @@ function fn() { } catch (x) { } // error missing try finally { } // potential error; can be absorbed by the 'catch' + try { } + finally { } + ; // missing finally } function fn2() { try { @@ -38,19 +37,14 @@ function fn2() { try { } catch (x) { } // error missing try - // no error + try { } + finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below try { } - finally { - } - // error missing try + finally { } // error missing try try { } - finally { - } - // error missing try - try { - } - catch (x) { - } + catch (x) { } // error missing try + try { } + catch () { } // error missing catch binding } diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts index 205d6f3f193..d3d261830f4 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts @@ -1,24 +1,20 @@ function fn() { catch(x) { } // error missing try - finally{ } // potential error; can be absorbed by the 'catch' + finally { } // potential error; can be absorbed by the 'catch' + + try { }; // missing finally } function fn2() { finally { } // error missing try catch (x) { } // error missing try + + try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below - // no error - try { - } - finally { - } + finally { } // error missing try + + catch (x) { } // error missing try - // error missing try - finally { - } - - // error missing try - catch (x) { - } + try { } catch () { } // error missing catch binding } \ No newline at end of file From 4f3e13ab8c290fe8a29d661fec280ff700f68021 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 20:50:45 +0200 Subject: [PATCH 23/51] Typo --- tests/baselines/reference/invalidTryStatements2.errors.txt | 2 +- tests/baselines/reference/invalidTryStatements2.js | 4 ++-- .../statements/tryStatements/invalidTryStatements2.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index d43c33e55a3..a7c436236f2 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -15,7 +15,7 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(19,20) finally { } // potential error; can be absorbed by the 'catch' - try { }; // missing finally + try { }; // error missing finally ~ !!! error TS1005: 'finally' expected. } diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 25d411ca484..50aff00c515 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -4,7 +4,7 @@ function fn() { finally { } // potential error; can be absorbed by the 'catch' - try { }; // missing finally + try { }; // error missing finally } function fn2() { @@ -28,7 +28,7 @@ function fn() { finally { } // potential error; can be absorbed by the 'catch' try { } finally { } - ; // missing finally + ; // error missing finally } function fn2() { try { diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts index d3d261830f4..7fb1b135c90 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts @@ -3,7 +3,7 @@ function fn() { finally { } // potential error; can be absorbed by the 'catch' - try { }; // missing finally + try { }; // error missing finally } function fn2() { From 3da1a53d7ec22a78346e373c9d5f887538a800d8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 2 Aug 2017 12:50:04 -0700 Subject: [PATCH 24/51] Amend comment about explicitly setting catch clause variables to 'undefined'. --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4547df15790..155ad3999bf 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4784,7 +4784,7 @@ namespace ts { parseExpected(SyntaxKind.CloseParenToken); } else { - // Keep shape of node to not avoid degrading performance. + // Keep shape of node to avoid degrading performance. result.variableDeclaration = undefined; } From b747c2dd96ede26c853dee1d8882d73bb6d8ddf8 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 3 Aug 2017 18:30:09 -0700 Subject: [PATCH 25/51] exclude node_modules unless explicitly included --- src/compiler/commandLineParser.ts | 6 +- src/compiler/core.ts | 101 ++++++--- src/harness/unittests/matchFiles.ts | 193 ++++++++++++------ .../nodeModulesMaxDepthExceeded.errors.txt | 2 +- .../nodeModulesMaxDepthExceeded.errors.txt | 2 +- .../maxDepthExceeded/tsconfig.json | 2 +- 6 files changed, 200 insertions(+), 106 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 554b46dcdfe..b0cb7f94029 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1446,14 +1446,10 @@ namespace ts { } } else { - // If no includes were specified, exclude common package folders and the outDir - const specs = includeSpecs ? [] : ["node_modules", "bower_components", "jspm_packages"]; - const outDir = raw["compilerOptions"] && raw["compilerOptions"]["outDir"]; if (outDir) { - specs.push(outDir); + excludeSpecs = [outDir]; } - excludeSpecs = specs; } if (fileNames === undefined && includeSpecs === undefined) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 728fb433c04..07f979333b6 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1889,14 +1889,54 @@ namespace ts { const reservedCharacterPattern = /[^\w\s\/]/g; const wildcardCharCodes = [CharacterCodes.asterisk, CharacterCodes.question]; - /** - * Matches any single directory segment unless it is the last segment and a .min.js file - * Breakdown: - * [^./] # matches everything up to the first . character (excluding directory seperators) - * (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension - */ - const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*"; - const singleAsteriskRegexFragmentOther = "[^/]*"; + /* @internal */ + export const commonPackageFolders: ReadonlyArray = ["node_modules", "bower_components", "jspm_packages"]; + + const implicitExcludePathRegexPattern = `(?!(${commonPackageFolders.join("|")})(/|$))`; + + interface WildcardMatcher { + singleAsteriskRegexFragment: string; + doubleAsteriskRegexFragment: string; + replaceWildcardCharacter: (match: string) => string; + } + + const filesMatcher: WildcardMatcher = { + /** + * Matches any single directory segment unless it is the last segment and a .min.js file + * Breakdown: + * [^./] # matches everything up to the first . character (excluding directory seperators) + * (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension + */ + singleAsteriskRegexFragment: "([^./]|(\\.(?!min\\.js$))?)*", + /** + * Regex for the ** wildcard. Matches any number of subdirectories. When used for including + * files or directories, does not match subdirectories that start with a . character + */ + doubleAsteriskRegexFragment: `(/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`, + replaceWildcardCharacter: match => replaceWildcardCharacter(match, filesMatcher.singleAsteriskRegexFragment) + }; + + const directoriesMatcher: WildcardMatcher = { + singleAsteriskRegexFragment: "[^/]*", + /** + * Regex for the ** wildcard. Matches any number of subdirectories. When used for including + * files or directories, does not match subdirectories that start with a . character + */ + doubleAsteriskRegexFragment: `(/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`, + replaceWildcardCharacter: match => replaceWildcardCharacter(match, directoriesMatcher.singleAsteriskRegexFragment) + }; + + const excludeMatcher: WildcardMatcher = { + singleAsteriskRegexFragment: "[^/]*", + doubleAsteriskRegexFragment: "(/.+?)?", + replaceWildcardCharacter: match => replaceWildcardCharacter(match, excludeMatcher.singleAsteriskRegexFragment) + }; + + const wildcardMatchers = { + files: filesMatcher, + directories: directoriesMatcher, + exclude: excludeMatcher + }; export function getRegularExpressionForWildcard(specs: ReadonlyArray, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined { const patterns = getRegularExpressionsForWildcards(specs, basePath, usage); @@ -1915,17 +1955,8 @@ namespace ts { return undefined; } - const replaceWildcardCharacter = usage === "files" ? replaceWildCardCharacterFiles : replaceWildCardCharacterOther; - const singleAsteriskRegexFragment = usage === "files" ? singleAsteriskRegexFragmentFiles : singleAsteriskRegexFragmentOther; - - /** - * Regex for the ** wildcard. Matches any number of subdirectories. When used for including - * files or directories, does not match subdirectories that start with a . character - */ - const doubleAsteriskRegexFragment = usage === "exclude" ? "(/.+?)?" : "(/[^/.][^/]*)*?"; - return flatMap(specs, spec => - spec && getSubPatternFromSpec(spec, basePath, usage, singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter)); + spec && getSubPatternFromSpec(spec, basePath, usage, wildcardMatchers[usage])); } /** @@ -1936,7 +1967,7 @@ namespace ts { return !/[.*?]/.test(lastPathComponent); } - function getSubPatternFromSpec(spec: string, basePath: string, usage: "files" | "directories" | "exclude", singleAsteriskRegexFragment: string, doubleAsteriskRegexFragment: string, replaceWildcardCharacter: (match: string) => string): string | undefined { + function getSubPatternFromSpec(spec: string, basePath: string, usage: "files" | "directories" | "exclude", { singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter }: WildcardMatcher): string | undefined { let subpattern = ""; let hasRecursiveDirectoryWildcard = false; let hasWrittenComponent = false; @@ -1975,20 +2006,36 @@ namespace ts { } if (usage !== "exclude") { + let componentPattern = ""; // The * and ? wildcards should not match directories or files that start with . if they // appear first in a component. Dotted directories and files can be included explicitly // like so: **/.*/.* if (component.charCodeAt(0) === CharacterCodes.asterisk) { - subpattern += "([^./]" + singleAsteriskRegexFragment + ")?"; + componentPattern += "([^./]" + singleAsteriskRegexFragment + ")?"; component = component.substr(1); } else if (component.charCodeAt(0) === CharacterCodes.question) { - subpattern += "[^./]"; + componentPattern += "[^./]"; component = component.substr(1); } - } - subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter); + componentPattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter); + + // Patterns should not include subfolders like node_modules unless they are + // explicitly included as part of the path. + // + // As an optimization, if the component pattern is the same as the component, + // then there definitely were no wildcard characters and we do not need to + // add the exclusion pattern. + if (componentPattern !== component) { + subpattern += implicitExcludePathRegexPattern; + } + + subpattern += componentPattern; + } + else { + subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter); + } } hasWrittenComponent = true; @@ -2002,14 +2049,6 @@ namespace ts { return subpattern; } - function replaceWildCardCharacterFiles(match: string) { - return replaceWildcardCharacter(match, singleAsteriskRegexFragmentFiles); - } - - function replaceWildCardCharacterOther(match: string) { - return replaceWildcardCharacter(match, singleAsteriskRegexFragmentOther); - } - function replaceWildcardCharacter(match: string, singleAsteriskRegexFragment: string) { return match === "*" ? singleAsteriskRegexFragment : match === "?" ? "[^/]" : "\\" + match; } diff --git a/src/harness/unittests/matchFiles.ts b/src/harness/unittests/matchFiles.ts index e0454671930..71b1bfff11a 100644 --- a/src/harness/unittests/matchFiles.ts +++ b/src/harness/unittests/matchFiles.ts @@ -73,6 +73,7 @@ namespace ts { "c:/dev/a.d.ts", "c:/dev/a.js", "c:/dev/b.ts", + "c:/dev/x/a.ts", "c:/dev/node_modules/a.ts", "c:/dev/bower_components/a.ts", "c:/dev/jspm_packages/a.ts" @@ -141,7 +142,8 @@ namespace ts { errors: [], fileNames: [ "c:/dev/a.ts", - "c:/dev/b.ts" + "c:/dev/b.ts", + "c:/dev/x/a.ts" ], wildcardDirectories: { "c:/dev": ts.WatchDirectoryFlags.Recursive @@ -462,7 +464,6 @@ namespace ts { }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); }); - it("same named declarations are excluded", () => { const json = { include: [ @@ -651,71 +652,127 @@ namespace ts { }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); }); - it("with common package folders and no exclusions", () => { - const json = { - include: [ - "**/a.ts" - ] - }; - const expected: ts.ParsedCommandLine = { - options: {}, - errors: [], - fileNames: [ - "c:/dev/a.ts", - "c:/dev/bower_components/a.ts", - "c:/dev/jspm_packages/a.ts", - "c:/dev/node_modules/a.ts" - ], - wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive - }, - }; - validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); - }); - it("with common package folders and exclusions", () => { - const json = { - include: [ - "**/a.ts" - ], - exclude: [ - "a.ts" - ] - }; - const expected: ts.ParsedCommandLine = { - options: {}, - errors: [], - fileNames: [ - "c:/dev/bower_components/a.ts", - "c:/dev/jspm_packages/a.ts", - "c:/dev/node_modules/a.ts" - ], - wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive - }, - }; - validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); - }); - it("with common package folders and empty exclude", () => { - const json = { - include: [ - "**/a.ts" - ], - exclude: [] - }; - const expected: ts.ParsedCommandLine = { - options: {}, - errors: [], - fileNames: [ - "c:/dev/a.ts", - "c:/dev/bower_components/a.ts", - "c:/dev/jspm_packages/a.ts", - "c:/dev/node_modules/a.ts" - ], - wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive - }, - }; - validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); + describe("with common package folders", () => { + it("and no exclusions", () => { + const json = { + include: [ + "**/a.ts" + ] + }; + const expected: ts.ParsedCommandLine = { + options: {}, + errors: [], + fileNames: [ + "c:/dev/a.ts", + "c:/dev/x/a.ts" + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + }, + }; + validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); + }); + it("and exclusions", () => { + const json = { + include: [ + "**/?.ts" + ], + exclude: [ + "a.ts" + ] + }; + const expected: ts.ParsedCommandLine = { + options: {}, + errors: [], + fileNames: [ + "c:/dev/b.ts", + "c:/dev/x/a.ts" + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + }, + }; + validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); + }); + it("and empty exclude", () => { + const json = { + include: [ + "**/a.ts" + ], + exclude: [] + }; + const expected: ts.ParsedCommandLine = { + options: {}, + errors: [], + fileNames: [ + "c:/dev/a.ts", + "c:/dev/x/a.ts" + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + }, + }; + validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); + }); + it("and explicit recursive include", () => { + const json = { + include: [ + "**/a.ts", + "**/node_modules/a.ts" + ] + }; + const expected: ts.ParsedCommandLine = { + options: {}, + errors: [], + fileNames: [ + "c:/dev/a.ts", + "c:/dev/x/a.ts", + "c:/dev/node_modules/a.ts" + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + }, + }; + validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); + }); + it("and wildcard include", () => { + const json = { + include: [ + "*/a.ts" + ] + }; + const expected: ts.ParsedCommandLine = { + options: {}, + errors: [], + fileNames: [ + "c:/dev/x/a.ts" + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + }, + }; + validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); + }); + it("and explicit wildcard include", () => { + const json = { + include: [ + "*/a.ts", + "node_modules/a.ts" + ] + }; + const expected: ts.ParsedCommandLine = { + options: {}, + errors: [], + fileNames: [ + "c:/dev/x/a.ts", + "c:/dev/node_modules/a.ts" + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + }, + }; + validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); + }); }); it("exclude .js files when allowJs=false", () => { const json = { @@ -1066,6 +1123,7 @@ namespace ts { }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); }); + describe("with trailing recursive directory", () => { it("in includes", () => { const json = { @@ -1264,6 +1322,7 @@ namespace ts { }); }); }); + describe("with files or folders that begin with a .", () => { it("that are not explicitly included", () => { const json = { diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt index a1b170ce665..bd2dd6231f3 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt +++ b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt @@ -9,7 +9,7 @@ maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it i "maxNodeModuleJsDepth": 1, // Note: Module m1 is already included as a root file "outDir": "built" }, - "include": ["**/*"], + "include": ["**/*", "node_modules/**/*"], "exclude": ["node_modules/m2/**/*"] } diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt index a1b170ce665..bd2dd6231f3 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt +++ b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt @@ -9,7 +9,7 @@ maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it i "maxNodeModuleJsDepth": 1, // Note: Module m1 is already included as a root file "outDir": "built" }, - "include": ["**/*"], + "include": ["**/*", "node_modules/**/*"], "exclude": ["node_modules/m2/**/*"] } diff --git a/tests/cases/projects/NodeModulesSearch/maxDepthExceeded/tsconfig.json b/tests/cases/projects/NodeModulesSearch/maxDepthExceeded/tsconfig.json index 52633bb5a98..b2ee28482ba 100644 --- a/tests/cases/projects/NodeModulesSearch/maxDepthExceeded/tsconfig.json +++ b/tests/cases/projects/NodeModulesSearch/maxDepthExceeded/tsconfig.json @@ -4,6 +4,6 @@ "maxNodeModuleJsDepth": 1, // Note: Module m1 is already included as a root file "outDir": "built" }, - "include": ["**/*"], + "include": ["**/*", "node_modules/**/*"], "exclude": ["node_modules/m2/**/*"] } From a282cbb07e18f0ef1bfd21633f8b461fa961e42f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 7 Aug 2017 10:56:18 -0700 Subject: [PATCH 26/51] Weak type errors for signature-only types too Now source types that only have a call signature (like functions) or construct signature will get a weak type error too. This is really good for catching uncalled functions: ```ts functionTakingWeakType(returnWeakType); // OOPS. Forgot to call `returnWeakType()`. That's an error! ``` --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8af11e7803..990bfd546a3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8938,7 +8938,9 @@ namespace ts { !(target.flags & TypeFlags.Union) && !isIntersectionConstituent && source !== globalObjectType && - getPropertiesOfType(source).length > 0 && + (getPropertiesOfType(source).length > 0 || + getSignaturesOfType(source, SignatureKind.Call).length > 0 || + getSignaturesOfType(source, SignatureKind.Construct).length > 0) && isWeakType(target) && !hasCommonProperties(source, target)) { if (reportErrors) { From 068cb8d5d05e5f46decd3e205b2b09d7455369da Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 7 Aug 2017 10:58:07 -0700 Subject: [PATCH 27/51] Update weakType test + baselines --- tests/baselines/reference/weakType.errors.txt | 28 +++++++++++++------ tests/baselines/reference/weakType.js | 10 ++++--- tests/cases/compiler/weakType.ts | 7 +++-- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/tests/baselines/reference/weakType.errors.txt b/tests/baselines/reference/weakType.errors.txt index 441ef70ac16..b08dcc33980 100644 --- a/tests/baselines/reference/weakType.errors.txt +++ b/tests/baselines/reference/weakType.errors.txt @@ -1,14 +1,17 @@ -tests/cases/compiler/weakType.ts(16,13): error TS2559: Type '12' has no properties in common with type 'Settings'. -tests/cases/compiler/weakType.ts(17,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'. -tests/cases/compiler/weakType.ts(18,13): error TS2559: Type 'false' has no properties in common with type 'Settings'. -tests/cases/compiler/weakType.ts(35,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'. -tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'. +tests/cases/compiler/weakType.ts(15,13): error TS2559: Type '() => { timeout: number; }' has no properties in common with type 'Settings'. +tests/cases/compiler/weakType.ts(16,13): error TS2559: Type '() => void' has no properties in common with type 'Settings'. +tests/cases/compiler/weakType.ts(17,13): error TS2559: Type 'CtorOnly' has no properties in common with type 'Settings'. +tests/cases/compiler/weakType.ts(18,13): error TS2559: Type '12' has no properties in common with type 'Settings'. +tests/cases/compiler/weakType.ts(19,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'. +tests/cases/compiler/weakType.ts(20,13): error TS2559: Type 'false' has no properties in common with type 'Settings'. +tests/cases/compiler/weakType.ts(37,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'. +tests/cases/compiler/weakType.ts(62,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'. Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'. Types of property 'properties' are incompatible. Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'. -==== tests/cases/compiler/weakType.ts (5 errors) ==== +==== tests/cases/compiler/weakType.ts (8 errors) ==== interface Settings { timeout?: number; onError?(): void; @@ -17,13 +20,21 @@ tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wron function getDefaultSettings() { return { timeout: 1000 }; } + interface CtorOnly { + new(s: string): string + } function doSomething(settings: Settings) { /* ... */ } // forgot to call `getDefaultSettings` - // but it is not caught because we don't check for call signatures doSomething(getDefaultSettings); - // same for arrow expressions: + ~~~~~~~~~~~~~~~~~~ +!!! error TS2559: Type '() => { timeout: number; }' has no properties in common with type 'Settings'. doSomething(() => { }); + ~~~~~~~~~ +!!! error TS2559: Type '() => void' has no properties in common with type 'Settings'. + doSomething(null as CtorOnly); + ~~~~~~~~~~~~~~~~ +!!! error TS2559: Type 'CtorOnly' has no properties in common with type 'Settings'. doSomething(12); ~~ !!! error TS2559: Type '12' has no properties in common with type 'Settings'. @@ -82,4 +93,5 @@ tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wron !!! error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'. !!! error TS2322: Types of property 'properties' are incompatible. !!! error TS2322: Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/weakType.js b/tests/baselines/reference/weakType.js index 5637271ccec..999269384dc 100644 --- a/tests/baselines/reference/weakType.js +++ b/tests/baselines/reference/weakType.js @@ -7,13 +7,15 @@ interface Settings { function getDefaultSettings() { return { timeout: 1000 }; } +interface CtorOnly { + new(s: string): string +} function doSomething(settings: Settings) { /* ... */ } // forgot to call `getDefaultSettings` -// but it is not caught because we don't check for call signatures doSomething(getDefaultSettings); -// same for arrow expressions: doSomething(() => { }); +doSomething(null as CtorOnly); doSomething(12); doSomething('completely wrong'); doSomething(false); @@ -59,6 +61,7 @@ declare let unknown: { } } let weak: Weak & Spoiler = unknown + //// [weakType.js] @@ -67,10 +70,9 @@ function getDefaultSettings() { } function doSomething(settings) { } // forgot to call `getDefaultSettings` -// but it is not caught because we don't check for call signatures doSomething(getDefaultSettings); -// same for arrow expressions: doSomething(function () { }); +doSomething(null); doSomething(12); doSomething('completely wrong'); doSomething(false); diff --git a/tests/cases/compiler/weakType.ts b/tests/cases/compiler/weakType.ts index ffe51205e53..8fda5df9166 100644 --- a/tests/cases/compiler/weakType.ts +++ b/tests/cases/compiler/weakType.ts @@ -6,13 +6,15 @@ interface Settings { function getDefaultSettings() { return { timeout: 1000 }; } +interface CtorOnly { + new(s: string): string +} function doSomething(settings: Settings) { /* ... */ } // forgot to call `getDefaultSettings` -// but it is not caught because we don't check for call signatures doSomething(getDefaultSettings); -// same for arrow expressions: doSomething(() => { }); +doSomething(null as CtorOnly); doSomething(12); doSomething('completely wrong'); doSomething(false); @@ -58,3 +60,4 @@ declare let unknown: { } } let weak: Weak & Spoiler = unknown + From b07aa0d97143cbcb5f15f005b00d0f4b36dbb981 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 7 Aug 2017 17:58:32 -0700 Subject: [PATCH 28/51] fix lint errors --- src/compiler/core.ts | 6 +++--- src/harness/unittests/matchFiles.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 07f979333b6..45602616640 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2021,16 +2021,16 @@ namespace ts { componentPattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter); - // Patterns should not include subfolders like node_modules unless they are + // Patterns should not include subfolders like node_modules unless they are // explicitly included as part of the path. // - // As an optimization, if the component pattern is the same as the component, + // As an optimization, if the component pattern is the same as the component, // then there definitely were no wildcard characters and we do not need to // add the exclusion pattern. if (componentPattern !== component) { subpattern += implicitExcludePathRegexPattern; } - + subpattern += componentPattern; } else { diff --git a/src/harness/unittests/matchFiles.ts b/src/harness/unittests/matchFiles.ts index 71b1bfff11a..9e2a5883754 100644 --- a/src/harness/unittests/matchFiles.ts +++ b/src/harness/unittests/matchFiles.ts @@ -1322,7 +1322,7 @@ namespace ts { }); }); }); - + describe("with files or folders that begin with a .", () => { it("that are not explicitly included", () => { const json = { From 813aaf40c01c4e46cb9a5477dcf1a65c031745d9 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 7 Aug 2017 18:20:57 -0700 Subject: [PATCH 29/51] fix lint errors --- src/harness/harness.ts | 2 +- src/lib/es2015.symbol.wellknown.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 55a8f3ebb4d..7122f55cae2 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -420,7 +420,7 @@ namespace Utils { const maxHarnessFrames = 1; - export function filterStack(error: Error, stackTraceLimit: number = Infinity) { + export function filterStack(error: Error, stackTraceLimit = Infinity) { const stack = (error).stack; if (stack) { const lines = stack.split(/\r\n?|\n/g); diff --git a/src/lib/es2015.symbol.wellknown.d.ts b/src/lib/es2015.symbol.wellknown.d.ts index 578cf0acbc2..b7c2610e652 100644 --- a/src/lib/es2015.symbol.wellknown.d.ts +++ b/src/lib/es2015.symbol.wellknown.d.ts @@ -110,7 +110,7 @@ interface Map { readonly [Symbol.toStringTag]: "Map"; } -interface WeakMap{ +interface WeakMap { readonly [Symbol.toStringTag]: "WeakMap"; } From 51e9aef2a7362cd82fce55901d0de82c521a8a89 Mon Sep 17 00:00:00 2001 From: Karlis Gangis Date: Tue, 8 Aug 2017 09:32:37 +0300 Subject: [PATCH 30/51] FileWatcher - handle empty directory path as the current directory Fixes #14559 --- src/compiler/sys.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 89cfb074bff..8a4c4ad22cc 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -153,7 +153,7 @@ namespace ts { return; } watcher = _fs.watch( - dirPath, + dirPath || ".", { persistent: true }, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath) ); From 9ea2350a6d8119156674759327333e6e2082ad10 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 07:31:21 -0700 Subject: [PATCH 31/51] Simplify parameters to updateProjectStructure and updateErrorCheck (#17175) --- src/server/session.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index 074ba4d6ca1..8fa580d7225 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -337,7 +337,7 @@ namespace ts.server { case ContextEvent: const { project, fileName } = event.data; this.projectService.logger.info(`got context event, updating diagnostics for ${fileName}`); - this.errorCheck.startNew(next => this.updateErrorCheck(next, [{ fileName, project }], this.changeSeq, (n) => n === this.changeSeq, 100)); + this.errorCheck.startNew(next => this.updateErrorCheck(next, [{ fileName, project }], 100)); break; case ConfigFileDiagEvent: const { triggerFile, configFileName, diagnostics } = event.data; @@ -453,22 +453,23 @@ namespace ts.server { } } - private updateProjectStructure(seq: number, matchSeq: (seq: number) => boolean, ms = 1500) { + private updateProjectStructure() { + const ms = 1500; + const seq = this.changeSeq; this.host.setTimeout(() => { - if (matchSeq(seq)) { + if (this.changeSeq === seq) { this.projectService.refreshInferredProjects(); } }, ms); } - private updateErrorCheck(next: NextStep, checkList: PendingErrorCheck[], seq: number, matchSeq: (seq: number) => boolean, ms = 1500, followMs = 200, requireOpen = true) { - if (followMs > ms) { - followMs = ms; - } + private updateErrorCheck(next: NextStep, checkList: PendingErrorCheck[], ms: number, requireOpen = true) { + const seq = this.changeSeq; + const followMs = Math.min(ms, 200); let index = 0; const checkOne = () => { - if (matchSeq(seq)) { + if (this.changeSeq === seq) { const checkSpec = checkList[index]; index++; if (checkSpec.project.containsFile(checkSpec.fileName, requireOpen)) { @@ -483,7 +484,7 @@ namespace ts.server { } }; - if ((checkList.length > index) && (matchSeq(seq))) { + if (checkList.length > index && this.changeSeq === seq) { next.delay(ms, checkOne); } } @@ -1262,14 +1263,14 @@ namespace ts.server { } private getDiagnostics(next: NextStep, delay: number, fileNames: string[]): void { - const checkList = mapDefined(fileNames, uncheckedFileName => { + const checkList = mapDefined(fileNames, uncheckedFileName => { const fileName = toNormalizedPath(uncheckedFileName); const project = this.projectService.getDefaultProjectForFile(fileName, /*refreshInferredProjects*/ true); return project && { fileName, project }; }); if (checkList.length > 0) { - this.updateErrorCheck(next, checkList, this.changeSeq, (n) => n === this.changeSeq, delay); + this.updateErrorCheck(next, checkList, delay); } } @@ -1283,7 +1284,7 @@ namespace ts.server { scriptInfo.editContent(start, end, args.insertString); this.changeSeq++; } - this.updateProjectStructure(this.changeSeq, n => n === this.changeSeq); + this.updateProjectStructure(); } } @@ -1638,7 +1639,7 @@ namespace ts.server { const checkList = fileNamesInProject.map(fileName => ({ fileName, project })); // Project level error analysis runs on background files too, therefore // doesn't require the file to be opened - this.updateErrorCheck(next, checkList, this.changeSeq, (n) => n === this.changeSeq, delay, 200, /*requireOpen*/ false); + this.updateErrorCheck(next, checkList, delay, /*requireOpen*/ false); } } From 382785a5282f6d49dae0f6af483c8acdaf89ed78 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 07:54:08 -0700 Subject: [PATCH 32/51] Fix logging of module resolution errors (#17144) --- src/compiler/moduleNameResolver.ts | 2 +- src/harness/harnessLanguageService.ts | 2 +- src/server/project.ts | 3 ++- src/server/server.ts | 2 -- src/server/types.ts | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 513c741ba09..be867db9743 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -678,7 +678,7 @@ namespace ts { const { resolvedModule, failedLookupLocations } = nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true); if (!resolvedModule) { - throw new Error(`Could not resolve JS module ${moduleName} starting at ${initialDir}. Looked in: ${failedLookupLocations.join(", ")}`); + throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`); } return resolvedModule.resolvedFileName; } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index c604b224656..994ebe67e0c 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -795,7 +795,7 @@ namespace Harness.LanguageService { default: return { module: undefined, - error: "Could not resolve module" + error: new Error("Could not resolve module") }; } diff --git a/src/server/project.ts b/src/server/project.ts index 524b6c4d28d..5a92e6505e0 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -170,7 +170,8 @@ namespace ts.server { log(`Loading ${moduleName} from ${initialDir} (resolved to ${resolvedPath})`); const result = host.require(resolvedPath, moduleName); if (result.error) { - log(`Failed to load module: ${JSON.stringify(result.error)}`); + const err = result.error.stack || result.error.message || JSON.stringify(result.error); + log(`Failed to load module '${moduleName}': ${err}`); return undefined; } return result.module; diff --git a/src/server/server.ts b/src/server/server.ts index b72cc2f5a81..d0044153b91 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -116,8 +116,6 @@ namespace ts.server { birthtime: Date; } - type RequireResult = { module: {}, error: undefined } | { module: undefined, error: {} }; - const readline: { createInterface(options: ReadLineOptions): NodeJS.EventEmitter; } = require("readline"); diff --git a/src/server/types.ts b/src/server/types.ts index 07b94fe827e..4fc4356a4a9 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -9,7 +9,7 @@ declare namespace ts.server { data: any; } - type RequireResult = { module: {}, error: undefined } | { module: undefined, error: {} }; + type RequireResult = { module: {}, error: undefined } | { module: undefined, error: { stack?: string, message?: string } }; export interface ServerHost extends System { setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; clearTimeout(timeoutId: any): void; From a9a30d76fb39a55d91f633b3555d90c4f438d9ae Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 07:55:03 -0700 Subject: [PATCH 33/51] Fix parsing of globalPlugins and pluginProbeLocations: Don't include empty string (#17143) --- src/server/server.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/server/server.ts b/src/server/server.ts index d0044153b91..2bf10964fa3 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -760,8 +760,16 @@ namespace ts.server { const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation); const npmLocation = findArgument(Arguments.NpmLocation); - const globalPlugins = (findArgument("--globalPlugins") || "").split(","); - const pluginProbeLocations = (findArgument("--pluginProbeLocations") || "").split(","); + function parseStringArray(argName: string): string[] { + const arg = findArgument(argName); + if (arg === undefined) { + return emptyArray as string[]; // TODO: https://github.com/Microsoft/TypeScript/issues/16312 + } + return arg.split(",").filter(name => name !== ""); + } + + const globalPlugins = parseStringArray("--globalPlugins"); + const pluginProbeLocations = parseStringArray("--pluginProbeLocations"); const allowLocalPluginLoads = hasArgument("--allowLocalPluginLoads"); const useSingleInferredProject = hasArgument("--useSingleInferredProject"); From ceae613e4c0ba36829a2381687883ecdc6b169c3 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 07:56:14 -0700 Subject: [PATCH 34/51] Add lint rule to check that `Debug.assert` calls do not eagerly interpolate strings (#17125) * And lint rule to check that `Debug.assert` calls do not eagerly interpolate strings * Use more specific 'assert' functions to avoid callbacks * Respond to PR feedback --- scripts/tslint/booleanTriviaRule.ts | 3 +- scripts/tslint/debugAssertRule.ts | 45 +++++++++++++++++++++++++ src/compiler/core.ts | 37 ++++++++++++++++---- src/compiler/transformers/generators.ts | 2 +- src/server/project.ts | 2 +- src/services/classifier.ts | 4 +-- src/services/services.ts | 2 +- src/services/signatureHelp.ts | 12 +++++-- src/services/transpile.ts | 4 +-- tslint.json | 1 + 10 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 scripts/tslint/debugAssertRule.ts diff --git a/scripts/tslint/booleanTriviaRule.ts b/scripts/tslint/booleanTriviaRule.ts index 189dafac77e..c498131be16 100644 --- a/scripts/tslint/booleanTriviaRule.ts +++ b/scripts/tslint/booleanTriviaRule.ts @@ -34,6 +34,7 @@ function walk(ctx: Lint.WalkContext): void { switch (methodName) { case "apply": case "assert": + case "assertEqual": case "call": case "equal": case "fail": @@ -69,7 +70,7 @@ function walk(ctx: Lint.WalkContext): void { const ranges = ts.getTrailingCommentRanges(sourceFile.text, arg.pos) || ts.getLeadingCommentRanges(sourceFile.text, arg.pos); if (ranges === undefined || ranges.length !== 1 || ranges[0].kind !== ts.SyntaxKind.MultiLineCommentTrivia) { - ctx.addFailureAtNode(arg, "Tag boolean argument with parameter name"); + ctx.addFailureAtNode(arg, "Tag argument with parameter name"); return; } diff --git a/scripts/tslint/debugAssertRule.ts b/scripts/tslint/debugAssertRule.ts new file mode 100644 index 00000000000..933b27697b0 --- /dev/null +++ b/scripts/tslint/debugAssertRule.ts @@ -0,0 +1,45 @@ +import * as Lint from "tslint/lib"; +import * as ts from "typescript"; + +export class Rule extends Lint.Rules.AbstractRule { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + return this.applyWithFunction(sourceFile, ctx => walk(ctx)); + } +} + +function walk(ctx: Lint.WalkContext): void { + ts.forEachChild(ctx.sourceFile, function recur(node) { + if (ts.isCallExpression(node)) { + checkCall(node); + } + ts.forEachChild(node, recur); + }); + + function checkCall(node: ts.CallExpression) { + if (!isDebugAssert(node.expression) || node.arguments.length < 2) { + return; + } + + const message = node.arguments[1]; + if (!ts.isStringLiteral(message)) { + ctx.addFailureAtNode(message, "Second argument to 'Debug.assert' should be a string literal."); + } + + if (node.arguments.length < 3) { + return; + } + + const message2 = node.arguments[2]; + if (!ts.isStringLiteral(message2) && !ts.isArrowFunction(message2)) { + ctx.addFailureAtNode(message, "Third argument to 'Debug.assert' should be a string literal or arrow function."); + } + } + + function isDebugAssert(expr: ts.Node): boolean { + return ts.isPropertyAccessExpression(expr) && isName(expr.expression, "Debug") && isName(expr.name, "assert"); + } + + function isName(expr: ts.Node, text: string): boolean { + return ts.isIdentifier(expr) && expr.text === text; + } +} diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f7ea0583670..bc131b201fd 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1290,12 +1290,12 @@ namespace ts { export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic { const end = start + length; - Debug.assert(start >= 0, "start must be non-negative, is " + start); - Debug.assert(length >= 0, "length must be non-negative, is " + length); + Debug.assertGreaterThanOrEqual(start, 0); + Debug.assertGreaterThanOrEqual(length, 0); if (file) { - Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${start} > ${file.text.length}`); - Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${end} > ${file.text.length}`); + Debug.assertLessThanOrEqual(start, file.text.length); + Debug.assertLessThanOrEqual(end, file.text.length); } let text = getLocaleSpecificMessage(message); @@ -2389,15 +2389,40 @@ namespace ts { return currentAssertionLevel >= level; } - export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string, stackCrawlMark?: Function): void { + export function assert(expression: boolean, message?: string, verboseDebugInfo?: string | (() => string), stackCrawlMark?: Function): void { if (!expression) { if (verboseDebugInfo) { - message += "\r\nVerbose Debug Information: " + verboseDebugInfo(); + message += "\r\nVerbose Debug Information: " + (typeof verboseDebugInfo === "string" ? verboseDebugInfo : verboseDebugInfo()); } fail(message ? "False expression: " + message : "False expression.", stackCrawlMark || assert); } } + export function assertEqual(a: T, b: T, msg?: string, msg2?: string): void { + if (a !== b) { + const message = msg ? msg2 ? `${msg} ${msg2}` : msg : ""; + fail(`Expected ${a} === ${b}. ${message}`); + } + } + + export function assertLessThan(a: number, b: number, msg?: string): void { + if (a >= b) { + fail(`Expected ${a} < ${b}. ${msg || ""}`); + } + } + + export function assertLessThanOrEqual(a: number, b: number): void { + if (a > b) { + fail(`Expected ${a} <= ${b}`); + } + } + + export function assertGreaterThanOrEqual(a: number, b: number): void { + if (a < b) { + fail(`Expected ${a} >= ${b}`); + } + } + export function fail(message?: string, stackCrawlMark?: Function): void { debugger; const e = new Error(message ? `Debug Failure. ${message}` : "Debug Failure."); diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 41edf24fe9e..5e2016ab590 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -2448,7 +2448,7 @@ namespace ts { * @param location An optional source map location for the statement. */ function createInlineBreak(label: Label, location?: TextRange): ReturnStatement { - Debug.assert(label > 0, `Invalid label: ${label}`); + Debug.assertLessThan(0, label, "Invalid label"); return setTextRange( createReturn( createArrayLiteral([ diff --git a/src/server/project.ts b/src/server/project.ts index 5a92e6505e0..844ded761d8 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -363,7 +363,7 @@ namespace ts.server { return map(this.program.getSourceFiles(), sourceFile => { const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.path); if (!scriptInfo) { - Debug.assert(false, `scriptInfo for a file '${sourceFile.fileName}' is missing.`); + Debug.fail(`scriptInfo for a file '${sourceFile.fileName}' is missing.`); } return scriptInfo; }); diff --git a/src/services/classifier.ts b/src/services/classifier.ts index dc5d99bc490..4552d8bf985 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -260,11 +260,11 @@ namespace ts { templateStack.pop(); } else { - Debug.assert(token === SyntaxKind.TemplateMiddle, "Should have been a template middle. Was " + token); + Debug.assertEqual(token, SyntaxKind.TemplateMiddle, "Should have been a template middle."); } } else { - Debug.assert(lastTemplateStackToken === SyntaxKind.OpenBraceToken, "Should have been an open brace. Was: " + token); + Debug.assertEqual(lastTemplateStackToken, SyntaxKind.OpenBraceToken, "Should have been an open brace"); templateStack.pop(); } } diff --git a/src/services/services.ts b/src/services/services.ts index 6a171ad9166..874c2feb107 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1258,7 +1258,7 @@ namespace ts { // We do not support the scenario where a host can modify a registered // file's script kind, i.e. in one project some file is treated as ".ts" // and in another as ".js" - Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + path); + Debug.assertEqual(hostFileInformation.scriptKind, oldSourceFile.scriptKind, "Registered script kind should match new script kind.", path); return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index f008c829116..2976b0d28ee 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -136,7 +136,9 @@ namespace ts.SignatureHelp { const kind = invocation.typeArguments && invocation.typeArguments.pos === list.pos ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments; const argumentCount = getArgumentCount(list); - Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`); + if (argumentIndex !== 0) { + Debug.assertLessThan(argumentIndex, argumentCount); + } const argumentsSpan = getApplicableSpanForArguments(list, sourceFile); return { kind, invocation, argumentsSpan, argumentIndex, argumentCount }; } @@ -270,7 +272,9 @@ namespace ts.SignatureHelp { ? 1 : (tagExpression.template).templateSpans.length + 1; - Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`); + if (argumentIndex !== 0) { + Debug.assertLessThan(argumentIndex, argumentCount); + } return { kind: ArgumentListKind.TaggedTemplateArguments, invocation: tagExpression, @@ -402,7 +406,9 @@ namespace ts.SignatureHelp { }; }); - Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`); + if (argumentIndex !== 0) { + Debug.assertLessThan(argumentIndex, argumentCount); + } const selectedItemIndex = candidates.indexOf(resolvedSignature); Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function. diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 561c188c6cd..79a69b886d9 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -78,11 +78,11 @@ namespace ts { getSourceFile: (fileName) => fileName === normalizePath(inputFileName) ? sourceFile : undefined, writeFile: (name, text) => { if (fileExtensionIs(name, ".map")) { - Debug.assert(sourceMapText === undefined, `Unexpected multiple source map outputs for the file '${name}'`); + Debug.assertEqual(sourceMapText, undefined, "Unexpected multiple source map outputs, file:", name); sourceMapText = text; } else { - Debug.assert(outputText === undefined, `Unexpected multiple outputs for the file: '${name}'`); + Debug.assertEqual(outputText, undefined, "Unexpected multiple outputs, file:", name); outputText = text; } }, diff --git a/tslint.json b/tslint.json index bcd4dfa2223..de60ad7683a 100644 --- a/tslint.json +++ b/tslint.json @@ -7,6 +7,7 @@ "check-space" ], "curly":[true, "ignore-same-line"], + "debug-assert": true, "indent": [true, "spaces" ], From e1802f49660a30df702c160f4ed001ccacdb33e3 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 10:49:49 -0700 Subject: [PATCH 35/51] MultistepOperation: Don't need 'completed', just use `requestId === undefined` (#17173) * MultistepOperation: Don't need 'completed', just use `requestId === undefined` * Check for `requestId !== undefined` --- src/server/session.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index 8fa580d7225..5c9d210939c 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -163,26 +163,22 @@ namespace ts.server { * Scheduling is done via instance of NextStep. If on current step subsequent step was not scheduled - operation is assumed to be completed. */ class MultistepOperation implements NextStep { - private requestId: number; + private requestId: number | undefined; private timerHandle: any; - private immediateId: any; - private completed = true; + private immediateId: number | undefined; constructor(private readonly operationHost: MultistepOperationHost) {} public startNew(action: (next: NextStep) => void) { this.complete(); this.requestId = this.operationHost.getCurrentRequestId(); - this.completed = false; this.executeAction(action); } private complete() { - if (!this.completed) { - if (this.requestId) { - this.operationHost.sendRequestCompletedEvent(this.requestId); - } - this.completed = true; + if (this.requestId !== undefined) { + this.operationHost.sendRequestCompletedEvent(this.requestId); + this.requestId = undefined; } this.setTimerHandle(undefined); this.setImmediateId(undefined); From f69ce5c0c8930a4a4912014e41fe6487410acb3d Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 10:54:18 -0700 Subject: [PATCH 36/51] Convert two arrays to readonly (#17685) --- src/server/editorServices.ts | 4 ++-- src/server/server.ts | 8 ++++---- src/server/session.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 4ffdf5d6c5d..5bb1da251ea 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -326,8 +326,8 @@ namespace ts.server { typingsInstaller: ITypingsInstaller; eventHandler?: ProjectServiceEventHandler; throttleWaitMilliseconds?: number; - globalPlugins?: string[]; - pluginProbeLocations?: string[]; + globalPlugins?: ReadonlyArray; + pluginProbeLocations?: ReadonlyArray; allowLocalPluginLoads?: boolean; } diff --git a/src/server/server.ts b/src/server/server.ts index 2bf10964fa3..6b89019632f 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -15,8 +15,8 @@ namespace ts.server { typingSafeListLocation: string; npmLocation: string | undefined; telemetryEnabled: boolean; - globalPlugins: string[]; - pluginProbeLocations: string[]; + globalPlugins: ReadonlyArray; + pluginProbeLocations: ReadonlyArray; allowLocalPluginLoads: boolean; } @@ -760,10 +760,10 @@ namespace ts.server { const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation); const npmLocation = findArgument(Arguments.NpmLocation); - function parseStringArray(argName: string): string[] { + function parseStringArray(argName: string): ReadonlyArray { const arg = findArgument(argName); if (arg === undefined) { - return emptyArray as string[]; // TODO: https://github.com/Microsoft/TypeScript/issues/16312 + return emptyArray; } return arg.split(",").filter(name => name !== ""); } diff --git a/src/server/session.ts b/src/server/session.ts index 5c9d210939c..d8e0f695def 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -255,8 +255,8 @@ namespace ts.server { eventHandler?: ProjectServiceEventHandler; throttleWaitMilliseconds?: number; - globalPlugins?: string[]; - pluginProbeLocations?: string[]; + globalPlugins?: ReadonlyArray; + pluginProbeLocations?: ReadonlyArray; allowLocalPluginLoads?: boolean; } From 5141ce751d9887a8b402a34d66c63581c17aed00 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 11:02:10 -0700 Subject: [PATCH 37/51] Deduplicate unresolvedImports (#17248) * Deduplicate unresolvedImports * Add `isNonDuplicateInSortedArray` helper --- src/compiler/core.ts | 8 ++++---- src/server/project.ts | 4 ++-- src/server/utilities.ts | 9 +++++++++ src/services/jsTyping.ts | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index bc131b201fd..d5c8396d06d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -361,11 +361,11 @@ namespace ts { return false; } - export function filterMutate(array: T[], f: (x: T) => boolean): void { + export function filterMutate(array: T[], f: (x: T, i: number, array: T[]) => boolean): void { let outIndex = 0; - for (const item of array) { - if (f(item)) { - array[outIndex] = item; + for (let i = 0; i < array.length; i++) { + if (f(array[i], i, array)) { + array[outIndex] = array[i]; outIndex++; } } diff --git a/src/server/project.ts b/src/server/project.ts index 844ded761d8..97c8eb706f3 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -495,7 +495,7 @@ namespace ts.server { this.projectStateVersion++; } - private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: string[]) { + private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: Push) { const cached = this.cachedUnresolvedImportsPerFile.get(file.path); if (cached) { // found cached result - use it and return @@ -555,7 +555,7 @@ namespace ts.server { for (const sourceFile of this.program.getSourceFiles()) { this.extractUnresolvedImportsFromSourceFile(sourceFile, result); } - this.lastCachedUnresolvedImportsList = toSortedArray(result); + this.lastCachedUnresolvedImportsList = toDeduplicatedSortedArray(result); } unresolvedImports = this.lastCachedUnresolvedImportsList; diff --git a/src/server/utilities.ts b/src/server/utilities.ts index fc88f11408a..5efb20d074f 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -262,6 +262,15 @@ namespace ts.server { return arr as SortedArray; } + export function toDeduplicatedSortedArray(arr: string[]): SortedArray { + arr.sort(); + filterMutate(arr, isNonDuplicateInSortedArray); + return arr as SortedArray; + } + function isNonDuplicateInSortedArray(value: T, index: number, array: T[]) { + return index === 0 || value !== array[index - 1]; + } + export function enumerateInsertsAndDeletes(newItems: SortedReadonlyArray, oldItems: SortedReadonlyArray, inserted: (newItem: T) => void, deleted: (oldItem: T) => void, compare?: Comparer) { compare = compare || compareValues; let newIndex = 0; diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 4de7bb3191d..5e7b7d424f8 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -35,7 +35,7 @@ namespace ts.JsTyping { "crypto", "stream", "util", "assert", "tty", "domain", "constants", "process", "v8", "timers", "console"]; - const nodeCoreModules = arrayToMap(nodeCoreModuleList, x => x); + const nodeCoreModules = arrayToSet(nodeCoreModuleList); /** * A map of loose file names to library names that we are confident require typings From eb8bcd77cba70b2dcafaaa687aeac06500f717d8 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 11:02:53 -0700 Subject: [PATCH 38/51] tsserverProjectSystem.ts: Remove unnecessary 'export's (#17201) * tsserverProjectSystem.ts: Remove unnecessary 'export's * Export `PostExecAction` --- .../unittests/tsserverProjectSystem.ts | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 4a7cafa245b..e2b516ddae6 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -45,7 +45,7 @@ namespace ts.projectSystem { getLogFileName: (): string => undefined }; - export const { content: libFileContent } = Harness.getDefaultLibraryFile(Harness.IO); + const { content: libFileContent } = Harness.getDefaultLibraryFile(Harness.IO); export const libFile: FileOrFolder = { path: "/a/lib/lib.d.ts", content: libFileContent @@ -118,7 +118,7 @@ namespace ts.projectSystem { return JSON.stringify({ dependencies }); } - export function getExecutingFilePathFromLibFile(): string { + function getExecutingFilePathFromLibFile(): string { return combinePaths(getDirectoryPath(libFile.path), "tsc.js"); } @@ -130,7 +130,7 @@ namespace ts.projectSystem { return map(fileNames, toExternalFile); } - export class TestServerEventManager { + class TestServerEventManager { public events: server.ProjectServiceEvent[] = []; handler: server.ProjectServiceEventHandler = (event: server.ProjectServiceEvent) => { @@ -143,7 +143,7 @@ namespace ts.projectSystem { } } - export interface TestServerHostCreationParameters { + interface TestServerHostCreationParameters { useCaseSensitiveFileNames?: boolean; executingFilePath?: string; currentDirectory?: string; @@ -205,7 +205,7 @@ namespace ts.projectSystem { return new TestSession(opts); } - export interface CreateProjectServiceParameters { + interface CreateProjectServiceParameters { cancellationToken?: HostCancellationToken; logger?: server.Logger; useSingleInferredProject?: boolean; @@ -253,15 +253,15 @@ namespace ts.projectSystem { entries: FSEntry[]; } - export function isFolder(s: FSEntry): s is Folder { + function isFolder(s: FSEntry): s is Folder { return isArray((s).entries); } - export function isFile(s: FSEntry): s is File { + function isFile(s: FSEntry): s is File { return typeof (s).content === "string"; } - export function addFolder(fullPath: string, toPath: (s: string) => Path, fs: Map): Folder { + function addFolder(fullPath: string, toPath: (s: string) => Path, fs: Map): Folder { const path = toPath(fullPath); if (fs.has(path)) { Debug.assert(isFolder(fs.get(path))); @@ -279,29 +279,29 @@ namespace ts.projectSystem { return entry; } - export function checkMapKeys(caption: string, map: Map, expectedKeys: string[]) { + function checkMapKeys(caption: string, map: Map, expectedKeys: string[]) { assert.equal(map.size, expectedKeys.length, `${caption}: incorrect size of map`); for (const name of expectedKeys) { assert.isTrue(map.has(name), `${caption} is expected to contain ${name}, actual keys: ${arrayFrom(map.keys())}`); } } - export function checkFileNames(caption: string, actualFileNames: string[], expectedFileNames: string[]) { + function checkFileNames(caption: string, actualFileNames: string[], expectedFileNames: string[]) { assert.equal(actualFileNames.length, expectedFileNames.length, `${caption}: incorrect actual number of files, expected ${JSON.stringify(expectedFileNames)}, got ${actualFileNames}`); for (const f of expectedFileNames) { assert.isTrue(contains(actualFileNames, f), `${caption}: expected to find ${f} in ${JSON.stringify(actualFileNames)}`); } } - export function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) { + function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) { assert.equal(projectService.configuredProjects.length, expected, `expected ${expected} configured project(s)`); } - export function checkNumberOfExternalProjects(projectService: server.ProjectService, expected: number) { + function checkNumberOfExternalProjects(projectService: server.ProjectService, expected: number) { assert.equal(projectService.externalProjects.length, expected, `expected ${expected} external project(s)`); } - export function checkNumberOfInferredProjects(projectService: server.ProjectService, expected: number) { + function checkNumberOfInferredProjects(projectService: server.ProjectService, expected: number) { assert.equal(projectService.inferredProjects.length, expected, `expected ${expected} inferred project(s)`); } @@ -315,7 +315,7 @@ namespace ts.projectSystem { checkMapKeys("watchedFiles", host.watchedFiles, expectedFiles); } - export function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[]) { + function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[]) { checkMapKeys("watchedDirectories", host.watchedDirectories, expectedDirectories); } @@ -323,11 +323,11 @@ namespace ts.projectSystem { checkFileNames(`${server.ProjectKind[project.projectKind]} project, actual files`, project.getFileNames(), expectedFiles); } - export function checkProjectRootFiles(project: server.Project, expectedFiles: string[]) { + function checkProjectRootFiles(project: server.Project, expectedFiles: string[]) { checkFileNames(`${server.ProjectKind[project.projectKind]} project, rootFileNames`, project.getRootFiles(), expectedFiles); } - export class Callbacks { + class Callbacks { private map: TimeOutCallback[] = []; private nextId = 1; @@ -363,7 +363,7 @@ namespace ts.projectSystem { } } - export type TimeOutCallback = () => any; + type TimeOutCallback = () => any; export class TestServerHost implements server.ServerHost { args: string[] = []; From 94518e853303b4a4a5cb178976593a6c4e319082 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 11:18:20 -0700 Subject: [PATCH 39/51] Don't count self-reference when setting `isReferenced` (#17495) * Don't count self-reference when setting `isReferenced` * Improve comment --- src/compiler/checker.ts | 25 ++-------- .../noUnusedLocals_selfReference.errors.txt | 28 +++++++++++ .../reference/noUnusedLocals_selfReference.js | 49 +++++++++++++++++++ ...LocalsAndParametersTypeAliases2.errors.txt | 5 +- .../compiler/noUnusedLocals_selfReference.ts | 17 +++++++ tests/webTestServer.ts | 16 ------ 6 files changed, 102 insertions(+), 38 deletions(-) create mode 100644 tests/baselines/reference/noUnusedLocals_selfReference.errors.txt create mode 100644 tests/baselines/reference/noUnusedLocals_selfReference.js create mode 100644 tests/cases/compiler/noUnusedLocals_selfReference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 10400a3853a..1113d131a03 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1086,7 +1086,10 @@ namespace ts { location = location.parent; } - if (result && nameNotFoundMessage && noUnusedIdentifiers) { + // We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`. + // If `result === lastLocation.symbol`, that means that we are somewhere inside `lastLocation` looking up a name, and resolving to `lastLocation` itself. + // That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used. + if (result && nameNotFoundMessage && noUnusedIdentifiers && result !== lastLocation.symbol) { result.isReferenced = true; } @@ -10800,17 +10803,6 @@ namespace ts { return undefined; } - function getLeftmostIdentifierOrThis(node: Node): Node { - switch (node.kind) { - case SyntaxKind.Identifier: - case SyntaxKind.ThisKeyword: - return node; - case SyntaxKind.PropertyAccessExpression: - return getLeftmostIdentifierOrThis((node).expression); - } - return undefined; - } - function getBindingElementNameText(element: BindingElement): string | undefined { if (element.parent.kind === SyntaxKind.ObjectBindingPattern) { const name = element.propertyName || element.name; @@ -18520,15 +18512,6 @@ namespace ts { return forEachChild(n, containsSuperCall); } - function markThisReferencesAsErrors(n: Node): void { - if (n.kind === SyntaxKind.ThisKeyword) { - error(n, Diagnostics.this_cannot_be_referenced_in_current_location); - } - else if (n.kind !== SyntaxKind.FunctionExpression && n.kind !== SyntaxKind.FunctionDeclaration) { - forEachChild(n, markThisReferencesAsErrors); - } - } - function isInstancePropertyWithInitializer(n: Node): boolean { return n.kind === SyntaxKind.PropertyDeclaration && !(getModifierFlags(n) & ModifierFlags.Static) && diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt new file mode 100644 index 00000000000..af40081e71c --- /dev/null +++ b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt @@ -0,0 +1,28 @@ +tests/cases/compiler/noUnusedLocals_selfReference.ts(3,10): error TS6133: 'f' is declared but never used. +tests/cases/compiler/noUnusedLocals_selfReference.ts(4,7): error TS6133: 'C' is declared but never used. +tests/cases/compiler/noUnusedLocals_selfReference.ts(7,6): error TS6133: 'E' is declared but never used. + + +==== tests/cases/compiler/noUnusedLocals_selfReference.ts (3 errors) ==== + export {}; // Make this a module scope, so these are local variables. + + function f() { f; } + ~ +!!! error TS6133: 'f' is declared but never used. + class C { + ~ +!!! error TS6133: 'C' is declared but never used. + m() { C; } + } + enum E { A = 0, B = E.A } + ~ +!!! error TS6133: 'E' is declared but never used. + + // Does not detect mutual recursion. + function g() { D; } + class D { m() { g; } } + + // Does not work on private methods. + class P { private m() { this.m; } } + P; + \ No newline at end of file diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.js b/tests/baselines/reference/noUnusedLocals_selfReference.js new file mode 100644 index 00000000000..74a39923d57 --- /dev/null +++ b/tests/baselines/reference/noUnusedLocals_selfReference.js @@ -0,0 +1,49 @@ +//// [noUnusedLocals_selfReference.ts] +export {}; // Make this a module scope, so these are local variables. + +function f() { f; } +class C { + m() { C; } +} +enum E { A = 0, B = E.A } + +// Does not detect mutual recursion. +function g() { D; } +class D { m() { g; } } + +// Does not work on private methods. +class P { private m() { this.m; } } +P; + + +//// [noUnusedLocals_selfReference.js] +"use strict"; +exports.__esModule = true; +function f() { f; } +var C = (function () { + function C() { + } + C.prototype.m = function () { C; }; + return C; +}()); +var E; +(function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 0] = "B"; +})(E || (E = {})); +// Does not detect mutual recursion. +function g() { D; } +var D = (function () { + function D() { + } + D.prototype.m = function () { g; }; + return D; +}()); +// Does not work on private methods. +var P = (function () { + function P() { + } + P.prototype.m = function () { this.m; }; + return P; +}()); +P; diff --git a/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt index 528ca9f9e73..e5c6f476480 100644 --- a/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt +++ b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt @@ -1,8 +1,9 @@ tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts(2,6): error TS6133: 'handler1' is declared but never used. +tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts(5,10): error TS6133: 'foo' is declared but never used. tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts(6,10): error TS6133: 'handler2' is declared but never used. -==== tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts (2 errors) ==== +==== tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts (3 errors) ==== // unused type handler1 = () => void; ~~~~~~~~ @@ -10,6 +11,8 @@ tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts(6,10): error TS613 function foo() { + ~~~ +!!! error TS6133: 'foo' is declared but never used. type handler2 = () => void; ~~~~~~~~ !!! error TS6133: 'handler2' is declared but never used. diff --git a/tests/cases/compiler/noUnusedLocals_selfReference.ts b/tests/cases/compiler/noUnusedLocals_selfReference.ts new file mode 100644 index 00000000000..8eb528743c0 --- /dev/null +++ b/tests/cases/compiler/noUnusedLocals_selfReference.ts @@ -0,0 +1,17 @@ +// @noUnusedLocals: true + +export {}; // Make this a module scope, so these are local variables. + +function f() { f; } +class C { + m() { C; } +} +enum E { A = 0, B = E.A } + +// Does not detect mutual recursion. +function g() { D; } +class D { m() { g; } } + +// Does not work on private methods. +class P { private m() { this.m; } } +P; diff --git a/tests/webTestServer.ts b/tests/webTestServer.ts index abfd71a8fff..20228f9a741 100644 --- a/tests/webTestServer.ts +++ b/tests/webTestServer.ts @@ -125,22 +125,6 @@ function dir(dirPath: string, spec?: string, options?: any) { } } -// fs.rmdirSync won't delete directories with files in it -function deleteFolderRecursive(dirPath: string) { - if (fs.existsSync(dirPath)) { - fs.readdirSync(dirPath).forEach((file) => { - const curPath = path.join(dirPath, file); - if (fs.statSync(curPath).isDirectory()) { // recurse - deleteFolderRecursive(curPath); - } - else { // delete file - fs.unlinkSync(curPath); - } - }); - fs.rmdirSync(dirPath); - } -}; - function writeFile(path: string, data: any) { ensureDirectoriesExist(getDirectoryPath(path)); fs.writeFileSync(path, data); From d99a492ddd7f30450268ed49fa1be308ee43690d Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 11:22:22 -0700 Subject: [PATCH 40/51] Simplify server logger (#17271) * Simplify server logger * Move function printProjects out of inner closure --- src/harness/harnessLanguageService.ts | 13 ++-- .../unittests/cachingInServerLSHost.ts | 14 +--- src/harness/unittests/session.ts | 18 +----- .../unittests/tsserverProjectSystem.ts | 13 ++-- src/server/editorServices.ts | 30 ++++----- src/server/server.ts | 64 ++++++++++--------- src/server/session.ts | 4 +- src/server/utilities.ts | 15 +---- 8 files changed, 67 insertions(+), 104 deletions(-) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 994ebe67e0c..af5a998df99 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -681,11 +681,11 @@ namespace Harness.LanguageService { } info(message: string): void { - return this.host.log(message); + this.host.log(message); } - msg(message: string) { - return this.host.log(message); + err(message: string): void { + this.host.log(message); } loggingEnabled() { @@ -700,17 +700,12 @@ namespace Harness.LanguageService { return false; } - - endGroup(): void { - } + group() { throw ts.notImplemented(); } perftrc(message: string): void { return this.host.log(message); } - startGroup(): void { - } - setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any { return setTimeout(callback, ms, args); } diff --git a/src/harness/unittests/cachingInServerLSHost.ts b/src/harness/unittests/cachingInServerLSHost.ts index eb2907e89de..92c10c1ff6d 100644 --- a/src/harness/unittests/cachingInServerLSHost.ts +++ b/src/harness/unittests/cachingInServerLSHost.ts @@ -52,21 +52,9 @@ namespace ts { } function createProject(rootFile: string, serverHost: server.ServerHost): { project: server.Project, rootScriptInfo: server.ScriptInfo } { - const logger: server.Logger = { - close: noop, - hasLevel: () => false, - loggingEnabled: () => false, - perftrc: noop, - info: noop, - startGroup: noop, - endGroup: noop, - msg: noop, - getLogFileName: (): string => undefined - }; - const svcOpts: server.ProjectServiceOptions = { host: serverHost, - logger, + logger: projectSystem.nullLogger, cancellationToken: { isCancellationRequested: () => false }, useSingleInferredProject: false, typingsInstaller: undefined diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 862ebee4b03..1ce5792a81b 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -28,18 +28,6 @@ namespace ts.server { createHash: Harness.LanguageService.mockHash, }; - const mockLogger: Logger = { - close: noop, - hasLevel(): boolean { return false; }, - loggingEnabled(): boolean { return false; }, - perftrc: noop, - info: noop, - startGroup: noop, - endGroup: noop, - msg: noop, - getLogFileName: (): string => undefined - }; - class TestSession extends Session { getProjectService() { return this.projectService; @@ -58,7 +46,7 @@ namespace ts.server { typingsInstaller: undefined, byteLength: Utils.byteLength, hrtime: process.hrtime, - logger: mockLogger, + logger: projectSystem.nullLogger, canUseEvents: true }; return new TestSession(opts); @@ -408,7 +396,7 @@ namespace ts.server { typingsInstaller: undefined, byteLength: Utils.byteLength, hrtime: process.hrtime, - logger: mockLogger, + logger: projectSystem.nullLogger, canUseEvents: true }); this.addProtocolHandler(this.customHandler, () => { @@ -475,7 +463,7 @@ namespace ts.server { typingsInstaller: undefined, byteLength: Utils.byteLength, hrtime: process.hrtime, - logger: mockLogger, + logger: projectSystem.nullLogger, canUseEvents: true }); this.addProtocolHandler("echo", (req: protocol.Request) => ({ diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index e2b516ddae6..6c60160740e 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -34,14 +34,13 @@ namespace ts.projectSystem { } export const nullLogger: server.Logger = { - close: () => void 0, - hasLevel: () => void 0, + close: noop, + hasLevel: () => false, loggingEnabled: () => false, - perftrc: () => void 0, - info: () => void 0, - startGroup: () => void 0, - endGroup: () => void 0, - msg: () => void 0, + perftrc: noop, + info: noop, + err: noop, + group: noop, getLogFileName: (): string => undefined }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 5bb1da251ea..554ac337920 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -928,26 +928,24 @@ namespace ts.server { return; } - this.logger.startGroup(); + this.logger.group(info => { + let counter = 0; + counter = printProjects(this.externalProjects, info, counter); + counter = printProjects(this.configuredProjects, info, counter); + printProjects(this.inferredProjects, info, counter); - let counter = 0; - counter = printProjects(this.logger, this.externalProjects, counter); - counter = printProjects(this.logger, this.configuredProjects, counter); - counter = printProjects(this.logger, this.inferredProjects, counter); + info("Open files: "); + for (const rootFile of this.openFiles) { + info(`\t${rootFile.fileName}`); + } + }); - this.logger.info("Open files: "); - for (const rootFile of this.openFiles) { - this.logger.info(`\t${rootFile.fileName}`); - } - - this.logger.endGroup(); - - function printProjects(logger: Logger, projects: Project[], counter: number) { + function printProjects(projects: Project[], info: (msg: string) => void, counter: number): number { for (const project of projects) { project.updateGraph(); - logger.info(`Project '${project.getProjectName()}' (${ProjectKind[project.projectKind]}) ${counter}`); - logger.info(project.filesToString()); - logger.info("-----------------------------------------------"); + info(`Project '${project.getProjectName()}' (${ProjectKind[project.projectKind]}) ${counter}`); + info(project.filesToString()); + info("-----------------------------------------------"); counter++; } return counter; diff --git a/src/server/server.ts b/src/server/server.ts index 6b89019632f..47a858c0efd 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -139,8 +139,6 @@ namespace ts.server { class Logger implements server.Logger { private fd = -1; private seq = 0; - private inGroup = false; - private firstInGroup = true; constructor(private readonly logFilename: string, private readonly traceToConsole: boolean, @@ -170,22 +168,24 @@ namespace ts.server { } perftrc(s: string) { - this.msg(s, Msg.Perf); + this.msg(s, "Perf"); } info(s: string) { - this.msg(s, Msg.Info); + this.msg(s, "Info"); } - startGroup() { - this.inGroup = true; - this.firstInGroup = true; + err(s: string) { + this.msg(s, "Err"); } - endGroup() { - this.inGroup = false; + group(logGroupEntries: (log: (msg: string) => void) => void) { + let firstInGroup = false; + logGroupEntries(s => { + this.msg(s, "Info", /*inGroup*/ true, firstInGroup); + firstInGroup = false; + }); this.seq++; - this.firstInGroup = true; } loggingEnabled() { @@ -196,26 +196,32 @@ namespace ts.server { return this.loggingEnabled() && this.level >= level; } - msg(s: string, type: Msg.Types = Msg.Err) { - if (this.fd >= 0 || this.traceToConsole) { - s = `[${nowString()}] ${s}\n`; + private msg(s: string, type: string, inGroup = false, firstInGroup = false) { + if (!this.canWrite) return; + + s = `[${nowString()}] ${s}\n`; + if (!inGroup || firstInGroup) { const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " "); - if (this.firstInGroup) { - s = prefix + s; - this.firstInGroup = false; - } - if (!this.inGroup) { - this.seq++; - this.firstInGroup = true; - } - if (this.fd >= 0) { - const buf = new Buffer(s); - // tslint:disable-next-line no-null-keyword - fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); - } - if (this.traceToConsole) { - console.warn(s); - } + s = prefix + s; + } + this.write(s); + if (!inGroup) { + this.seq++; + } + } + + private get canWrite() { + return this.fd >= 0 || this.traceToConsole; + } + + private write(s: string) { + if (this.fd >= 0) { + const buf = new Buffer(s); + // tslint:disable-next-line no-null-keyword + fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); + } + if (this.traceToConsole) { + console.warn(s); } } } diff --git a/src/server/session.ts b/src/server/session.ts index d8e0f695def..3c9c1b714de 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -366,7 +366,7 @@ namespace ts.server { msg += "\n" + (err).stack; } } - this.logger.msg(msg, Msg.Err); + this.logger.err(msg); } public send(msg: protocol.Message) { @@ -1946,7 +1946,7 @@ namespace ts.server { return this.executeWithRequestId(request.seq, () => handler(request)); } else { - this.logger.msg(`Unrecognized JSON command: ${JSON.stringify(request)}`, Msg.Err); + this.logger.err(`Unrecognized JSON command: ${JSON.stringify(request)}`); this.output(undefined, CommandNames.Unknown, request.seq, `Unrecognized JSON command: ${request.command}`); return { responseRequired: false }; } diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 5efb20d074f..0d4bc101ff6 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -17,22 +17,11 @@ namespace ts.server { loggingEnabled(): boolean; perftrc(s: string): void; info(s: string): void; - startGroup(): void; - endGroup(): void; - msg(s: string, type?: Msg.Types): void; + err(s: string): void; + group(logGroupEntries: (log: (msg: string) => void) => void): void; getLogFileName(): string; } - export namespace Msg { - export type Err = "Err"; - export const Err: Err = "Err"; - export type Info = "Info"; - export const Info: Info = "Info"; - export type Perf = "Perf"; - export const Perf: Perf = "Perf"; - export type Types = Err | Info | Perf; - } - function getProjectRootPath(project: Project): Path { switch (project.projectKind) { case ProjectKind.Configured: From 7ff1d8e797afee9b20ce233a1fbe15a19af2f56c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 8 Aug 2017 11:25:32 -0700 Subject: [PATCH 41/51] Add specific weak type error for callable types "Did you mean to call it?" --- src/compiler/checker.ts | 10 +++++++++- src/compiler/diagnosticMessages.json | 4 ++++ tests/baselines/reference/weakType.errors.txt | 18 +++++++++--------- tests/baselines/reference/weakType.js | 6 +++--- tests/cases/compiler/weakType.ts | 4 ++-- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4dd2058d4d3..2b910e6abb8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8944,7 +8944,15 @@ namespace ts { isWeakType(target) && !hasCommonProperties(source, target)) { if (reportErrors) { - reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target)); + const calls = getSignaturesOfType(source, SignatureKind.Call); + const constructs = getSignaturesOfType(source, SignatureKind.Construct); + if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, /*reportErrors*/ false) || + constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, /*reportErrors*/ false)) { + reportError(Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, typeToString(source), typeToString(target)); + } + else { + reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target)); + } } return Ternary.False; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3b4b0ddf667..03164c54ffd 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1908,6 +1908,10 @@ "category": "Error", "code": 2559 }, + "Value of type '{0}' has no properties in common with type '{1}'. Did you mean to call it?": { + "category": "Error", + "code": 2560 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 diff --git a/tests/baselines/reference/weakType.errors.txt b/tests/baselines/reference/weakType.errors.txt index b08dcc33980..ffc1d237593 100644 --- a/tests/baselines/reference/weakType.errors.txt +++ b/tests/baselines/reference/weakType.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/weakType.ts(15,13): error TS2559: Type '() => { timeout: number; }' has no properties in common with type 'Settings'. -tests/cases/compiler/weakType.ts(16,13): error TS2559: Type '() => void' has no properties in common with type 'Settings'. -tests/cases/compiler/weakType.ts(17,13): error TS2559: Type 'CtorOnly' has no properties in common with type 'Settings'. +tests/cases/compiler/weakType.ts(15,13): error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it? +tests/cases/compiler/weakType.ts(16,13): error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it? +tests/cases/compiler/weakType.ts(17,13): error TS2560: Value of type 'CtorOnly' has no properties in common with type 'Settings'. Did you mean to call it? tests/cases/compiler/weakType.ts(18,13): error TS2559: Type '12' has no properties in common with type 'Settings'. tests/cases/compiler/weakType.ts(19,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'. tests/cases/compiler/weakType.ts(20,13): error TS2559: Type 'false' has no properties in common with type 'Settings'. @@ -21,20 +21,20 @@ tests/cases/compiler/weakType.ts(62,5): error TS2322: Type '{ properties: { wron return { timeout: 1000 }; } interface CtorOnly { - new(s: string): string + new(s: string): { timeout: 1000 } } function doSomething(settings: Settings) { /* ... */ } // forgot to call `getDefaultSettings` doSomething(getDefaultSettings); ~~~~~~~~~~~~~~~~~~ -!!! error TS2559: Type '() => { timeout: number; }' has no properties in common with type 'Settings'. - doSomething(() => { }); - ~~~~~~~~~ -!!! error TS2559: Type '() => void' has no properties in common with type 'Settings'. +!!! error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it? + doSomething(() => ({ timeout: 1000 })); + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it? doSomething(null as CtorOnly); ~~~~~~~~~~~~~~~~ -!!! error TS2559: Type 'CtorOnly' has no properties in common with type 'Settings'. +!!! error TS2560: Value of type 'CtorOnly' has no properties in common with type 'Settings'. Did you mean to call it? doSomething(12); ~~ !!! error TS2559: Type '12' has no properties in common with type 'Settings'. diff --git a/tests/baselines/reference/weakType.js b/tests/baselines/reference/weakType.js index 999269384dc..2a1dc4ca0e4 100644 --- a/tests/baselines/reference/weakType.js +++ b/tests/baselines/reference/weakType.js @@ -8,13 +8,13 @@ function getDefaultSettings() { return { timeout: 1000 }; } interface CtorOnly { - new(s: string): string + new(s: string): { timeout: 1000 } } function doSomething(settings: Settings) { /* ... */ } // forgot to call `getDefaultSettings` doSomething(getDefaultSettings); -doSomething(() => { }); +doSomething(() => ({ timeout: 1000 })); doSomething(null as CtorOnly); doSomething(12); doSomething('completely wrong'); @@ -71,7 +71,7 @@ function getDefaultSettings() { function doSomething(settings) { } // forgot to call `getDefaultSettings` doSomething(getDefaultSettings); -doSomething(function () { }); +doSomething(function () { return ({ timeout: 1000 }); }); doSomething(null); doSomething(12); doSomething('completely wrong'); diff --git a/tests/cases/compiler/weakType.ts b/tests/cases/compiler/weakType.ts index 8fda5df9166..08c9d95e672 100644 --- a/tests/cases/compiler/weakType.ts +++ b/tests/cases/compiler/weakType.ts @@ -7,13 +7,13 @@ function getDefaultSettings() { return { timeout: 1000 }; } interface CtorOnly { - new(s: string): string + new(s: string): { timeout: 1000 } } function doSomething(settings: Settings) { /* ... */ } // forgot to call `getDefaultSettings` doSomething(getDefaultSettings); -doSomething(() => { }); +doSomething(() => ({ timeout: 1000 })); doSomething(null as CtorOnly); doSomething(12); doSomething('completely wrong'); From 85f59098d3e16010bff6f82a1e9b7ee33b9a6859 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 11:38:41 -0700 Subject: [PATCH 42/51] validateSpecs: Use array helpers (#17275) * validateSpecs: Use array helpers * Make filter predicate smaller * forEach -> for-of --- src/compiler/commandLineParser.ts | 34 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index b0cb7f94029..e82e70dc764 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -2011,23 +2011,13 @@ namespace ts { } function validateSpecs(specs: ReadonlyArray, errors: Push, allowTrailingRecursion: boolean, jsonSourceFile: JsonSourceFile, specKey: string) { - const validSpecs: string[] = []; - for (const spec of specs) { - if (!allowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) { - errors.push(createDiagnostic(Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec)); + return specs.filter(spec => { + const diag = specToDiagnostic(spec, allowTrailingRecursion); + if (diag !== undefined) { + errors.push(createDiagnostic(diag, spec)); } - else if (invalidMultipleRecursionPatterns.test(spec)) { - errors.push(createDiagnostic(Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, spec)); - } - else if (invalidDotDotAfterRecursiveWildcardPattern.test(spec)) { - errors.push(createDiagnostic(Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec)); - } - else { - validSpecs.push(spec); - } - } - - return validSpecs; + return diag === undefined; + }); function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic { if (jsonSourceFile && jsonSourceFile.jsonObject) { @@ -2045,6 +2035,18 @@ namespace ts { } } + function specToDiagnostic(spec: string, allowTrailingRecursion: boolean): ts.DiagnosticMessage | undefined { + if (!allowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) { + return Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0; + } + else if (invalidMultipleRecursionPatterns.test(spec)) { + return Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0; + } + else if (invalidDotDotAfterRecursiveWildcardPattern.test(spec)) { + return Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0; + } + } + /** * Gets directories in a set of include patterns that should be watched for changes. */ From af20adb13732ee1e50d38e397699016b85d1f84d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 Aug 2017 13:06:12 -0700 Subject: [PATCH 43/51] Add tests for #15358 (#17664) --- ...ckTypePredicateForRedundantProperties.errors.txt | 13 +++++++++++++ .../checkTypePredicateForRedundantProperties.js | 10 ++++++++++ .../checkTypePredicateForRedundantProperties.ts | 3 +++ 3 files changed, 26 insertions(+) create mode 100644 tests/baselines/reference/checkTypePredicateForRedundantProperties.errors.txt create mode 100644 tests/baselines/reference/checkTypePredicateForRedundantProperties.js create mode 100644 tests/cases/compiler/checkTypePredicateForRedundantProperties.ts diff --git a/tests/baselines/reference/checkTypePredicateForRedundantProperties.errors.txt b/tests/baselines/reference/checkTypePredicateForRedundantProperties.errors.txt new file mode 100644 index 00000000000..a5cb9b0a098 --- /dev/null +++ b/tests/baselines/reference/checkTypePredicateForRedundantProperties.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/checkTypePredicateForRedundantProperties.ts(1,35): error TS2300: Duplicate identifier 'a'. +tests/cases/compiler/checkTypePredicateForRedundantProperties.ts(1,46): error TS2300: Duplicate identifier 'a'. + + +==== tests/cases/compiler/checkTypePredicateForRedundantProperties.ts (2 errors) ==== + function addProp2(x: any): x is { a: string; a: string; } { + ~ +!!! error TS2300: Duplicate identifier 'a'. + ~ +!!! error TS2300: Duplicate identifier 'a'. + return true; + } + \ No newline at end of file diff --git a/tests/baselines/reference/checkTypePredicateForRedundantProperties.js b/tests/baselines/reference/checkTypePredicateForRedundantProperties.js new file mode 100644 index 00000000000..8f7be2bfbbc --- /dev/null +++ b/tests/baselines/reference/checkTypePredicateForRedundantProperties.js @@ -0,0 +1,10 @@ +//// [checkTypePredicateForRedundantProperties.ts] +function addProp2(x: any): x is { a: string; a: string; } { + return true; +} + + +//// [checkTypePredicateForRedundantProperties.js] +function addProp2(x) { + return true; +} diff --git a/tests/cases/compiler/checkTypePredicateForRedundantProperties.ts b/tests/cases/compiler/checkTypePredicateForRedundantProperties.ts new file mode 100644 index 00000000000..35222f1e9db --- /dev/null +++ b/tests/cases/compiler/checkTypePredicateForRedundantProperties.ts @@ -0,0 +1,3 @@ +function addProp2(x: any): x is { a: string; a: string; } { + return true; +} From a46d6bde974ead83b5bb4bfbfa76d085d391137d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 Aug 2017 13:07:27 -0700 Subject: [PATCH 44/51] Add a seperate cache for the all attributes version of the jsx attributes type (#17620) --- src/compiler/checker.ts | 12 +++++------- src/compiler/types.ts | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 579a234cb95..c164833ca47 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14107,11 +14107,8 @@ namespace ts { */ function resolveCustomJsxElementAttributesType(openingLikeElement: JsxOpeningLikeElement, shouldIncludeAllStatelessAttributesType: boolean, - elementType?: Type, + elementType: Type = checkExpression(openingLikeElement.tagName), elementClassType?: Type): Type { - if (!elementType) { - elementType = checkExpression(openingLikeElement.tagName); - } if (elementType.flags & TypeFlags.Union) { const types = (elementType as UnionType).types; @@ -14245,11 +14242,12 @@ namespace ts { */ function getCustomJsxElementAttributesType(node: JsxOpeningLikeElement, shouldIncludeAllStatelessAttributesType: boolean): Type { const links = getNodeLinks(node); - if (!links.resolvedJsxElementAttributesType) { + const linkLocation = shouldIncludeAllStatelessAttributesType ? "resolvedJsxElementAllAttributesType" : "resolvedJsxElementAttributesType"; + if (!links[linkLocation]) { const elemClassType = getJsxGlobalElementClassType(); - return links.resolvedJsxElementAttributesType = resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, /*elementType*/ undefined, elemClassType); + return links[linkLocation] = resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, /*elementType*/ undefined, elemClassType); } - return links.resolvedJsxElementAttributesType; + return links[linkLocation]; } /** diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3b57608abc5..0eb7f03e3ec 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3067,6 +3067,7 @@ namespace ts { hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element + resolvedJsxElementAllAttributesType?: Type; // resolved all element attributes type of a JSX openinglike element hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt. superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing switchTypes?: Type[]; // Cached array of switch case expression types From 3deb39bba6bfa7dc0482bf1a6ad4494ed04dc3c1 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 Aug 2017 14:01:16 -0700 Subject: [PATCH 45/51] Remove unnecessary check that type is ObjectType (#17418) --- src/compiler/checker.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c164833ca47..b427ae34b69 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3420,9 +3420,7 @@ namespace ts { if (!symbolStack) { symbolStack = []; } - const isConstructorObject = type.flags & TypeFlags.Object && - getObjectFlags(type) & ObjectFlags.Anonymous && - type.symbol && type.symbol.flags & SymbolFlags.Class; + const isConstructorObject = type.objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class; if (isConstructorObject) { writeLiteralType(type, flags); } From d2625678f9d67062dee980bf8ae1ee9298d2e272 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 Aug 2017 14:44:41 -0700 Subject: [PATCH 46/51] Add test case from #14439 (#17627) --- .../reference/mixingApparentTypeOverrides.js | 84 +++++++++++++++++++ .../mixingApparentTypeOverrides.symbols | 67 +++++++++++++++ .../mixingApparentTypeOverrides.types | 76 +++++++++++++++++ .../compiler/mixingApparentTypeOverrides.ts | 28 +++++++ 4 files changed, 255 insertions(+) create mode 100644 tests/baselines/reference/mixingApparentTypeOverrides.js create mode 100644 tests/baselines/reference/mixingApparentTypeOverrides.symbols create mode 100644 tests/baselines/reference/mixingApparentTypeOverrides.types create mode 100644 tests/cases/compiler/mixingApparentTypeOverrides.ts diff --git a/tests/baselines/reference/mixingApparentTypeOverrides.js b/tests/baselines/reference/mixingApparentTypeOverrides.js new file mode 100644 index 00000000000..20db894abb8 --- /dev/null +++ b/tests/baselines/reference/mixingApparentTypeOverrides.js @@ -0,0 +1,84 @@ +//// [mixingApparentTypeOverrides.ts] +type Constructor = new(...args: any[]) => T; +function Tagged>(Base: T) { + return class extends Base { + _tag: string; + constructor(...args: any[]) { + super(...args); + this._tag = ""; + } + }; +} + +class A { + toString () { + return "class A"; + } +} + +class B extends Tagged(A) { + toString () { // Should not be an error + return "class B"; + } +} + +class C extends A { + toString () { // Should not be an error + return "class C"; + } +} + +//// [mixingApparentTypeOverrides.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +function Tagged(Base) { + return (function (_super) { + __extends(class_1, _super); + function class_1() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var _this = _super.apply(this, args) || this; + _this._tag = ""; + return _this; + } + return class_1; + }(Base)); +} +var A = (function () { + function A() { + } + A.prototype.toString = function () { + return "class A"; + }; + return A; +}()); +var B = (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + B.prototype.toString = function () { + return "class B"; + }; + return B; +}(Tagged(A))); +var C = (function (_super) { + __extends(C, _super); + function C() { + return _super !== null && _super.apply(this, arguments) || this; + } + C.prototype.toString = function () { + return "class C"; + }; + return C; +}(A)); diff --git a/tests/baselines/reference/mixingApparentTypeOverrides.symbols b/tests/baselines/reference/mixingApparentTypeOverrides.symbols new file mode 100644 index 00000000000..ea0adbb8acd --- /dev/null +++ b/tests/baselines/reference/mixingApparentTypeOverrides.symbols @@ -0,0 +1,67 @@ +=== tests/cases/compiler/mixingApparentTypeOverrides.ts === +type Constructor = new(...args: any[]) => T; +>Constructor : Symbol(Constructor, Decl(mixingApparentTypeOverrides.ts, 0, 0)) +>T : Symbol(T, Decl(mixingApparentTypeOverrides.ts, 0, 17)) +>args : Symbol(args, Decl(mixingApparentTypeOverrides.ts, 0, 26)) +>T : Symbol(T, Decl(mixingApparentTypeOverrides.ts, 0, 17)) + +function Tagged>(Base: T) { +>Tagged : Symbol(Tagged, Decl(mixingApparentTypeOverrides.ts, 0, 47)) +>T : Symbol(T, Decl(mixingApparentTypeOverrides.ts, 1, 16)) +>Constructor : Symbol(Constructor, Decl(mixingApparentTypeOverrides.ts, 0, 0)) +>Base : Symbol(Base, Decl(mixingApparentTypeOverrides.ts, 1, 43)) +>T : Symbol(T, Decl(mixingApparentTypeOverrides.ts, 1, 16)) + + return class extends Base { +>Base : Symbol(Base, Decl(mixingApparentTypeOverrides.ts, 1, 43)) + + _tag: string; +>_tag : Symbol((Anonymous class)._tag, Decl(mixingApparentTypeOverrides.ts, 2, 29)) + + constructor(...args: any[]) { +>args : Symbol(args, Decl(mixingApparentTypeOverrides.ts, 4, 16)) + + super(...args); +>super : Symbol(T, Decl(mixingApparentTypeOverrides.ts, 1, 16)) +>args : Symbol(args, Decl(mixingApparentTypeOverrides.ts, 4, 16)) + + this._tag = ""; +>this._tag : Symbol((Anonymous class)._tag, Decl(mixingApparentTypeOverrides.ts, 2, 29)) +>this : Symbol((Anonymous class), Decl(mixingApparentTypeOverrides.ts, 2, 8)) +>_tag : Symbol((Anonymous class)._tag, Decl(mixingApparentTypeOverrides.ts, 2, 29)) + } + }; +} + +class A { +>A : Symbol(A, Decl(mixingApparentTypeOverrides.ts, 9, 1)) + + toString () { +>toString : Symbol(A.toString, Decl(mixingApparentTypeOverrides.ts, 11, 9)) + + return "class A"; + } +} + +class B extends Tagged(A) { +>B : Symbol(B, Decl(mixingApparentTypeOverrides.ts, 15, 1)) +>Tagged : Symbol(Tagged, Decl(mixingApparentTypeOverrides.ts, 0, 47)) +>A : Symbol(A, Decl(mixingApparentTypeOverrides.ts, 9, 1)) + + toString () { // Should not be an error +>toString : Symbol(B.toString, Decl(mixingApparentTypeOverrides.ts, 17, 27)) + + return "class B"; + } +} + +class C extends A { +>C : Symbol(C, Decl(mixingApparentTypeOverrides.ts, 21, 1)) +>A : Symbol(A, Decl(mixingApparentTypeOverrides.ts, 9, 1)) + + toString () { // Should not be an error +>toString : Symbol(C.toString, Decl(mixingApparentTypeOverrides.ts, 23, 19)) + + return "class C"; + } +} diff --git a/tests/baselines/reference/mixingApparentTypeOverrides.types b/tests/baselines/reference/mixingApparentTypeOverrides.types new file mode 100644 index 00000000000..eae9c391a78 --- /dev/null +++ b/tests/baselines/reference/mixingApparentTypeOverrides.types @@ -0,0 +1,76 @@ +=== tests/cases/compiler/mixingApparentTypeOverrides.ts === +type Constructor = new(...args: any[]) => T; +>Constructor : Constructor +>T : T +>args : any[] +>T : T + +function Tagged>(Base: T) { +>Tagged : >(Base: T) => { new (...args: any[]): (Anonymous class); prototype: Tagged.(Anonymous class); } & T +>T : T +>Constructor : Constructor +>Base : T +>T : T + + return class extends Base { +>class extends Base { _tag: string; constructor(...args: any[]) { super(...args); this._tag = ""; } } : { new (...args: any[]): (Anonymous class); prototype: Tagged.(Anonymous class); } & T +>Base : {} + + _tag: string; +>_tag : string + + constructor(...args: any[]) { +>args : any[] + + super(...args); +>super(...args) : void +>super : T +>...args : any +>args : any[] + + this._tag = ""; +>this._tag = "" : "" +>this._tag : string +>this : this +>_tag : string +>"" : "" + } + }; +} + +class A { +>A : A + + toString () { +>toString : () => string + + return "class A"; +>"class A" : "class A" + } +} + +class B extends Tagged(A) { +>B : B +>Tagged(A) : Tagged.(Anonymous class) & A +>Tagged : >(Base: T) => { new (...args: any[]): (Anonymous class); prototype: Tagged.(Anonymous class); } & T +>A : typeof A + + toString () { // Should not be an error +>toString : () => string + + return "class B"; +>"class B" : "class B" + } +} + +class C extends A { +>C : C +>A : A + + toString () { // Should not be an error +>toString : () => string + + return "class C"; +>"class C" : "class C" + } +} diff --git a/tests/cases/compiler/mixingApparentTypeOverrides.ts b/tests/cases/compiler/mixingApparentTypeOverrides.ts new file mode 100644 index 00000000000..5d68c58d461 --- /dev/null +++ b/tests/cases/compiler/mixingApparentTypeOverrides.ts @@ -0,0 +1,28 @@ +type Constructor = new(...args: any[]) => T; +function Tagged>(Base: T) { + return class extends Base { + _tag: string; + constructor(...args: any[]) { + super(...args); + this._tag = ""; + } + }; +} + +class A { + toString () { + return "class A"; + } +} + +class B extends Tagged(A) { + toString () { // Should not be an error + return "class B"; + } +} + +class C extends A { + toString () { // Should not be an error + return "class C"; + } +} \ No newline at end of file From e47df360dc050bce8fa3f559c6506d1a8e739d7c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 8 Aug 2017 14:51:06 -0700 Subject: [PATCH 47/51] Use isTypeAny instead of checking flags directly --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0fc2b927515..ff1d157c4fa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17148,7 +17148,7 @@ namespace ts { // and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature. // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported - if (!(leftType.flags & TypeFlags.Any) && isTypeAssignableToKind(leftType, TypeFlags.Primitive)) { + if (!isTypeAny(leftType) && isTypeAssignableToKind(leftType, TypeFlags.Primitive)) { error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } // NOTE: do not raise error if right is unknown as related error was already reported From fac93a304c816eea3b4f078ffe6f4567da145098 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 8 Aug 2017 16:11:42 -0700 Subject: [PATCH 48/51] Add parentheses:clarify evaluation order of &&/|| in isTypeAssignableToKind --- src/compiler/checker.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff1d157c4fa..33457daeccb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17120,15 +17120,15 @@ namespace ts { if (strict && source.flags & (TypeFlags.Any | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { return false; } - return kind & TypeFlags.NumberLike && isTypeAssignableTo(source, numberType) || - kind & TypeFlags.StringLike && isTypeAssignableTo(source, stringType) || - kind & TypeFlags.BooleanLike && isTypeAssignableTo(source, booleanType) || - kind & TypeFlags.Void && isTypeAssignableTo(source, voidType) || - kind & TypeFlags.Never && isTypeAssignableTo(source, neverType) || - kind & TypeFlags.Null && isTypeAssignableTo(source, nullType) || - kind & TypeFlags.Undefined && isTypeAssignableTo(source, undefinedType) || - kind & TypeFlags.ESSymbol && isTypeAssignableTo(source, esSymbolType) || - kind & TypeFlags.NonPrimitive && isTypeAssignableTo(source, nonPrimitiveType); + return (kind & TypeFlags.NumberLike && isTypeAssignableTo(source, numberType)) || + (kind & TypeFlags.StringLike && isTypeAssignableTo(source, stringType)) || + (kind & TypeFlags.BooleanLike && isTypeAssignableTo(source, booleanType)) || + (kind & TypeFlags.Void && isTypeAssignableTo(source, voidType)) || + (kind & TypeFlags.Never && isTypeAssignableTo(source, neverType)) || + (kind & TypeFlags.Null && isTypeAssignableTo(source, nullType)) || + (kind & TypeFlags.Undefined && isTypeAssignableTo(source, undefinedType)) || + (kind & TypeFlags.ESSymbol && isTypeAssignableTo(source, esSymbolType)) || + (kind & TypeFlags.NonPrimitive && isTypeAssignableTo(source, nonPrimitiveType)); } function isConstEnumObjectType(type: Type): boolean { From 43e758e1a96f2f8a93eefe215af9c30c0c90fbe0 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 Aug 2017 17:01:18 -0700 Subject: [PATCH 49/51] Create synthetic default exports for dynamic imports (#17492) * Create synthetic default exports for dynamic imports * Slightly better solution * Actually accept baselines * Slightly adjust synthetic type * Cache synthetic type * Inline variables, remove non-required calls * Rename function --- src/compiler/checker.ts | 29 ++++++++- src/compiler/types.ts | 5 ++ .../importCallExpressionAsyncES3System.types | 30 +++++----- .../importCallExpressionAsyncES5System.types | 30 +++++----- .../importCallExpressionAsyncES6System.types | 30 +++++----- .../importCallExpressionES5System.types | 34 +++++------ .../importCallExpressionES6System.types | 34 +++++------ .../importCallExpressionInSystem1.types | 26 ++++---- .../importCallExpressionInSystem2.types | 2 +- .../importCallExpressionInSystem3.types | 6 +- .../importCallExpressionInSystem4.types | 60 +++++++++---------- ...ntheticDefaultExportsWithDynamicImports.js | 19 ++++++ ...icDefaultExportsWithDynamicImports.symbols | 17 ++++++ ...eticDefaultExportsWithDynamicImports.types | 22 +++++++ ...ntheticDefaultExportsWithDynamicImports.ts | 9 +++ 15 files changed, 224 insertions(+), 129 deletions(-) create mode 100644 tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.js create mode 100644 tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.symbols create mode 100644 tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types create mode 100644 tests/cases/compiler/syntheticDefaultExportsWithDynamicImports.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e2200218030..1d1d16b7ee1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1757,7 +1757,7 @@ namespace ts { // 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 { - return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export=" as __String), dontResolveAlias)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias)) || moduleSymbol; } // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' @@ -1772,7 +1772,7 @@ namespace ts { } function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean { - return moduleSymbol.exports.get("export=" as __String) !== undefined; + return moduleSymbol.exports.get(InternalSymbolName.ExportEquals) !== undefined; } function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] { @@ -16402,12 +16402,35 @@ namespace ts { if (moduleSymbol) { const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true); if (esModuleSymbol) { - return createPromiseReturnType(node, getTypeOfSymbol(esModuleSymbol)); + return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol)); } } return createPromiseReturnType(node, anyType); } + function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol): Type { + if (allowSyntheticDefaultImports && type && type !== unknownType) { + const synthType = type as SyntheticDefaultModuleType; + if (!synthType.syntheticType) { + if (!getPropertyOfType(type, InternalSymbolName.Default)) { + const memberTable = createSymbolTable(); + const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default); + newSymbol.target = resolveSymbol(symbol); + memberTable.set(InternalSymbolName.Default, newSymbol); + const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); + const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); + anonymousSymbol.type = defaultContainingObject; + synthType.syntheticType = getIntersectionType([type, defaultContainingObject]); + } + else { + synthType.syntheticType = type; + } + } + return synthType.syntheticType; + } + return type; + } + function isCommonJsRequire(node: Node) { if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { return false; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 259dad75b00..27dcbda309f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3318,6 +3318,11 @@ namespace ts { awaitedTypeOfType?: Type; } + /* @internal */ + export interface SyntheticDefaultModuleType extends Type { + syntheticType?: Type; + } + export interface TypeVariable extends Type { /* @internal */ resolvedBaseConstraint: Type; diff --git a/tests/baselines/reference/importCallExpressionAsyncES3System.types b/tests/baselines/reference/importCallExpressionAsyncES3System.types index 4f6a2bb31be..90c981c01ca 100644 --- a/tests/baselines/reference/importCallExpressionAsyncES3System.types +++ b/tests/baselines/reference/importCallExpressionAsyncES3System.types @@ -3,9 +3,9 @@ export async function fn() { >fn : () => Promise const req = await import('./test') // ONE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } @@ -16,9 +16,9 @@ export class cl1 { >m : () => Promise const req = await import('./test') // TWO ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -32,9 +32,9 @@ export const obj = { >async () => { const req = await import('./test') // THREE } : () => Promise const req = await import('./test') // THREE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -51,9 +51,9 @@ export class cl2 { >async () => { const req = await import('./test') // FOUR } : () => Promise const req = await import('./test') // FOUR ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -64,9 +64,9 @@ export const l = async () => { >async () => { const req = await import('./test') // FIVE} : () => Promise const req = await import('./test') // FIVE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } diff --git a/tests/baselines/reference/importCallExpressionAsyncES5System.types b/tests/baselines/reference/importCallExpressionAsyncES5System.types index 4f6a2bb31be..90c981c01ca 100644 --- a/tests/baselines/reference/importCallExpressionAsyncES5System.types +++ b/tests/baselines/reference/importCallExpressionAsyncES5System.types @@ -3,9 +3,9 @@ export async function fn() { >fn : () => Promise const req = await import('./test') // ONE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } @@ -16,9 +16,9 @@ export class cl1 { >m : () => Promise const req = await import('./test') // TWO ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -32,9 +32,9 @@ export const obj = { >async () => { const req = await import('./test') // THREE } : () => Promise const req = await import('./test') // THREE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -51,9 +51,9 @@ export class cl2 { >async () => { const req = await import('./test') // FOUR } : () => Promise const req = await import('./test') // FOUR ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -64,9 +64,9 @@ export const l = async () => { >async () => { const req = await import('./test') // FIVE} : () => Promise const req = await import('./test') // FIVE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } diff --git a/tests/baselines/reference/importCallExpressionAsyncES6System.types b/tests/baselines/reference/importCallExpressionAsyncES6System.types index 4f6a2bb31be..90c981c01ca 100644 --- a/tests/baselines/reference/importCallExpressionAsyncES6System.types +++ b/tests/baselines/reference/importCallExpressionAsyncES6System.types @@ -3,9 +3,9 @@ export async function fn() { >fn : () => Promise const req = await import('./test') // ONE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } @@ -16,9 +16,9 @@ export class cl1 { >m : () => Promise const req = await import('./test') // TWO ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -32,9 +32,9 @@ export const obj = { >async () => { const req = await import('./test') // THREE } : () => Promise const req = await import('./test') // THREE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -51,9 +51,9 @@ export class cl2 { >async () => { const req = await import('./test') // FOUR } : () => Promise const req = await import('./test') // FOUR ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } } @@ -64,9 +64,9 @@ export const l = async () => { >async () => { const req = await import('./test') // FIVE} : () => Promise const req = await import('./test') // FIVE ->req : typeof "tests/cases/conformance/dynamicImport/test" ->await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" ->import('./test') : Promise +>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; } +>import('./test') : Promise >'./test' : "./test" } diff --git a/tests/baselines/reference/importCallExpressionES5System.types b/tests/baselines/reference/importCallExpressionES5System.types index e97f722b14f..02bd64142d4 100644 --- a/tests/baselines/reference/importCallExpressionES5System.types +++ b/tests/baselines/reference/importCallExpressionES5System.types @@ -5,41 +5,41 @@ export function foo() { return "foo"; } === tests/cases/conformance/dynamicImport/1.ts === import("./0"); ->import("./0") : Promise +>import("./0") : Promise >"./0" : "./0" var p1 = import("./0"); ->p1 : Promise ->import("./0") : Promise +>p1 : Promise +>import("./0") : Promise >"./0" : "./0" p1.then(zero => { >p1.then(zero => { return zero.foo();}) : Promise ->p1.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->p1 : Promise ->then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->zero => { return zero.foo();} : (zero: typeof "tests/cases/conformance/dynamicImport/0") => string ->zero : typeof "tests/cases/conformance/dynamicImport/0" +>p1.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>p1 : Promise +>then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>zero => { return zero.foo();} : (zero: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => string +>zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } return zero.foo(); >zero.foo() : string >zero.foo : () => string ->zero : typeof "tests/cases/conformance/dynamicImport/0" +>zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } >foo : () => string }); export var p2 = import("./0"); ->p2 : Promise ->import("./0") : Promise +>p2 : Promise +>import("./0") : Promise >"./0" : "./0" function foo() { >foo : () => void const p2 = import("./0"); ->p2 : Promise ->import("./0") : Promise +>p2 : Promise +>import("./0") : Promise >"./0" : "./0" } @@ -50,8 +50,8 @@ class C { >method : () => void const loadAsync = import ("./0"); ->loadAsync : Promise ->import ("./0") : Promise +>loadAsync : Promise +>import ("./0") : Promise >"./0" : "./0" } } @@ -63,8 +63,8 @@ export class D { >method : () => void const loadAsync = import ("./0"); ->loadAsync : Promise ->import ("./0") : Promise +>loadAsync : Promise +>import ("./0") : Promise >"./0" : "./0" } } diff --git a/tests/baselines/reference/importCallExpressionES6System.types b/tests/baselines/reference/importCallExpressionES6System.types index e97f722b14f..02bd64142d4 100644 --- a/tests/baselines/reference/importCallExpressionES6System.types +++ b/tests/baselines/reference/importCallExpressionES6System.types @@ -5,41 +5,41 @@ export function foo() { return "foo"; } === tests/cases/conformance/dynamicImport/1.ts === import("./0"); ->import("./0") : Promise +>import("./0") : Promise >"./0" : "./0" var p1 = import("./0"); ->p1 : Promise ->import("./0") : Promise +>p1 : Promise +>import("./0") : Promise >"./0" : "./0" p1.then(zero => { >p1.then(zero => { return zero.foo();}) : Promise ->p1.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->p1 : Promise ->then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->zero => { return zero.foo();} : (zero: typeof "tests/cases/conformance/dynamicImport/0") => string ->zero : typeof "tests/cases/conformance/dynamicImport/0" +>p1.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>p1 : Promise +>then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>zero => { return zero.foo();} : (zero: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => string +>zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } return zero.foo(); >zero.foo() : string >zero.foo : () => string ->zero : typeof "tests/cases/conformance/dynamicImport/0" +>zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } >foo : () => string }); export var p2 = import("./0"); ->p2 : Promise ->import("./0") : Promise +>p2 : Promise +>import("./0") : Promise >"./0" : "./0" function foo() { >foo : () => void const p2 = import("./0"); ->p2 : Promise ->import("./0") : Promise +>p2 : Promise +>import("./0") : Promise >"./0" : "./0" } @@ -50,8 +50,8 @@ class C { >method : () => void const loadAsync = import ("./0"); ->loadAsync : Promise ->import ("./0") : Promise +>loadAsync : Promise +>import ("./0") : Promise >"./0" : "./0" } } @@ -63,8 +63,8 @@ export class D { >method : () => void const loadAsync = import ("./0"); ->loadAsync : Promise ->import ("./0") : Promise +>loadAsync : Promise +>import ("./0") : Promise >"./0" : "./0" } } diff --git a/tests/baselines/reference/importCallExpressionInSystem1.types b/tests/baselines/reference/importCallExpressionInSystem1.types index 661d27d1469..a82d8176753 100644 --- a/tests/baselines/reference/importCallExpressionInSystem1.types +++ b/tests/baselines/reference/importCallExpressionInSystem1.types @@ -5,40 +5,40 @@ export function foo() { return "foo"; } === tests/cases/conformance/dynamicImport/1.ts === import("./0"); ->import("./0") : Promise +>import("./0") : Promise >"./0" : "./0" var p1 = import("./0"); ->p1 : Promise ->import("./0") : Promise +>p1 : Promise +>import("./0") : Promise >"./0" : "./0" p1.then(zero => { >p1.then(zero => { return zero.foo();}) : Promise ->p1.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->p1 : Promise ->then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->zero => { return zero.foo();} : (zero: typeof "tests/cases/conformance/dynamicImport/0") => string ->zero : typeof "tests/cases/conformance/dynamicImport/0" +>p1.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>p1 : Promise +>then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>zero => { return zero.foo();} : (zero: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => string +>zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } return zero.foo(); >zero.foo() : string >zero.foo : () => string ->zero : typeof "tests/cases/conformance/dynamicImport/0" +>zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } >foo : () => string }); export var p2 = import("./0"); ->p2 : Promise ->import("./0") : Promise +>p2 : Promise +>import("./0") : Promise >"./0" : "./0" function foo() { >foo : () => void const p2 = import("./0"); ->p2 : Promise ->import("./0") : Promise +>p2 : Promise +>import("./0") : Promise >"./0" : "./0" } diff --git a/tests/baselines/reference/importCallExpressionInSystem2.types b/tests/baselines/reference/importCallExpressionInSystem2.types index 44b17eb51fd..160da81b214 100644 --- a/tests/baselines/reference/importCallExpressionInSystem2.types +++ b/tests/baselines/reference/importCallExpressionInSystem2.types @@ -41,6 +41,6 @@ function foo(x: Promise) { foo(import("./0")); >foo(import("./0")) : void >foo : (x: Promise) => void ->import("./0") : Promise +>import("./0") : Promise >"./0" : "./0" diff --git a/tests/baselines/reference/importCallExpressionInSystem3.types b/tests/baselines/reference/importCallExpressionInSystem3.types index e517be6e722..08bf03fb506 100644 --- a/tests/baselines/reference/importCallExpressionInSystem3.types +++ b/tests/baselines/reference/importCallExpressionInSystem3.types @@ -14,9 +14,9 @@ async function foo() { class C extends (await import("./0")).B {} >C : C >(await import("./0")).B : B ->(await import("./0")) : typeof "tests/cases/conformance/dynamicImport/0" ->await import("./0") : typeof "tests/cases/conformance/dynamicImport/0" ->import("./0") : Promise +>(await import("./0")) : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } +>await import("./0") : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } +>import("./0") : Promise >"./0" : "./0" >B : typeof B diff --git a/tests/baselines/reference/importCallExpressionInSystem4.types b/tests/baselines/reference/importCallExpressionInSystem4.types index 156247851c9..c9f2b2e5211 100644 --- a/tests/baselines/reference/importCallExpressionInSystem4.types +++ b/tests/baselines/reference/importCallExpressionInSystem4.types @@ -24,27 +24,27 @@ class C { >C : C private myModule = import("./0"); ->myModule : Promise ->import("./0") : Promise +>myModule : Promise +>import("./0") : Promise >"./0" : "./0" method() { >method : () => void const loadAsync = import("./0"); ->loadAsync : Promise ->import("./0") : Promise +>loadAsync : Promise +>import("./0") : Promise >"./0" : "./0" this.myModule.then(Zero => { >this.myModule.then(Zero => { console.log(Zero.foo()); }, async err => { console.log(err); let one = await import("./1"); console.log(one.backup()); }) : Promise ->this.myModule.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->this.myModule : Promise +>this.myModule.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>this.myModule : Promise >this : this ->myModule : Promise ->then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->Zero => { console.log(Zero.foo()); } : (Zero: typeof "tests/cases/conformance/dynamicImport/0") => void ->Zero : typeof "tests/cases/conformance/dynamicImport/0" +>myModule : Promise +>then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>Zero => { console.log(Zero.foo()); } : (Zero: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => void +>Zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } console.log(Zero.foo()); >console.log(Zero.foo()) : any @@ -53,7 +53,7 @@ class C { >log : any >Zero.foo() : string >Zero.foo : () => string ->Zero : typeof "tests/cases/conformance/dynamicImport/0" +>Zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } >foo : () => string }, async err => { @@ -68,9 +68,9 @@ class C { >err : any let one = await import("./1"); ->one : typeof "tests/cases/conformance/dynamicImport/1" ->await import("./1") : typeof "tests/cases/conformance/dynamicImport/1" ->import("./1") : Promise +>one : typeof "tests/cases/conformance/dynamicImport/1" & { default: typeof "tests/cases/conformance/dynamicImport/1"; } +>await import("./1") : typeof "tests/cases/conformance/dynamicImport/1" & { default: typeof "tests/cases/conformance/dynamicImport/1"; } +>import("./1") : Promise >"./1" : "./1" console.log(one.backup()); @@ -80,7 +80,7 @@ class C { >log : any >one.backup() : string >one.backup : () => string ->one : typeof "tests/cases/conformance/dynamicImport/1" +>one : typeof "tests/cases/conformance/dynamicImport/1" & { default: typeof "tests/cases/conformance/dynamicImport/1"; } >backup : () => string }); @@ -91,27 +91,27 @@ export class D { >D : D private myModule = import("./0"); ->myModule : Promise ->import("./0") : Promise +>myModule : Promise +>import("./0") : Promise >"./0" : "./0" method() { >method : () => void const loadAsync = import("./0"); ->loadAsync : Promise ->import("./0") : Promise +>loadAsync : Promise +>import("./0") : Promise >"./0" : "./0" this.myModule.then(Zero => { >this.myModule.then(Zero => { console.log(Zero.foo()); }, async err => { console.log(err); let one = await import("./1"); console.log(one.backup()); }) : Promise ->this.myModule.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->this.myModule : Promise +>this.myModule.then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>this.myModule : Promise >this : this ->myModule : Promise ->then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0") => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->Zero => { console.log(Zero.foo()); } : (Zero: typeof "tests/cases/conformance/dynamicImport/0") => void ->Zero : typeof "tests/cases/conformance/dynamicImport/0" +>myModule : Promise +>then : (onfulfilled?: (value: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>Zero => { console.log(Zero.foo()); } : (Zero: typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; }) => void +>Zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } console.log(Zero.foo()); >console.log(Zero.foo()) : any @@ -120,7 +120,7 @@ export class D { >log : any >Zero.foo() : string >Zero.foo : () => string ->Zero : typeof "tests/cases/conformance/dynamicImport/0" +>Zero : typeof "tests/cases/conformance/dynamicImport/0" & { default: typeof "tests/cases/conformance/dynamicImport/0"; } >foo : () => string }, async err => { @@ -135,9 +135,9 @@ export class D { >err : any let one = await import("./1"); ->one : typeof "tests/cases/conformance/dynamicImport/1" ->await import("./1") : typeof "tests/cases/conformance/dynamicImport/1" ->import("./1") : Promise +>one : typeof "tests/cases/conformance/dynamicImport/1" & { default: typeof "tests/cases/conformance/dynamicImport/1"; } +>await import("./1") : typeof "tests/cases/conformance/dynamicImport/1" & { default: typeof "tests/cases/conformance/dynamicImport/1"; } +>import("./1") : Promise >"./1" : "./1" console.log(one.backup()); @@ -147,7 +147,7 @@ export class D { >log : any >one.backup() : string >one.backup : () => string ->one : typeof "tests/cases/conformance/dynamicImport/1" +>one : typeof "tests/cases/conformance/dynamicImport/1" & { default: typeof "tests/cases/conformance/dynamicImport/1"; } >backup : () => string }); diff --git a/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.js b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.js new file mode 100644 index 00000000000..c49924191e5 --- /dev/null +++ b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.js @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/syntheticDefaultExportsWithDynamicImports.ts] //// + +//// [index.d.ts] +declare function packageExport(x: number): string; +export = packageExport; + +//// [index.ts] +import("package").then(({default: foo}) => foo(42)); + +//// [index.js] +System.register([], function (exports_1, context_1) { + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + context_1.import("package").then(({ default: foo }) => foo(42)); + } + }; +}); diff --git a/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.symbols b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.symbols new file mode 100644 index 00000000000..85019711153 --- /dev/null +++ b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.symbols @@ -0,0 +1,17 @@ +=== tests/cases/compiler/node_modules/package/index.d.ts === +declare function packageExport(x: number): string; +>packageExport : Symbol(packageExport, Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 0, 31)) + +export = packageExport; +>packageExport : Symbol(packageExport, Decl(index.d.ts, 0, 0)) + +=== tests/cases/compiler/index.ts === +import("package").then(({default: foo}) => foo(42)); +>import("package").then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>"package" : Symbol("tests/cases/compiler/node_modules/package/index", Decl(index.d.ts, 0, 0)) +>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>default : Symbol(default) +>foo : Symbol(foo, Decl(index.ts, 0, 25)) +>foo : Symbol(foo, Decl(index.ts, 0, 25)) + diff --git a/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types new file mode 100644 index 00000000000..1c38ecc466c --- /dev/null +++ b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/node_modules/package/index.d.ts === +declare function packageExport(x: number): string; +>packageExport : (x: number) => string +>x : number + +export = packageExport; +>packageExport : (x: number) => string + +=== tests/cases/compiler/index.ts === +import("package").then(({default: foo}) => foo(42)); +>import("package").then(({default: foo}) => foo(42)) : Promise +>import("package").then : string) & { default: (x: number) => string; }, TResult2 = never>(onfulfilled?: (value: ((x: number) => string) & { default: (x: number) => string; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>import("package") : Promise<((x: number) => string) & { default: (x: number) => string; }> +>"package" : "package" +>then : string) & { default: (x: number) => string; }, TResult2 = never>(onfulfilled?: (value: ((x: number) => string) & { default: (x: number) => string; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +>({default: foo}) => foo(42) : ({ default: foo }: ((x: number) => string) & { default: (x: number) => string; }) => string +>default : any +>foo : (x: number) => string +>foo(42) : string +>foo : (x: number) => string +>42 : 42 + diff --git a/tests/cases/compiler/syntheticDefaultExportsWithDynamicImports.ts b/tests/cases/compiler/syntheticDefaultExportsWithDynamicImports.ts new file mode 100644 index 00000000000..07f08d03185 --- /dev/null +++ b/tests/cases/compiler/syntheticDefaultExportsWithDynamicImports.ts @@ -0,0 +1,9 @@ +// @module: system +// @target: es6 +// @moduleResolution: node +// @filename: node_modules/package/index.d.ts +declare function packageExport(x: number): string; +export = packageExport; + +// @filename: index.ts +import("package").then(({default: foo}) => foo(42)); \ No newline at end of file From 81e1e26a6c038d11a32a95d4f301e37c190a22ef Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 Aug 2017 17:20:25 -0700 Subject: [PATCH 50/51] TSLint now realizes when you attempt to use a rule which is not present (#17688) --- Jakefile.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 31243f77c42..e6ff364e58b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -1122,14 +1122,15 @@ task("update-sublime", ["local", serverFile], function () { var tslintRuleDir = "scripts/tslint"; var tslintRules = [ - "nextLineRule", "booleanTriviaRule", - "typeOperatorSpacingRule", - "noInOperatorRule", + "debugAssertRule", + "nextLineRule", + "noBomRule", "noIncrementDecrementRule", - "objectLiteralSurroundingSpaceRule", + "noInOperatorRule", "noTypeAssertionWhitespaceRule", - "noBomRule" + "objectLiteralSurroundingSpaceRule", + "typeOperatorSpacingRule", ]; var tslintRulesFiles = tslintRules.map(function (p) { return path.join(tslintRuleDir, p + ".ts"); From c399230767a470e703e361333bac0cb6be513b8c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 Aug 2017 19:53:53 -0700 Subject: [PATCH 51/51] Retain comments inside return statements (#17557) * Retain comments inside return statements by including the return keyword in the parse tree * Revert "Retain comments inside return statements by including the return keyword in the parse tree" This reverts commit 5d2142edb1ffb9f6cb150b815aff6e627ae80449. * Readd test * Function for handling printing comments on a token --- src/compiler/comments.ts | 6 +++--- src/compiler/emitter.ts | 14 +++++++++++++- .../baselines/reference/jsdocCastCommentEmit.js | 17 +++++++++++++++++ .../reference/jsdocCastCommentEmit.symbols | 10 ++++++++++ .../reference/jsdocCastCommentEmit.types | 11 +++++++++++ tests/cases/compiler/jsdocCastCommentEmit.ts | 7 +++++++ 6 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/jsdocCastCommentEmit.js create mode 100644 tests/baselines/reference/jsdocCastCommentEmit.symbols create mode 100644 tests/baselines/reference/jsdocCastCommentEmit.types create mode 100644 tests/cases/compiler/jsdocCastCommentEmit.ts diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 06285309f64..50d706d3c42 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -8,7 +8,7 @@ namespace ts { setWriter(writer: EmitTextWriter): void; emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; - emitTrailingCommentsOfPosition(pos: number): void; + emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean): void; emitLeadingCommentsOfPosition(pos: number): void; } @@ -306,7 +306,7 @@ namespace ts { } } - function emitTrailingCommentsOfPosition(pos: number) { + function emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean) { if (disabled) { return; } @@ -315,7 +315,7 @@ namespace ts { performance.mark("beforeEmitTrailingCommentsOfPosition"); } - forEachTrailingCommentToEmit(pos, emitTrailingCommentOfPosition); + forEachTrailingCommentToEmit(pos, prefixSpace ? emitTrailingComment : emitTrailingCommentOfPosition); if (extendedDiagnostics) { performance.measure("commentTime", "beforeEmitTrailingCommentsOfPosition"); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9eb1af2f187..923e6da4215 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1572,8 +1572,20 @@ namespace ts { write(";"); } + function emitTokenWithComment(token: SyntaxKind, pos: number, contextNode?: Node) { + const node = contextNode && getParseTreeNode(contextNode); + if (node && node.kind === contextNode.kind) { + pos = skipTrivia(currentSourceFile.text, pos); + } + pos = writeToken(token, pos, /*contextNode*/ contextNode); + if (node && node.kind === contextNode.kind) { + emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true); + } + return pos; + } + function emitReturnStatement(node: ReturnStatement) { - writeToken(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node); + emitTokenWithComment(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node); emitExpressionWithPrefix(" ", node.expression); write(";"); } diff --git a/tests/baselines/reference/jsdocCastCommentEmit.js b/tests/baselines/reference/jsdocCastCommentEmit.js new file mode 100644 index 00000000000..d071f8f6b2b --- /dev/null +++ b/tests/baselines/reference/jsdocCastCommentEmit.js @@ -0,0 +1,17 @@ +//// [jsdocCastCommentEmit.ts] +// allowJs: true +// checkJs: true +// outDir: out/ +// filename: input.js +function f() { + return /* @type {number} */ 42; +} + +//// [jsdocCastCommentEmit.js] +// allowJs: true +// checkJs: true +// outDir: out/ +// filename: input.js +function f() { + return /* @type {number} */ 42; +} diff --git a/tests/baselines/reference/jsdocCastCommentEmit.symbols b/tests/baselines/reference/jsdocCastCommentEmit.symbols new file mode 100644 index 00000000000..5490315bc19 --- /dev/null +++ b/tests/baselines/reference/jsdocCastCommentEmit.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/jsdocCastCommentEmit.ts === +// allowJs: true +// checkJs: true +// outDir: out/ +// filename: input.js +function f() { +>f : Symbol(f, Decl(jsdocCastCommentEmit.ts, 0, 0)) + + return /* @type {number} */ 42; +} diff --git a/tests/baselines/reference/jsdocCastCommentEmit.types b/tests/baselines/reference/jsdocCastCommentEmit.types new file mode 100644 index 00000000000..3d4c3e47e46 --- /dev/null +++ b/tests/baselines/reference/jsdocCastCommentEmit.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/jsdocCastCommentEmit.ts === +// allowJs: true +// checkJs: true +// outDir: out/ +// filename: input.js +function f() { +>f : () => number + + return /* @type {number} */ 42; +>42 : 42 +} diff --git a/tests/cases/compiler/jsdocCastCommentEmit.ts b/tests/cases/compiler/jsdocCastCommentEmit.ts new file mode 100644 index 00000000000..5e7230bd049 --- /dev/null +++ b/tests/cases/compiler/jsdocCastCommentEmit.ts @@ -0,0 +1,7 @@ +// allowJs: true +// checkJs: true +// outDir: out/ +// filename: input.js +function f() { + return /* @type {number} */ 42; +} \ No newline at end of file