From 323a195db9b07fd54fa888d744da1866f24a4b76 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 20 Mar 2016 12:30:54 -0700 Subject: [PATCH 1/5] Don't elaborate errors when trying to relate a primitive to a union. --- 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 27b08397205..b7779fc9da0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5678,7 +5678,7 @@ namespace ts { } } if (target.flags & TypeFlags.Union) { - if (result = typeRelatedToSomeType(source, target, reportErrors)) { + if (result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & TypeFlags.Primitive))) { return result; } } From e9aeaa2f0d7f8813e2bb874ec5e64df4cf71bec2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 20 Mar 2016 12:31:11 -0700 Subject: [PATCH 2/5] Accepted baselines. --- .../reference/contextualTypeWithTuple.errors.txt | 2 -- ...uallyTypedBindingInitializerNegative.errors.txt | 2 -- ...TypedStringLiteralsInJsxAttributes01.errors.txt | 6 +----- .../destructuringParameterDeclaration2.errors.txt | 4 ---- .../destructuringParameterDeclaration4.errors.txt | 2 -- .../errorMessagesIntersectionTypes02.errors.txt | 2 -- .../reference/genericCallWithTupleType.errors.txt | 2 -- .../reference/iteratorSpreadInCall6.errors.txt | 2 -- ...ypeArgumentsWithStringLiteralTypes01.errors.txt | 14 -------------- 9 files changed, 1 insertion(+), 35 deletions(-) diff --git a/tests/baselines/reference/contextualTypeWithTuple.errors.txt b/tests/baselines/reference/contextualTypeWithTuple.errors.txt index e447ed62b39..a2d3b224ddc 100644 --- a/tests/baselines/reference/contextualTypeWithTuple.errors.txt +++ b/tests/baselines/reference/contextualTypeWithTuple.errors.txt @@ -3,7 +3,6 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(3,5): error TS232 Type '() => number | string | boolean' is not assignable to type '() => number | string'. Type 'number | string | boolean' is not assignable to type 'number | string'. Type 'boolean' is not assignable to type 'number | string'. - Type 'boolean' is not assignable to type 'string'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(15,1): error TS2322: Type '[number, string, boolean]' is not assignable to type '[number, string]'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(18,1): error TS2322: Type '[{}, number]' is not assignable to type '[{ a: string; }, number]'. Types of property '0' are incompatible. @@ -34,7 +33,6 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23 !!! error TS2322: Type '() => number | string | boolean' is not assignable to type '() => number | string'. !!! error TS2322: Type 'number | string | boolean' is not assignable to type 'number | string'. !!! error TS2322: Type 'boolean' is not assignable to type 'number | string'. -!!! error TS2322: Type 'boolean' is not assignable to type 'string'. var numStrBoolTuple: [number, string, boolean] = [5, "foo", true]; var objNumTuple: [{ a: string }, number] = [{ a: "world" }, 5]; var strTupleTuple: [string, [number, {}]] = ["bar", [5, { x: 1, y: 1 }]]; diff --git a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt index 689645386c4..42d617887e0 100644 --- a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt +++ b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt @@ -14,7 +14,6 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp Types of property '0' are incompatible. Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(26,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'. - Type '"baz"' is not assignable to type '"bar"'. ==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts (7 errors) ==== @@ -67,5 +66,4 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp function h({ prop = "baz" }: StringUnion) {} ~~~~ !!! error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'. -!!! error TS2322: Type '"baz"' is not assignable to type '"bar"'. \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt index 32b86e455d2..48e11fb1221 100644 --- a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt +++ b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt @@ -1,7 +1,5 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(16,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. - Type '"f"' is not assignable to type '"C"'. tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(17,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. - Type '"f"' is not assignable to type '"C"'. ==== tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx (2 errors) ==== @@ -23,8 +21,6 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStr ; ~~~~~~~~~ !!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. -!!! error TS2322: Type '"f"' is not assignable to type '"C"'. ; ~~~~~~~ -!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. -!!! error TS2322: Type '"f"' is not assignable to type '"C"'. \ No newline at end of file +!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. \ No newline at end of file diff --git a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt index 114efc14d9c..d68220c8308 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt @@ -7,7 +7,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( Type '() => number | string[][] | string' is not assignable to type '() => number | string[][]'. Type 'number | string[][] | string' is not assignable to type 'number | string[][]'. Type 'string' is not assignable to type 'number | string[][]'. - Type 'string' is not assignable to type 'string[][]'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(16,8): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(16,16): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(23,14): error TS2345: Argument of type '{ x: string; y: boolean; }' is not assignable to parameter of type '{ x: number; y: any; }'. @@ -29,7 +28,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(38,4): error TS2345: Argument of type '{ b: boolean; }' is not assignable to parameter of type '{ b: number | string; }'. Types of property 'b' are incompatible. Type 'boolean' is not assignable to type 'number | string'. - Type 'boolean' is not assignable to type 'string'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(39,4): error TS2345: Argument of type '[number, number, boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. Types of property '2' are incompatible. Type 'boolean' is not assignable to type '[[any]]'. @@ -75,7 +73,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( !!! error TS2345: Type '() => number | string[][] | string' is not assignable to type '() => number | string[][]'. !!! error TS2345: Type 'number | string[][] | string' is not assignable to type 'number | string[][]'. !!! error TS2345: Type 'string' is not assignable to type 'number | string[][]'. -!!! error TS2345: Type 'string' is not assignable to type 'string[][]'. // If the declaration includes an initializer expression (which is permitted only @@ -137,7 +134,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( !!! error TS2345: Argument of type '{ b: boolean; }' is not assignable to parameter of type '{ b: number | string; }'. !!! error TS2345: Types of property 'b' are incompatible. !!! error TS2345: Type 'boolean' is not assignable to type 'number | string'. -!!! error TS2345: Type 'boolean' is not assignable to type 'string'. c5([1, 2, false, true]); // Error, implied type is [any, any, [[any]]] ~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '[number, number, boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. diff --git a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt index b08c5b942d8..aa5a8e8daea 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt @@ -1,7 +1,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(11,13): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(13,13): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(20,19): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number | string'. - Type 'boolean' is not assignable to type 'string'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(21,7): error TS2304: Cannot find name 'array2'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(22,4): error TS2345: Argument of type '[number, number, string, boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. Types of property '2' are incompatible. @@ -43,7 +42,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( a1(1, 2, "hello", true); // Error, parameter type is (number|string)[] ~~~~ !!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number | string'. -!!! error TS2345: Type 'boolean' is not assignable to type 'string'. a1(...array2); // Error parameter type is (number|string)[] ~~~~~~ !!! error TS2304: Cannot find name 'array2'. diff --git a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt index 06e06c87015..6a9dd26706c 100644 --- a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt +++ b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt @@ -1,7 +1,6 @@ tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. Types of property 'fooProp' are incompatible. Type 'string' is not assignable to type '"hello" | "world"'. - Type 'string' is not assignable to type '"world"'. ==== tests/cases/compiler/errorMessagesIntersectionTypes02.ts (1 errors) ==== @@ -23,6 +22,5 @@ tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Ty !!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. !!! error TS2322: Types of property 'fooProp' are incompatible. !!! error TS2322: Type 'string' is not assignable to type '"hello" | "world"'. -!!! error TS2322: Type 'string' is not assignable to type '"world"'. fooProp: "frizzlebizzle" }); \ No newline at end of file diff --git a/tests/baselines/reference/genericCallWithTupleType.errors.txt b/tests/baselines/reference/genericCallWithTupleType.errors.txt index bcf580320e5..24e0505d009 100644 --- a/tests/baselines/reference/genericCallWithTupleType.errors.txt +++ b/tests/baselines/reference/genericCallWithTupleType.errors.txt @@ -3,7 +3,6 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup Type '() => string | number | boolean' is not assignable to type '() => string | number'. Type 'string | number | boolean' is not assignable to type 'string | number'. Type 'boolean' is not assignable to type 'string | number'. - Type 'boolean' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,1): error TS2322: Type '{ a: string; }' is not assignable to type 'string | number'. Type '{ a: string; }' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,1): error TS2322: Type '[number, string]' is not assignable to type '[string, number]'. @@ -35,7 +34,6 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup !!! error TS2322: Type '() => string | number | boolean' is not assignable to type '() => string | number'. !!! error TS2322: Type 'string | number | boolean' is not assignable to type 'string | number'. !!! error TS2322: Type 'boolean' is not assignable to type 'string | number'. -!!! error TS2322: Type 'boolean' is not assignable to type 'number'. var e3 = i1.tuple1[2]; // {} i1.tuple1[3] = { a: "string" }; ~~~~~~~~~~~~ diff --git a/tests/baselines/reference/iteratorSpreadInCall6.errors.txt b/tests/baselines/reference/iteratorSpreadInCall6.errors.txt index 0a0da985ace..ee9945f7af6 100644 --- a/tests/baselines/reference/iteratorSpreadInCall6.errors.txt +++ b/tests/baselines/reference/iteratorSpreadInCall6.errors.txt @@ -1,12 +1,10 @@ tests/cases/conformance/es6/spread/iteratorSpreadInCall6.ts(1,28): error TS2345: Argument of type 'string' is not assignable to parameter of type 'symbol | number'. - Type 'string' is not assignable to type 'number'. ==== tests/cases/conformance/es6/spread/iteratorSpreadInCall6.ts (1 errors) ==== foo(...new SymbolIterator, ...new StringIterator); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'symbol | number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. function foo(...s: (symbol | number)[]) { } class SymbolIterator { diff --git a/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt b/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt index ef582ab9b26..48c7efb37e8 100644 --- a/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt +++ b/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt @@ -4,15 +4,10 @@ tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes0 tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(40,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(41,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(44,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. - Type 'string' is not assignable to type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(45,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. - Type 'string' is not assignable to type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(46,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. - Type 'string' is not assignable to type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(47,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. - Type 'string' is not assignable to type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(48,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. - Type 'string' is not assignable to type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(55,43): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(57,52): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(58,43): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. @@ -26,9 +21,7 @@ tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes0 tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(88,43): error TS2345: Argument of type '"Hello"' is not assignable to parameter of type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(89,52): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(93,5): error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. - Type 'string' is not assignable to type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(97,5): error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. - Type 'string' is not assignable to type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(100,25): error TS2345: Argument of type '"Hello" | "World"' is not assignable to parameter of type '"Hello"'. Type '"World"' is not assignable to type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(104,25): error TS2345: Argument of type '"Hello" | "World"' is not assignable to parameter of type '"Hello"'. @@ -92,23 +85,18 @@ tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes0 a = takeReturnHelloWorld(a); ~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. -!!! error TS2345: Type 'string' is not assignable to type '"World"'. b = takeReturnHelloWorld(b); ~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. -!!! error TS2345: Type 'string' is not assignable to type '"World"'. c = takeReturnHelloWorld(c); ~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. -!!! error TS2345: Type 'string' is not assignable to type '"World"'. d = takeReturnHelloWorld(d); ~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. -!!! error TS2345: Type 'string' is not assignable to type '"World"'. e = takeReturnHelloWorld(e); ~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. -!!! error TS2345: Type 'string' is not assignable to type '"World"'. } namespace n2 { @@ -178,14 +166,12 @@ tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes0 a = takeReturnString(a); ~ !!! error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. -!!! error TS2322: Type 'string' is not assignable to type '"World"'. b = takeReturnString(b); c = takeReturnString(c); d = takeReturnString(d); e = takeReturnString(e); ~ !!! error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. -!!! error TS2322: Type 'string' is not assignable to type '"World"'. // Passing these as arguments should cause an error. a = takeReturnHello(a); From 2901425d41cfc6d89632ef20eb18623b39de0cd2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 7 Apr 2016 16:16:34 -0700 Subject: [PATCH 3/5] remove trailing commas --- src/compiler/visitor.ts | 178 ++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 81f36399b62..d55357bed8d 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -46,27 +46,27 @@ namespace ts { const nodeEdgeTraversalMap: Map = { [SyntaxKind.QualifiedName]: [ { name: "left", test: isEntityName }, - { name: "right", test: isIdentifier }, + { name: "right", test: isIdentifier } ], [SyntaxKind.ComputedPropertyName]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.Parameter]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isBindingName }, { name: "type", test: isTypeNode, optional: true }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.Decorator]: [ - { name: "expression", test: isLeftHandSideExpression }, + { name: "expression", test: isLeftHandSideExpression } ], [SyntaxKind.PropertyDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isPropertyName }, { name: "type", test: isTypeNode, optional: true }, - { name: "initializer", test: isExpression, optional: true }, + { name: "initializer", test: isExpression, optional: true } ], [SyntaxKind.MethodDeclaration]: [ { name: "decorators", test: isDecorator }, @@ -75,7 +75,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.Constructor]: [ { name: "decorators", test: isDecorator }, @@ -83,7 +83,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.GetAccessor]: [ { name: "decorators", test: isDecorator }, @@ -92,7 +92,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.SetAccessor]: [ { name: "decorators", test: isDecorator }, @@ -101,53 +101,53 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.ObjectBindingPattern]: [ - { name: "elements", test: isBindingElement }, + { name: "elements", test: isBindingElement } ], [SyntaxKind.ArrayBindingPattern]: [ - { name: "elements", test: isBindingElement }, + { name: "elements", test: isBindingElement } ], [SyntaxKind.BindingElement]: [ { name: "propertyName", test: isPropertyName, optional: true }, { name: "name", test: isBindingName }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ArrayLiteralExpression]: [ - { name: "elements", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "elements", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ObjectLiteralExpression]: [ - { name: "properties", test: isObjectLiteralElement }, + { name: "properties", test: isObjectLiteralElement } ], [SyntaxKind.PropertyAccessExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.ElementAccessExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "argumentExpression", test: isExpression }, + { name: "argumentExpression", test: isExpression } ], [SyntaxKind.CallExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, { name: "typeArguments", test: isTypeNode }, - { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.NewExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForNew }, { name: "typeArguments", test: isTypeNode }, - { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.TaggedTemplateExpression]: [ { name: "tag", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "template", test: isTemplate }, + { name: "template", test: isTemplate } ], [SyntaxKind.TypeAssertionExpression]: [ { name: "type", test: isTypeNode }, - { name: "expression", test: isUnaryExpression }, + { name: "expression", test: isUnaryExpression } ], [SyntaxKind.ParenthesizedExpression]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.FunctionExpression]: [ { name: "decorators", test: isDecorator }, @@ -156,7 +156,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.ArrowFunction]: [ { name: "decorators", test: isDecorator }, @@ -164,44 +164,44 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isConciseBody, lift: liftToBlock, parenthesize: parenthesizeConciseBody }, + { name: "body", test: isConciseBody, lift: liftToBlock, parenthesize: parenthesizeConciseBody } ], [SyntaxKind.DeleteExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.TypeOfExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.VoidExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.AwaitExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.PrefixUnaryExpression]: [ - { name: "operand", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "operand", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.PostfixUnaryExpression]: [ - { name: "operand", test: isLeftHandSideExpression, parenthesize: parenthesizePostfixOperand }, + { name: "operand", test: isLeftHandSideExpression, parenthesize: parenthesizePostfixOperand } ], [SyntaxKind.BinaryExpression]: [ { name: "left", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, true, /*leftOperand*/ undefined) }, - { name: "right", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, false, parent.left) }, + { name: "right", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, false, parent.left) } ], [SyntaxKind.ConditionalExpression]: [ { name: "condition", test: isExpression }, { name: "whenTrue", test: isExpression }, - { name: "whenFalse", test: isExpression }, + { name: "whenFalse", test: isExpression } ], [SyntaxKind.TemplateExpression]: [ { name: "head", test: isTemplateLiteralFragment }, - { name: "templateSpans", test: isTemplateSpan }, + { name: "templateSpans", test: isTemplateSpan } ], [SyntaxKind.YieldExpression]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.SpreadElementExpression]: [ - { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ClassExpression]: [ { name: "decorators", test: isDecorator }, @@ -209,96 +209,96 @@ namespace ts { { name: "name", test: isIdentifier, optional: true }, { name: "typeParameters", test: isTypeParameter }, { name: "heritageClauses", test: isHeritageClause }, - { name: "members", test: isClassElement }, + { name: "members", test: isClassElement } ], [SyntaxKind.ExpressionWithTypeArguments]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "typeArguments", test: isTypeNode }, + { name: "typeArguments", test: isTypeNode } ], [SyntaxKind.AsExpression]: [ { name: "expression", test: isExpression }, - { name: "type", test: isTypeNode }, + { name: "type", test: isTypeNode } ], [SyntaxKind.TemplateSpan]: [ { name: "expression", test: isExpression }, - { name: "literal", test: isTemplateLiteralFragment }, + { name: "literal", test: isTemplateLiteralFragment } ], [SyntaxKind.Block]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.VariableStatement]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, - { name: "declarationList", test: isVariableDeclarationList }, + { name: "declarationList", test: isVariableDeclarationList } ], [SyntaxKind.ExpressionStatement]: [ - { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForExpressionStatement }, + { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForExpressionStatement } ], [SyntaxKind.IfStatement]: [ { name: "expression", test: isExpression }, { name: "thenStatement", test: isStatement, lift: liftToBlock }, - { name: "elseStatement", test: isStatement, lift: liftToBlock, optional: true }, + { name: "elseStatement", test: isStatement, lift: liftToBlock, optional: true } ], [SyntaxKind.DoStatement]: [ { name: "statement", test: isStatement, lift: liftToBlock }, - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.WhileStatement]: [ { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ForStatement]: [ { name: "initializer", test: isForInitializer, optional: true }, { name: "condition", test: isExpression, optional: true }, { name: "incrementor", test: isExpression, optional: true }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ForInStatement]: [ { name: "initializer", test: isForInitializer }, { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ForOfStatement]: [ { name: "initializer", test: isForInitializer }, { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ContinueStatement]: [ - { name: "label", test: isIdentifier, optional: true }, + { name: "label", test: isIdentifier, optional: true } ], [SyntaxKind.BreakStatement]: [ - { name: "label", test: isIdentifier, optional: true }, + { name: "label", test: isIdentifier, optional: true } ], [SyntaxKind.ReturnStatement]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.WithStatement]: [ { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.SwitchStatement]: [ { name: "expression", test: isExpression }, - { name: "caseBlock", test: isCaseBlock }, + { name: "caseBlock", test: isCaseBlock } ], [SyntaxKind.LabeledStatement]: [ { name: "label", test: isIdentifier }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ThrowStatement]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.TryStatement]: [ { name: "tryBlock", test: isBlock }, { name: "catchClause", test: isCatchClause, optional: true }, - { name: "finallyBlock", test: isBlock, optional: true }, + { name: "finallyBlock", test: isBlock, optional: true } ], [SyntaxKind.VariableDeclaration]: [ { name: "name", test: isBindingName }, { name: "type", test: isTypeNode, optional: true }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.VariableDeclarationList]: [ - { name: "declarations", test: isVariableDeclaration }, + { name: "declarations", test: isVariableDeclaration } ], [SyntaxKind.FunctionDeclaration]: [ { name: "decorators", test: isDecorator }, @@ -307,7 +307,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.ClassDeclaration]: [ { name: "decorators", test: isDecorator }, @@ -315,127 +315,127 @@ namespace ts { { name: "name", test: isIdentifier, optional: true }, { name: "typeParameters", test: isTypeParameter }, { name: "heritageClauses", test: isHeritageClause }, - { name: "members", test: isClassElement }, + { name: "members", test: isClassElement } ], [SyntaxKind.EnumDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isIdentifier }, - { name: "members", test: isEnumMember }, + { name: "members", test: isEnumMember } ], [SyntaxKind.ModuleDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isModuleName }, - { name: "body", test: isModuleBody }, + { name: "body", test: isModuleBody } ], [SyntaxKind.ModuleBlock]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.CaseBlock]: [ - { name: "clauses", test: isCaseOrDefaultClause }, + { name: "clauses", test: isCaseOrDefaultClause } ], [SyntaxKind.ImportEqualsDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isIdentifier }, - { name: "moduleReference", test: isModuleReference }, + { name: "moduleReference", test: isModuleReference } ], [SyntaxKind.ImportDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "importClause", test: isImportClause, optional: true }, - { name: "moduleSpecifier", test: isExpression }, + { name: "moduleSpecifier", test: isExpression } ], [SyntaxKind.ImportClause]: [ { name: "name", test: isIdentifier, optional: true }, - { name: "namedBindings", test: isNamedImportBindings, optional: true }, + { name: "namedBindings", test: isNamedImportBindings, optional: true } ], [SyntaxKind.NamespaceImport]: [ - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.NamedImports]: [ - { name: "elements", test: isImportSpecifier }, + { name: "elements", test: isImportSpecifier } ], [SyntaxKind.ImportSpecifier]: [ { name: "propertyName", test: isIdentifier, optional: true }, - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.ExportAssignment]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.ExportDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "exportClause", test: isNamedExports, optional: true }, - { name: "moduleSpecifier", test: isExpression, optional: true }, + { name: "moduleSpecifier", test: isExpression, optional: true } ], [SyntaxKind.NamedExports]: [ - { name: "elements", test: isExportSpecifier }, + { name: "elements", test: isExportSpecifier } ], [SyntaxKind.ExportSpecifier]: [ { name: "propertyName", test: isIdentifier, optional: true }, - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.ExternalModuleReference]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.JsxElement]: [ { name: "openingElement", test: isJsxOpeningElement }, { name: "children", test: isJsxChild }, - { name: "closingElement", test: isJsxClosingElement }, + { name: "closingElement", test: isJsxClosingElement } ], [SyntaxKind.JsxSelfClosingElement]: [ { name: "tagName", test: isEntityName }, - { name: "attributes", test: isJsxAttributeLike }, + { name: "attributes", test: isJsxAttributeLike } ], [SyntaxKind.JsxOpeningElement]: [ { name: "tagName", test: isEntityName }, - { name: "attributes", test: isJsxAttributeLike }, + { name: "attributes", test: isJsxAttributeLike } ], [SyntaxKind.JsxClosingElement]: [ - { name: "tagName", test: isEntityName }, + { name: "tagName", test: isEntityName } ], [SyntaxKind.JsxAttribute]: [ { name: "name", test: isIdentifier }, - { name: "initializer", test: isStringLiteralOrJsxExpression, optional: true }, + { name: "initializer", test: isStringLiteralOrJsxExpression, optional: true } ], [SyntaxKind.JsxSpreadAttribute]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.JsxExpression]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.CaseClause]: [ { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList }, - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.DefaultClause]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.HeritageClause]: [ - { name: "types", test: isExpressionWithTypeArguments }, + { name: "types", test: isExpressionWithTypeArguments } ], [SyntaxKind.CatchClause]: [ { name: "variableDeclaration", test: isVariableDeclaration }, - { name: "block", test: isBlock }, + { name: "block", test: isBlock } ], [SyntaxKind.PropertyAssignment]: [ { name: "name", test: isPropertyName }, - { name: "initializer", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ShorthandPropertyAssignment]: [ { name: "name", test: isIdentifier }, - { name: "objectAssignmentInitializer", test: isExpression, optional: true }, + { name: "objectAssignmentInitializer", test: isExpression, optional: true } ], [SyntaxKind.EnumMember]: [ { name: "name", test: isPropertyName }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.SourceFile]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.NotEmittedStatement]: [], [SyntaxKind.PartiallyEmittedExpression]: [ From 68170dfbdba7b0c45b0a81b7e525ffb308ce67b6 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 7 Apr 2016 16:17:58 -0700 Subject: [PATCH 4/5] Add a source mapping to the closing `}` for functions, and wire in positions for class transfomtaion --- src/compiler/printer.ts | 14 ++++++-------- src/compiler/transformers/es6.ts | 16 ++++++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 4193ac6ef75..23220b25f42 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -1095,7 +1095,7 @@ const _super = (function (geti, seti) { } function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { - writeToken(node.operator); + writeTokenText(node.operator); if (shouldEmitWhitespaceBeforeOperand(node)) { write(" "); } @@ -1123,7 +1123,7 @@ const _super = (function (geti, seti) { function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { emitExpression(node.operand); - writeToken(node.operator); + writeTokenText(node.operator); } function emitBinaryExpression(node: BinaryExpression) { @@ -1419,8 +1419,7 @@ const _super = (function (geti, seti) { emitSignatureHead(node); write(" {"); emitBlockFunctionBody(node, body); - write("}"); - + writeToken(SyntaxKind.CloseBraceToken, node.end) if (indentedFlag) { decreaseIndent(); } @@ -1826,7 +1825,7 @@ const _super = (function (geti, seti) { function emitHeritageClause(node: HeritageClause) { write(" "); - writeToken(node.token); + writeTokenText(node.token); write(" "); emitList(node, node.types, ListFormat.HeritageClauseTypes); } @@ -2275,10 +2274,9 @@ const _super = (function (geti, seti) { } } - function writeToken(token: SyntaxKind, pos?: number) { - const tokenStartPos = skipTrivia(currentText, pos); + function writeToken(token: SyntaxKind, tokenStartPos: number) { emitPos(tokenStartPos); - const tokenEndPos = writeTokenText(token, pos); + const tokenEndPos = writeTokenText(token, tokenStartPos); emitPos(tokenEndPos); return tokenEndPos; } diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index d1c443f8401..98c94d7c6a9 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -609,12 +609,14 @@ namespace ts { if (node.name) { enableSubstitutionsForBlockScopedBindings(); } + const closingBraceLocation = { pos: node.end - 1, end: node.end }; const baseTypeNode = getClassExtendsHeritageClauseElement(node); const classFunction = createFunctionExpression( /*asteriskToken*/ undefined, /*name*/ undefined, baseTypeNode ? [createParameter("_super")] : [], - transformClassBody(node, baseTypeNode !== undefined) + transformClassBody(node, baseTypeNode !== undefined, closingBraceLocation), + closingBraceLocation ); // To preserve the behavior of the old emitter, we explicitly indent @@ -629,8 +631,10 @@ namespace ts { classFunction, baseTypeNode ? [visitNode(baseTypeNode.expression, visitor, isExpression)] - : [] - ) + : [], + closingBraceLocation + ), + closingBraceLocation ); } @@ -640,13 +644,13 @@ namespace ts { * @param node A ClassExpression or ClassDeclaration node. * @param hasExtendsClause A value indicating whether the class has an `extends` clause. */ - function transformClassBody(node: ClassExpression | ClassDeclaration, hasExtendsClause: boolean): Block { + function transformClassBody(node: ClassExpression | ClassDeclaration, hasExtendsClause: boolean, closingBraceLocation: TextRange): Block { const statements: Statement[] = []; startLexicalEnvironment(); addExtendsHelperIfNeeded(statements, node, hasExtendsClause); addConstructor(statements, node, hasExtendsClause); addClassMembers(statements, node); - statements.push(createReturn(getDeclarationName(node))); + statements.push(createReturn(getDeclarationName(node), /*location*/ closingBraceLocation)); addRange(statements, endLexicalEnvironment()); return createBlock(statements, /*location*/ undefined, /*multiLine*/ true); } @@ -685,7 +689,7 @@ namespace ts { getDeclarationName(node), transformConstructorParameters(constructor, hasSynthesizedSuper), transformConstructorBody(constructor, hasExtendsClause, hasSynthesizedSuper), - /*location*/ constructor + /*location*/ constructor || node ) ); } From 6225a5aa401e1c67e544a648ffbc417cc707f802 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 15 Apr 2016 18:39:30 -0700 Subject: [PATCH 5/5] Addesses a number of comment/sourcemap related issues --- src/compiler/comments.ts | 32 +++++- src/compiler/factory.ts | 9 +- src/compiler/printer.ts | 62 +++++++---- src/compiler/transformers/es6.ts | 102 ++++++++++++++---- src/compiler/utilities.ts | 59 +++++++++- ...ntextualTypeWithUnionTypeCallSignatures.js | 4 +- .../disallowLineTerminatorBeforeArrow.js | 4 +- 7 files changed, 211 insertions(+), 61 deletions(-) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 1baf1847f04..3e02558117b 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -13,7 +13,10 @@ namespace ts { getTrailingCommentsOfPosition(pos: number): CommentRange[]; emitLeadingComments(range: TextRange, comments: CommentRange[]): void; emitTrailingComments(range: TextRange, comments: CommentRange[]): void; - emitDetachedComments(range: TextRange): void; + emitLeadingDetachedComments(range: TextRange): void; + emitLeadingDetachedComments(range: TextRange, contextNode: Node, shouldSkipCommentsForNodeCallback: (node: Node) => boolean): void; + emitTrailingDetachedComments(range: TextRange): void; + emitTrailingDetachedComments(range: TextRange, contextNode: Node, shouldSkipCommentsForNodeCallback: (node: Node) => boolean): void; } export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter { @@ -46,10 +49,15 @@ namespace ts { getTrailingCommentsOfPosition(pos: number): CommentRange[] { return undefined; }, emitLeadingComments(range: TextRange, comments: CommentRange[]): void { }, emitTrailingComments(range: TextRange, comments: CommentRange[]): void { }, - emitDetachedComments, + emitLeadingDetachedComments, + emitTrailingDetachedComments(node: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void {} }; - function emitDetachedComments(node: TextRange): void { + function emitLeadingDetachedComments(node: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void { + if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(contextNode)) { + return; + } + emitDetachedCommentsAndUpdateCommentsInfo(node, /*removeComments*/ true); } } @@ -65,7 +73,8 @@ namespace ts { getTrailingCommentsOfPosition, emitLeadingComments, emitTrailingComments, - emitDetachedComments, + emitLeadingDetachedComments, + emitTrailingDetachedComments }; function getLeadingComments(range: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): CommentRange[]; @@ -154,10 +163,23 @@ namespace ts { emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment); } - function emitDetachedComments(range: TextRange) { + function emitLeadingDetachedComments(range: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void { + if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(contextNode)) { + return; + } + emitDetachedCommentsAndUpdateCommentsInfo(range, /*removeComments*/ false); } + function emitTrailingDetachedComments(range: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void { + if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(contextNode)) { + return; + } + + range = collapseRangeToEnd(range); + emitLeadingComments(range, getLeadingComments(range)); + } + function hasConsumedCommentRange(comment: CommentRange) { return comment.end === consumedCommentRanges[comment.pos]; } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 928ba76699e..8721a03ad71 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -651,13 +651,14 @@ namespace ts { /** * Creates a synthetic expression to act as a placeholder for a not-emitted expression in - * order to preserve comments. + * order to preserve comments or sourcemap positions. * * @param expression The inner expression to emit. * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. */ - export function createPartiallyEmittedExpression(expression: Expression, original: Node) { - const node = createNode(SyntaxKind.PartiallyEmittedExpression, /*location*/ original); + export function createPartiallyEmittedExpression(expression: Expression, original?: Node, location?: TextRange) { + const node = createNode(SyntaxKind.PartiallyEmittedExpression, /*location*/ location || original); node.expression = expression; node.original = original; return node; @@ -1257,7 +1258,7 @@ namespace ts { * The function needs to be called during each transformation step. * This function needs to be called whenever we transform the statement * list of a source file, namespace, or function-like body. - * + * * @param target: result statements array * @param source: origin statements array * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 619b3745e70..b5cc8206688 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -140,7 +140,8 @@ const _super = (function (geti, seti) { getTrailingCommentsOfPosition, emitLeadingComments, emitTrailingComments, - emitDetachedComments + emitLeadingDetachedComments, + emitTrailingDetachedComments } = comments; let context: TransformationContext; @@ -298,24 +299,45 @@ const _super = (function (geti, seti) { const leadingComments = getLeadingComments(node, shouldSkipCommentsForNode); const trailingComments = getTrailingComments(node, shouldSkipCommentsForNode); emitLeadingComments(node, leadingComments); - emitStart(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren); + emitStart(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren); emitWorker(node); - emitEnd(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren); + emitEnd(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren); emitTrailingComments(node, trailingComments); } } + /** + * Determines whether to skip comment emit for a node. + * + * We do not emit comments for NotEmittedStatement nodes or any node that has + * NodeEmitFlags.NoComments. + * + * @param node A Node. + */ function shouldSkipCommentsForNode(node: Node) { return isNotEmittedStatement(node) || (getNodeEmitFlags(node) & NodeEmitFlags.NoComments) !== 0; } - function shouldIgnoreSourceMapForNode(node: Node) { - return isNotEmittedOrPartiallyEmittedNode(node) + /** + * Determines whether to skip source map emit for a node. + * + * We do not emit source maps for NotEmittedStatement nodes or any node that + * has NodeEmitFlags.NoSourceMap. + * + * @param node A Node. + */ + function shouldSkipSourceMapForNode(node: Node) { + return isNotEmittedStatement(node) || (getNodeEmitFlags(node) & NodeEmitFlags.NoSourceMap) !== 0; } - function shouldIgnoreSourceMapForChildren(node: Node) { + /** + * Determines whether to skip source map emit for a node and its children. + * + * We do not emit source maps for a node that has NodeEmitFlags.NoNestedSourceMaps. + */ + function shouldSkipSourceMapForChildren(node: Node) { return (getNodeEmitFlags(node) & NodeEmitFlags.NoNestedSourceMaps) !== 0; } @@ -1064,7 +1086,6 @@ const _super = (function (geti, seti) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emitSignatureAndBody(node, emitArrowFunctionHead); - } function emitArrowFunctionHead(node: ArrowFunction) { @@ -1375,7 +1396,8 @@ const _super = (function (geti, seti) { } function emitDebuggerStatement(node: DebuggerStatement) { - write("debugger;"); + writeToken(SyntaxKind.DebuggerKeyword, node.pos); + write(";"); } // @@ -1417,9 +1439,7 @@ const _super = (function (geti, seti) { tempFlags = 0; startLexicalEnvironment(); emitSignatureHead(node); - write(" {"); - emitBlockFunctionBody(node, body); - writeToken(SyntaxKind.CloseBraceToken, node.end) + emitBlockFunctionBodyAndEndLexicalEnvironment(node, body); if (indentedFlag) { decreaseIndent(); } @@ -1483,10 +1503,12 @@ const _super = (function (geti, seti) { return true; } - function emitBlockFunctionBody(parentNode: Node, body: Block) { + function emitBlockFunctionBodyAndEndLexicalEnvironment(parentNode: Node, body: Block) { + write(" {"); + const startingLine = writer.getLine(); increaseIndent(); - emitDetachedComments(body.statements); + emitLeadingDetachedComments(body.statements, body, shouldSkipCommentsForNode); // Emit all the prologue directives (like "use strict"). const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); @@ -1503,10 +1525,9 @@ const _super = (function (geti, seti) { const endingLine = writer.getLine(); emitLexicalEnvironment(endLexicalEnvironment(), /*newLine*/ startingLine !== endingLine); - - const range = collapseRangeToEnd(body.statements); - emitLeadingComments(range, getLeadingComments(range)); + emitTrailingDetachedComments(body.statements, body, shouldSkipCommentsForNode); decreaseIndent(); + writeToken(SyntaxKind.CloseBraceToken, body.statements.end); } function emitClassDeclaration(node: ClassDeclaration) { @@ -1882,7 +1903,7 @@ const _super = (function (geti, seti) { function emitSourceFile(node: SourceFile) { writeLine(); emitShebang(); - emitDetachedComments(node); + emitLeadingDetachedComments(node); const statements = node.statements; const statementOffset = emitPrologueDirectives(statements); @@ -1900,7 +1921,7 @@ const _super = (function (geti, seti) { tempFlags = savedTempFlags; } - emitLeadingComments(node.endOfFileToken, getLeadingComments(node.endOfFileToken)); + emitTrailingDetachedComments(node.statements); } // Transformation nodes @@ -2281,6 +2302,7 @@ const _super = (function (geti, seti) { } function writeToken(token: SyntaxKind, tokenStartPos: number) { + tokenStartPos = skipTrivia(currentText, tokenStartPos); emitPos(tokenStartPos); const tokenEndPos = writeTokenText(token, tokenStartPos); emitPos(tokenEndPos); @@ -2295,9 +2317,9 @@ const _super = (function (geti, seti) { function writeTokenNode(node: Node) { if (node) { - emitStart(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren); + emitStart(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren); writeTokenText(node.kind); - emitEnd(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren); + emitEnd(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren); } } diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 6aa373a4ef4..b66e7cc0b5a 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -156,6 +156,7 @@ namespace ts { context.expressionSubstitution = substituteExpression; let currentSourceFile: SourceFile; + let currentText: string; let currentParent: Node; let currentNode: Node; let enclosingBlockScopeContainer: Node; @@ -183,6 +184,7 @@ namespace ts { function transformSourceFile(node: SourceFile) { currentSourceFile = node; + currentText = node.text; return visitNode(node, visitor, isSourceFile); } @@ -609,14 +611,14 @@ namespace ts { if (node.name) { enableSubstitutionsForBlockScopedBindings(); } + const closingBraceLocation = { pos: node.end - 1, end: node.end }; const baseTypeNode = getClassExtendsHeritageClauseElement(node); const classFunction = createFunctionExpression( /*asteriskToken*/ undefined, /*name*/ undefined, baseTypeNode ? [createParameter("_super")] : [], - transformClassBody(node, baseTypeNode !== undefined, closingBraceLocation), - closingBraceLocation + transformClassBody(node, baseTypeNode !== undefined) ); // To preserve the behavior of the old emitter, we explicitly indent @@ -626,15 +628,23 @@ namespace ts { setNodeEmitFlags(classFunction, NodeEmitFlags.Indented); } + // "inner" and "outer" below are added purely to preserve source map locations from + // the old emitter + const inner = createPartiallyEmittedExpression(classFunction); + inner.end = node.end; + setNodeEmitFlags(inner, NodeEmitFlags.NoComments); + + const outer = createPartiallyEmittedExpression(inner); + outer.end = node.pos; + setNodeEmitFlags(outer, NodeEmitFlags.NoComments); + return createParen( createCall( - classFunction, + outer, baseTypeNode ? [visitNode(baseTypeNode.expression, visitor, isExpression)] - : [], - closingBraceLocation - ), - closingBraceLocation + : [] + ) ); } @@ -644,15 +654,33 @@ namespace ts { * @param node A ClassExpression or ClassDeclaration node. * @param hasExtendsClause A value indicating whether the class has an `extends` clause. */ - function transformClassBody(node: ClassExpression | ClassDeclaration, hasExtendsClause: boolean, closingBraceLocation: TextRange): Block { + function transformClassBody(node: ClassExpression | ClassDeclaration, hasExtendsClause: boolean): Block { const statements: Statement[] = []; startLexicalEnvironment(); addExtendsHelperIfNeeded(statements, node, hasExtendsClause); addConstructor(statements, node, hasExtendsClause); addClassMembers(statements, node); - statements.push(createReturn(getDeclarationName(node), /*location*/ closingBraceLocation)); + + // Create a synthetic text range for the return statement. + const closingBraceLocation = createTokenRange(skipTrivia(currentText, node.members.end), SyntaxKind.CloseBraceToken); + const name = getDeclarationName(node); + + // The following partially-emitted expression exists purely to align our sourcemap + // emit with the original emitter. + const outer = createPartiallyEmittedExpression(name); + outer.end = closingBraceLocation.end; + setNodeEmitFlags(outer, NodeEmitFlags.NoComments); + + const statement = createReturn(outer); + statement.pos = closingBraceLocation.pos; + statements.push(statement); + setNodeEmitFlags(statement, NodeEmitFlags.NoComments); + addRange(statements, endLexicalEnvironment()); - return createBlock(statements, /*location*/ undefined, /*multiLine*/ true); + const block = createBlock(createNodeArray(statements, /*location*/ node.members), /*location*/ undefined, /*multiLine*/ true); + setNodeEmitFlags(block, NodeEmitFlags.NoComments); + + return block; } /** @@ -688,7 +716,7 @@ namespace ts { /*asteriskToken*/ undefined, getDeclarationName(node), transformConstructorParameters(constructor, hasSynthesizedSuper), - transformConstructorBody(constructor, hasExtendsClause, hasSynthesizedSuper), + transformConstructorBody(constructor, node, hasExtendsClause, hasSynthesizedSuper), /*location*/ constructor || node ) ); @@ -718,11 +746,12 @@ namespace ts { * Transforms the body of a constructor declaration of a class. * * @param constructor The constructor for the class. + * @param node The node which contains the constructor. * @param hasExtendsClause A value indicating whether the class has an `extends` clause. * @param hasSynthesizedSuper A value indicating whether the constructor starts with a * synthesized `super` call. */ - function transformConstructorBody(constructor: ConstructorDeclaration, hasExtendsClause: boolean, hasSynthesizedSuper: boolean) { + function transformConstructorBody(constructor: ConstructorDeclaration, node: ClassDeclaration | ClassExpression, hasExtendsClause: boolean, hasSynthesizedSuper: boolean) { const statements: Statement[] = []; startLexicalEnvironment(); if (constructor) { @@ -739,14 +768,20 @@ namespace ts { } addRange(statements, endLexicalEnvironment()); - return createBlock( + const block = createBlock( createNodeArray( statements, - /*location*/ constructor ? constructor.body.statements : undefined + /*location*/ constructor ? constructor.body.statements : node.members ), - /*location*/ constructor ? constructor.body : undefined, + /*location*/ constructor ? constructor.body : node, /*multiLine*/ true ); + + if (!constructor) { + setNodeEmitFlags(block, NodeEmitFlags.NoComments); + } + + return block; } function transformConstructorBodyWithSynthesizedSuper(node: ConstructorDeclaration) { @@ -1077,16 +1112,24 @@ namespace ts { * @param member The MethodDeclaration node. */ function transformClassMethodDeclarationToStatement(receiver: LeftHandSideExpression, member: MethodDeclaration) { - return createStatement( + const statement = createStatement( createAssignment( createMemberAccessForPropertyName( receiver, - visitNode(member.name, visitor, isPropertyName) + visitNode(member.name, visitor, isPropertyName), + /*location*/ member.name ), - transformFunctionLikeToExpression(member, /*location*/ undefined, /*name*/ undefined) + transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined), + /*location*/ moveRangeEnd(member, -1) ), /*location*/ member ); + + // The location for the statement is used to emit comments only. + // No source map should be emitted for this statement to align with the + // old emitter. + setNodeEmitFlags(statement, NodeEmitFlags.NoSourceMap); + return statement; } /** @@ -1096,9 +1139,16 @@ namespace ts { * @param accessors The set of related get/set accessors. */ function transformAccessorsToStatement(receiver: LeftHandSideExpression, accessors: AllAccessorDeclarations): Statement { - return createStatement( - transformAccessorsToExpression(receiver, accessors) + const statement = createStatement( + transformAccessorsToExpression(receiver, accessors), + /*location*/ accessors.firstAccessor ); + + // The location for the statement is used to emit source maps only. + // No comments should be emitted for this statement to align with the + // old emitter. + setNodeEmitFlags(statement, NodeEmitFlags.NoComments); + return statement; } /** @@ -1122,7 +1172,7 @@ namespace ts { configurable: true }, /*preferNewLine*/ true, - /*location*/ firstAccessor, + /*location*/ undefined, /*descriptorLocations*/ { get: getAccessor, set: setAccessor @@ -1224,6 +1274,7 @@ namespace ts { // addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false); } + addCaptureThisForNodeIfNeeded(statements, node); addDefaultValueAssignmentsIfNeeded(statements, node); addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false); @@ -1244,7 +1295,12 @@ namespace ts { } else { Debug.assert(node.kind === SyntaxKind.ArrowFunction); - statementsLocation = body; + + // To align with the old emitter, we use a synthetic end position on the location + // for the statement list we synthesize when we down-level an arrow function with + // an expression function body. This prevents both comments and source maps from + // being emitted for the end position only. + statementsLocation = moveRangeEnd(body, -1); const equalsGreaterThanToken = (node).equalsGreaterThanToken; if (!nodeIsSynthesized(equalsGreaterThanToken) && !nodeIsSynthesized(body)) { @@ -1258,7 +1314,7 @@ namespace ts { const expression = visitNode(body, visitor, isExpression); if (expression) { - statements.push(createReturn(expression)); + statements.push(createReturn(expression, /*location*/ statementsLocation)); } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bf6881b9810..8b09e521d51 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2943,12 +2943,63 @@ namespace ts { } } - export function collapseRangeToStart(range: TextRange) { - return range.pos === range.end ? range : { pos: range.pos, end: range.pos }; + /** + * Creates a new TextRange from a provided range with a new end position. + * + * @param range A TextRange. + * @param end The new end position. + */ + export function moveRangeEnd(range: TextRange, end: number): TextRange { + return { pos: range.pos, end }; } - export function collapseRangeToEnd(range: TextRange) { - return range.pos === range.end ? range : { pos: range.end, end: range.end }; + /** + * Creates a new TextRange from a provided range with a new start position. + * + * @param range A TextRange. + * @param pos The new Start position. + */ + export function moveRangePos(range: TextRange, pos: number): TextRange { + return { pos, end: range.end }; + } + + /** + * Determines whether a TextRange has the same start and end positions. + * + * @param range A TextRange. + */ + export function isCollapsedRange(range: TextRange) { + return range.pos === range.end; + } + + /** + * Creates a new TextRange from a provided range with its end position collapsed to its + * start position. + * + * @param range A TextRange. + */ + export function collapseRangeToStart(range: TextRange): TextRange { + return isCollapsedRange(range) ? range : moveRangeEnd(range, range.pos); + } + + /** + * Creates a new TextRange from a provided range with its start position collapsed to its + * end position. + * + * @param range A TextRange. + */ + export function collapseRangeToEnd(range: TextRange): TextRange { + return isCollapsedRange(range) ? range : moveRangePos(range, range.end); + } + + /** + * Creates a new TextRange for a token at the provides start position. + * + * @param pos The start position. + * @param token The token. + */ + export function createTokenRange(pos: number, token: SyntaxKind): TextRange { + return { pos, end: pos + tokenToString(token).length }; } export function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile) { diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js index e29d4720cbc..bbe190f65b9 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js @@ -45,6 +45,6 @@ var x = function (a) { return a.toString(); }; var x2 = function (a) { return a.toString(); }; // Like iWithCallSignatures var x2 = function (a) { return a; }; // Like iWithCallSignatures2 // With call signatures of mismatching parameter type -var x3 = function (a) { return a.toString(); }; +var x3 = function (a) { /*here a should be any*/ return a.toString(); }; // With call signature count mismatch -var x4 = function (a) { return a.toString(); }; +var x4 = function (a) { /*here a should be any*/ return a.toString(); }; diff --git a/tests/baselines/reference/disallowLineTerminatorBeforeArrow.js b/tests/baselines/reference/disallowLineTerminatorBeforeArrow.js index 55fba8115e0..1044146ccd0 100644 --- a/tests/baselines/reference/disallowLineTerminatorBeforeArrow.js +++ b/tests/baselines/reference/disallowLineTerminatorBeforeArrow.js @@ -110,9 +110,7 @@ var f8 = function (x, y, z) { var f9 = function (a) { return a; }; var f10 = function (a) { return a; }; var f11 = function (a) { return a; }; -var f12 = function (a) { - return a; -}; +var f12 = function (a) { return a; }; // Should be valid. var f11 = function (a) { return a; }; // Should be valid.