diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index db13a2c03cd..afd493bc8f1 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3289,6 +3289,21 @@ module ts { decreaseIndent(); } + function emitSignatureParametersES6(node: FunctionLikeDeclaration) { + // Check the node's parameters whether it contains flags indicating that it has no parenthesis around the parameters + // Preserver no-parenthesis + if (node && node.flags & NodeFlags.SimpleArrowFunction) { + increaseIndent(); + var parameters = node.parameters; + var omitCount = languageVersion < ScriptTarget.ES6 && hasRestParameters(node) ? 1 : 0; + emitList(parameters, 0, parameters.length - omitCount, /*multiLine*/ false, /*trailingComma*/ false); + decreaseIndent(); + } + else { + emitSignatureParameters(node); + } + } + function emitSignatureAndBody(node: FunctionLikeDeclaration) { var saveTempCount = tempCount; var saveTempVariables = tempVariables; @@ -3296,12 +3311,15 @@ module ts { tempCount = 0; tempVariables = undefined; tempParameters = undefined; - emitSignatureParameters(node); // When targeting ES6, emit arrow function natively in ES6 if (isES6ArrowFunction(node)) { - write(" =>"); + emitSignatureParametersES6(node); + write(" =>"); } + else { + emitSignatureParameters(node); + } write(" {"); scopeEmitStart(node); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5ae44e5ff39..82fa5f2c579 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2883,6 +2883,9 @@ module ts { node.parameters = >[parameter]; node.parameters.pos = parameter.pos; node.parameters.end = parameter.end; + // Add node flags for simple arrow function(no parenthesis around parameters) + // so that in emit state we can check this flag and preserve users original text + node.flags |= NodeFlags.SimpleArrowFunction; parseExpected(SyntaxKind.EqualsGreaterThanToken); node.body = parseArrowFunctionExpressionBody(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b8c842641d7..fb1f2d8d5be 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -293,6 +293,8 @@ module ts { Const = 0x00001000, // Variable declaration OctalLiteral = 0x00002000, + SimpleArrowFunction = 0x00004000, // Arrow function without parenthesized parameters + Modifier = Export | Ambient | Public | Private | Protected | Static, AccessibilityModifier = Public | Private | Protected, BlockScoped = Let | Const diff --git a/tests/baselines/reference/emitArrowFunctionsAsIs.js b/tests/baselines/reference/emitArrowFunctionsAsIs.js new file mode 100644 index 00000000000..ee8347dda3e --- /dev/null +++ b/tests/baselines/reference/emitArrowFunctionsAsIs.js @@ -0,0 +1,13 @@ +//// [emitArrowFunctionsAsIs.ts] +var arrow1 = a => { }; +var arrow2 = (a) => { }; + +var arrow3 = (a, b) => { }; + +//// [emitArrowFunctionsAsIs.js] +var arrow1 = function (a) { +}; +var arrow2 = function (a) { +}; +var arrow3 = function (a, b) { +}; diff --git a/tests/baselines/reference/emitArrowFunctionsAsIs.types b/tests/baselines/reference/emitArrowFunctionsAsIs.types new file mode 100644 index 00000000000..36dae7e9c5a --- /dev/null +++ b/tests/baselines/reference/emitArrowFunctionsAsIs.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIs.ts === +var arrow1 = a => { }; +>arrow1 : (a: any) => void +>a => { } : (a: any) => void +>a : any + +var arrow2 = (a) => { }; +>arrow2 : (a: any) => void +>(a) => { } : (a: any) => void +>a : any + +var arrow3 = (a, b) => { }; +>arrow3 : (a: any, b: any) => void +>(a, b) => { } : (a: any, b: any) => void +>a : any +>b : any + diff --git a/tests/baselines/reference/emitArrowFunctionsAsIsES6.js b/tests/baselines/reference/emitArrowFunctionsAsIsES6.js new file mode 100644 index 00000000000..021e048ed88 --- /dev/null +++ b/tests/baselines/reference/emitArrowFunctionsAsIsES6.js @@ -0,0 +1,13 @@ +//// [emitArrowFunctionsAsIsES6.ts] +var arrow1 = a => { }; +var arrow2 = (a) => { }; + +var arrow3 = (a, b) => { }; + +//// [emitArrowFunctionsAsIsES6.js] +var arrow1 = a => { +}; +var arrow2 = (a) => { +}; +var arrow3 = (a, b) => { +}; diff --git a/tests/baselines/reference/emitArrowFunctionsAsIsES6.types b/tests/baselines/reference/emitArrowFunctionsAsIsES6.types new file mode 100644 index 00000000000..4073355d259 --- /dev/null +++ b/tests/baselines/reference/emitArrowFunctionsAsIsES6.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIsES6.ts === +var arrow1 = a => { }; +>arrow1 : (a: any) => void +>a => { } : (a: any) => void +>a : any + +var arrow2 = (a) => { }; +>arrow2 : (a: any) => void +>(a) => { } : (a: any) => void +>a : any + +var arrow3 = (a, b) => { }; +>arrow3 : (a: any, b: any) => void +>(a, b) => { } : (a: any, b: any) => void +>a : any +>b : any + diff --git a/tests/baselines/reference/parenthesizedContexualTyping3.js b/tests/baselines/reference/parenthesizedContexualTyping3.js index efff077d331..cc6dbd44f88 100644 --- a/tests/baselines/reference/parenthesizedContexualTyping3.js +++ b/tests/baselines/reference/parenthesizedContexualTyping3.js @@ -25,11 +25,11 @@ var h = tempFun `${ (x => x) } ${ (((x => x))) } ${ undefined }` function tempFun(tempStrs, g, x) { return g(x); } -var a = tempFun `${(x) => { return x; }} ${10}`; -var b = tempFun `${((x) => { return x; })} ${10}`; -var c = tempFun `${(((x) => { return x; }))} ${10}`; -var d = tempFun `${(x) => { return x; }} ${(x) => { return x; }} ${10}`; -var e = tempFun `${(x) => { return x; }} ${((x) => { return x; })} ${10}`; -var f = tempFun `${(x) => { return x; }} ${(((x) => { return x; }))} ${10}`; -var g = tempFun `${((x) => { return x; })} ${((((x) => { return x; })))} ${10}`; -var h = tempFun `${((x) => { return x; })} ${((((x) => { return x; })))} ${undefined}`; +var a = tempFun `${x => { return x; }} ${10}`; +var b = tempFun `${(x => { return x; })} ${10}`; +var c = tempFun `${((x => { return x; }))} ${10}`; +var d = tempFun `${x => { return x; }} ${x => { return x; }} ${10}`; +var e = tempFun `${x => { return x; }} ${(x => { return x; })} ${10}`; +var f = tempFun `${x => { return x; }} ${((x => { return x; }))} ${10}`; +var g = tempFun `${(x => { return x; })} ${(((x => { return x; })))} ${10}`; +var h = tempFun `${(x => { return x; })} ${(((x => { return x; })))} ${undefined}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping1.js b/tests/baselines/reference/taggedTemplateContextualTyping1.js index be8ec812741..173d0f56bb7 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping1.js +++ b/tests/baselines/reference/taggedTemplateContextualTyping1.js @@ -26,18 +26,18 @@ function tempTag1(...rest) { // Otherwise, the arrow functions' parameters will be typed as 'any', // and it is an error to invoke an any-typed value with type arguments, // so this test will error. -tempTag1 `${(x) => { +tempTag1 `${x => { x(undefined); return x; }}${10}`; -tempTag1 `${(x) => { +tempTag1 `${x => { x(undefined); return x; -}}${(y) => { +}}${y => { y(undefined); return y; }}${10}`; -tempTag1 `${(x) => { +tempTag1 `${x => { x(undefined); return x; }}${(y) => { @@ -47,7 +47,7 @@ tempTag1 `${(x) => { tempTag1 `${(x) => { x(undefined); return x; -}}${(y) => { +}}${y => { y(undefined); return y; }}${undefined}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping2.js b/tests/baselines/reference/taggedTemplateContextualTyping2.js index 387d5f49883..1eed600da4c 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping2.js +++ b/tests/baselines/reference/taggedTemplateContextualTyping2.js @@ -25,18 +25,18 @@ function tempTag2(...rest) { // Otherwise, the arrow functions' parameters will be typed as 'any', // and it is an error to invoke an any-typed value with type arguments, // so this test will error. -tempTag2 `${(x) => { +tempTag2 `${x => { x(undefined); return x; }}${0}`; -tempTag2 `${(x) => { +tempTag2 `${x => { x(undefined); return x; -}}${(y) => { +}}${y => { y(null); return y; }}${"hello"}`; -tempTag2 `${(x) => { +tempTag2 `${x => { x(undefined); return x; }}${undefined}${"hello"}`; diff --git a/tests/baselines/reference/taggedTemplateStringsTypeArgumentInferenceES6.js b/tests/baselines/reference/taggedTemplateStringsTypeArgumentInferenceES6.js index 8e96736e790..da39703931c 100644 --- a/tests/baselines/reference/taggedTemplateStringsTypeArgumentInferenceES6.js +++ b/tests/baselines/reference/taggedTemplateStringsTypeArgumentInferenceES6.js @@ -136,14 +136,14 @@ someGenerics5 `${null}${null}`; // Generic tag with multiple arguments of function types that each have parameters of the same generic type function someGenerics6(strs, a, b, c) { } -someGenerics6 `${(n) => { return n; }}${(n) => { return n; }}${(n) => { return n; }}`; -someGenerics6 `${(n) => { return n; }}${(n) => { return n; }}${(n) => { return n; }}`; +someGenerics6 `${n => { return n; }}${n => { return n; }}${n => { return n; }}`; +someGenerics6 `${n => { return n; }}${n => { return n; }}${n => { return n; }}`; someGenerics6 `${(n) => { return n; }}${(n) => { return n; }}${(n) => { return n; }}`; // Generic tag with multiple arguments of function types that each have parameters of different generic type function someGenerics7(strs, a, b, c) { } -someGenerics7 `${(n) => { return n; }}${(n) => { return n; }}${(n) => { return n; }}`; -someGenerics7 `${(n) => { return n; }}${(n) => { return n; }}${(n) => { return n; }}`; +someGenerics7 `${n => { return n; }}${n => { return n; }}${n => { return n; }}`; +someGenerics7 `${n => { return n; }}${n => { return n; }}${n => { return n; }}`; someGenerics7 `${(n) => { return n; }}${(n) => { return n; }}${(n) => { return n; }}`; // Generic tag with argument of generic function type function someGenerics8(strs, n) { diff --git a/tests/baselines/reference/templateStringInArrowFunctionES6.js b/tests/baselines/reference/templateStringInArrowFunctionES6.js index 1dc7b5c9fa1..11dd7a82fe3 100644 --- a/tests/baselines/reference/templateStringInArrowFunctionES6.js +++ b/tests/baselines/reference/templateStringInArrowFunctionES6.js @@ -2,4 +2,4 @@ var x = x => `abc${ x }def`; //// [templateStringInArrowFunctionES6.js] -var x = (x) => { return `abc${x}def`; }; +var x = x => { return `abc${x}def`; }; diff --git a/tests/baselines/reference/templateStringWithEmbeddedArrowFunctionES6.js b/tests/baselines/reference/templateStringWithEmbeddedArrowFunctionES6.js index 5d95a9a0079..3dd7e4c11e4 100644 --- a/tests/baselines/reference/templateStringWithEmbeddedArrowFunctionES6.js +++ b/tests/baselines/reference/templateStringWithEmbeddedArrowFunctionES6.js @@ -2,4 +2,4 @@ var x = `abc${ x => x }def`; //// [templateStringWithEmbeddedArrowFunctionES6.js] -var x = `abc${(x) => { return x; }}def`; +var x = `abc${x => { return x; }}def`; diff --git a/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIs.ts b/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIs.ts new file mode 100644 index 00000000000..1366fff90a1 --- /dev/null +++ b/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIs.ts @@ -0,0 +1,5 @@ +// @target:ES5 +var arrow1 = a => { }; +var arrow2 = (a) => { }; + +var arrow3 = (a, b) => { }; \ No newline at end of file diff --git a/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIsES6.ts b/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIsES6.ts new file mode 100644 index 00000000000..01331ededf9 --- /dev/null +++ b/tests/cases/conformance/es6/arrowFunction/emitArrowFunctionsAsIsES6.ts @@ -0,0 +1,5 @@ +// @target:ES6 +var arrow1 = a => { }; +var arrow2 = (a) => { }; + +var arrow3 = (a, b) => { }; \ No newline at end of file