From 6da4326a31c202fa32fd02dc4b5ffb7356b56105 Mon Sep 17 00:00:00 2001 From: iinicole Date: Mon, 10 Apr 2023 18:44:40 -0400 Subject: [PATCH 1/6] Change emitter to preserve newline in if statement --- src/compiler/emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d15e4de4be6e0..9f50ba77c19fc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4866,7 +4866,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitEmbeddedStatement(parent: Node, node: Statement) { - if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine) { + if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine || !preserveSourceNewlines) { writeSpace(); emit(node); } From 709493cff9e6041b0cf73475351b9ddb55aab3bd Mon Sep 17 00:00:00 2001 From: iinicole Date: Mon, 10 Apr 2023 23:54:57 -0400 Subject: [PATCH 2/6] temp fix for preserve newline behavior --- src/compiler/emitter.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9f50ba77c19fc..0a4fbec4b9f36 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -862,6 +862,7 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi inlineSources: compilerOptions.inlineSources, extendedDiagnostics: compilerOptions.extendedDiagnostics, writeBundleFileInfo: !!bundleBuildInfo, + preserveSourceNewlines: true, relativeToBuildInfo }; @@ -4866,20 +4867,27 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitEmbeddedStatement(parent: Node, node: Statement) { - if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine || !preserveSourceNewlines) { + const lines = getLeadingLineTerminatorCount(parent, node, ListFormat.None); + if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine || !lines) { writeSpace(); emit(node); } else { - writeLine(); - increaseIndent(); - if (isEmptyStatement(node)) { - pipelineEmit(EmitHint.EmbeddedStatement, node); + if (lines) { + writeLine(lines); + increaseIndent(); + if (isEmptyStatement(node)) { + pipelineEmit(EmitHint.EmbeddedStatement, node); + } + else { + emit(node); + } + decreaseIndent(); } else { + writeSpace(); emit(node); } - decreaseIndent(); } } From 426e93fb578f2efc278c14dea63af0bae0a4a57a Mon Sep 17 00:00:00 2001 From: iinicole Date: Tue, 11 Apr 2023 02:54:34 -0400 Subject: [PATCH 3/6] Create test case for preserve behavior --- tests/baselines/reference/preserveSpace.js | 47 ++++++++++++ .../baselines/reference/preserveSpace.symbols | 50 +++++++++++++ tests/baselines/reference/preserveSpace.types | 73 +++++++++++++++++++ tests/cases/conformance/preserveSpace.ts | 22 ++++++ 4 files changed, 192 insertions(+) create mode 100644 tests/baselines/reference/preserveSpace.js create mode 100644 tests/baselines/reference/preserveSpace.symbols create mode 100644 tests/baselines/reference/preserveSpace.types create mode 100644 tests/cases/conformance/preserveSpace.ts diff --git a/tests/baselines/reference/preserveSpace.js b/tests/baselines/reference/preserveSpace.js new file mode 100644 index 0000000000000..d91db1f84520c --- /dev/null +++ b/tests/baselines/reference/preserveSpace.js @@ -0,0 +1,47 @@ +//// [preserveSpace.ts] +function f() { + return [].filter(x => { + if (!x) return false; // testing comments + if (x) + return true; // testing comments + if (x) { + return false; // testing comments + } else { + console.log("here"); // testing comments + } + let i: number = 0; + while (i > 0) i = i - 1; + do console.log("here"); + while (false); + + try { + return true; + } catch (e) { + return false; + } + }); +} + +//// [preserveSpace.js] +function f() { + return [].filter(function (x) { + if (!x) return false; // testing comments + if (x) + return true; // testing comments + if (x) { + return false; // testing comments + } else { + console.log("here"); // testing comments + } + var i = 0; + while (i > 0) i = i - 1; + do console.log("here"); + while (false); + + try { + return true; + } catch (e) { + return false; + } + }); +} diff --git a/tests/baselines/reference/preserveSpace.symbols b/tests/baselines/reference/preserveSpace.symbols new file mode 100644 index 0000000000000..817d9b3a869fe --- /dev/null +++ b/tests/baselines/reference/preserveSpace.symbols @@ -0,0 +1,50 @@ +=== tests/cases/conformance/preserveSpace.ts === +function f() { +>f : Symbol(f, Decl(preserveSpace.ts, 0, 0)) + + return [].filter(x => { +>[].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) + + if (!x) return false; // testing comments +>x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) + + if (x) +>x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) + + return true; // testing comments + if (x) { +>x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) + + return false; // testing comments + } else { + console.log("here"); // testing comments +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } + let i: number = 0; +>i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) + + while (i > 0) i = i - 1; +>i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) +>i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) +>i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) + + do console.log("here"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + + while (false); + + try { + return true; + } catch (e) { +>e : Symbol(e, Decl(preserveSpace.ts, 17, 17)) + + return false; + } + }); +} diff --git a/tests/baselines/reference/preserveSpace.types b/tests/baselines/reference/preserveSpace.types new file mode 100644 index 0000000000000..38fa5e631d8e3 --- /dev/null +++ b/tests/baselines/reference/preserveSpace.types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/preserveSpace.ts === +function f() { +>f : () => any[] + + return [].filter(x => { +>[].filter(x => { if (!x) return false; // testing comments if (x) return true; // testing comments if (x) { return false; // testing comments } else { console.log("here"); // testing comments } let i: number = 0; while (i > 0) i = i - 1; do console.log("here"); while (false); try { return true; } catch (e) { return false; } }) : any[] +>[].filter : { (predicate: (value: any, index: number, array: any[]) => value is S, thisArg?: any): S[]; (predicate: (value: any, index: number, array: any[]) => unknown, thisArg?: any): any[]; } +>[] : undefined[] +>filter : { (predicate: (value: any, index: number, array: any[]) => value is S, thisArg?: any): S[]; (predicate: (value: any, index: number, array: any[]) => unknown, thisArg?: any): any[]; } +>x => { if (!x) return false; // testing comments if (x) return true; // testing comments if (x) { return false; // testing comments } else { console.log("here"); // testing comments } let i: number = 0; while (i > 0) i = i - 1; do console.log("here"); while (false); try { return true; } catch (e) { return false; } } : (x: any) => boolean +>x : any + + if (!x) return false; // testing comments +>!x : boolean +>x : any +>false : false + + if (x) +>x : any + + return true; // testing comments +>true : true + + if (x) { +>x : any + + return false; // testing comments +>false : false + + } else { + console.log("here"); // testing comments +>console.log("here") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"here" : "here" + } + let i: number = 0; +>i : number +>0 : 0 + + while (i > 0) i = i - 1; +>i > 0 : boolean +>i : number +>0 : 0 +>i = i - 1 : number +>i : number +>i - 1 : number +>i : number +>1 : 1 + + do console.log("here"); +>console.log("here") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"here" : "here" + + while (false); +>false : false + + try { + return true; +>true : true + + } catch (e) { +>e : any + + return false; +>false : false + } + }); +} diff --git a/tests/cases/conformance/preserveSpace.ts b/tests/cases/conformance/preserveSpace.ts new file mode 100644 index 0000000000000..dd7aaf34b12c7 --- /dev/null +++ b/tests/cases/conformance/preserveSpace.ts @@ -0,0 +1,22 @@ +function f() { + return [].filter(x => { + if (!x) return false; // testing comments + if (x) + return true; // testing comments + if (x) { + return false; // testing comments + } else { + console.log("here"); // testing comments + } + let i: number = 0; + while (i > 0) i = i - 1; + do console.log("here"); + while (false); + + try { + return true; + } catch (e) { + return false; + } + }); +} \ No newline at end of file From 53a40b90b3e5eb9fc7c7161748f96a55a6067d11 Mon Sep 17 00:00:00 2001 From: iinicole Date: Tue, 11 Apr 2023 22:47:30 -0400 Subject: [PATCH 4/6] change emitter behavior --- src/compiler/emitter.ts | 19 ++--- tests/baselines/reference/preserveSpace.js | 47 ------------ .../baselines/reference/preserveSpace.symbols | 50 ------------- tests/baselines/reference/preserveSpace.types | 73 ------------------- tests/cases/conformance/preserveSpace.ts | 22 ------ 5 files changed, 6 insertions(+), 205 deletions(-) delete mode 100644 tests/baselines/reference/preserveSpace.js delete mode 100644 tests/baselines/reference/preserveSpace.symbols delete mode 100644 tests/baselines/reference/preserveSpace.types delete mode 100644 tests/cases/conformance/preserveSpace.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0a4fbec4b9f36..f382ab5188fda 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -862,7 +862,6 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi inlineSources: compilerOptions.inlineSources, extendedDiagnostics: compilerOptions.extendedDiagnostics, writeBundleFileInfo: !!bundleBuildInfo, - preserveSourceNewlines: true, relativeToBuildInfo }; @@ -4868,26 +4867,20 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitEmbeddedStatement(parent: Node, node: Statement) { const lines = getLeadingLineTerminatorCount(parent, node, ListFormat.None); - if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine || !lines) { + if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine || (preserveSourceNewlines && !lines)) { writeSpace(); emit(node); } else { - if (lines) { - writeLine(lines); - increaseIndent(); - if (isEmptyStatement(node)) { - pipelineEmit(EmitHint.EmbeddedStatement, node); - } - else { - emit(node); - } - decreaseIndent(); + writeLine(); + increaseIndent(); + if (isEmptyStatement(node)) { + pipelineEmit(EmitHint.EmbeddedStatement, node); } else { - writeSpace(); emit(node); } + decreaseIndent(); } } diff --git a/tests/baselines/reference/preserveSpace.js b/tests/baselines/reference/preserveSpace.js deleted file mode 100644 index d91db1f84520c..0000000000000 --- a/tests/baselines/reference/preserveSpace.js +++ /dev/null @@ -1,47 +0,0 @@ -//// [preserveSpace.ts] -function f() { - return [].filter(x => { - if (!x) return false; // testing comments - if (x) - return true; // testing comments - if (x) { - return false; // testing comments - } else { - console.log("here"); // testing comments - } - let i: number = 0; - while (i > 0) i = i - 1; - do console.log("here"); - while (false); - - try { - return true; - } catch (e) { - return false; - } - }); -} - -//// [preserveSpace.js] -function f() { - return [].filter(function (x) { - if (!x) return false; // testing comments - if (x) - return true; // testing comments - if (x) { - return false; // testing comments - } else { - console.log("here"); // testing comments - } - var i = 0; - while (i > 0) i = i - 1; - do console.log("here"); - while (false); - - try { - return true; - } catch (e) { - return false; - } - }); -} diff --git a/tests/baselines/reference/preserveSpace.symbols b/tests/baselines/reference/preserveSpace.symbols deleted file mode 100644 index 817d9b3a869fe..0000000000000 --- a/tests/baselines/reference/preserveSpace.symbols +++ /dev/null @@ -1,50 +0,0 @@ -=== tests/cases/conformance/preserveSpace.ts === -function f() { ->f : Symbol(f, Decl(preserveSpace.ts, 0, 0)) - - return [].filter(x => { ->[].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) - - if (!x) return false; // testing comments ->x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) - - if (x) ->x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) - - return true; // testing comments - if (x) { ->x : Symbol(x, Decl(preserveSpace.ts, 1, 19)) - - return false; // testing comments - } else { - console.log("here"); // testing comments ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) - } - let i: number = 0; ->i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) - - while (i > 0) i = i - 1; ->i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) ->i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) ->i : Symbol(i, Decl(preserveSpace.ts, 10, 11)) - - do console.log("here"); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) - - while (false); - - try { - return true; - } catch (e) { ->e : Symbol(e, Decl(preserveSpace.ts, 17, 17)) - - return false; - } - }); -} diff --git a/tests/baselines/reference/preserveSpace.types b/tests/baselines/reference/preserveSpace.types deleted file mode 100644 index 38fa5e631d8e3..0000000000000 --- a/tests/baselines/reference/preserveSpace.types +++ /dev/null @@ -1,73 +0,0 @@ -=== tests/cases/conformance/preserveSpace.ts === -function f() { ->f : () => any[] - - return [].filter(x => { ->[].filter(x => { if (!x) return false; // testing comments if (x) return true; // testing comments if (x) { return false; // testing comments } else { console.log("here"); // testing comments } let i: number = 0; while (i > 0) i = i - 1; do console.log("here"); while (false); try { return true; } catch (e) { return false; } }) : any[] ->[].filter : { (predicate: (value: any, index: number, array: any[]) => value is S, thisArg?: any): S[]; (predicate: (value: any, index: number, array: any[]) => unknown, thisArg?: any): any[]; } ->[] : undefined[] ->filter : { (predicate: (value: any, index: number, array: any[]) => value is S, thisArg?: any): S[]; (predicate: (value: any, index: number, array: any[]) => unknown, thisArg?: any): any[]; } ->x => { if (!x) return false; // testing comments if (x) return true; // testing comments if (x) { return false; // testing comments } else { console.log("here"); // testing comments } let i: number = 0; while (i > 0) i = i - 1; do console.log("here"); while (false); try { return true; } catch (e) { return false; } } : (x: any) => boolean ->x : any - - if (!x) return false; // testing comments ->!x : boolean ->x : any ->false : false - - if (x) ->x : any - - return true; // testing comments ->true : true - - if (x) { ->x : any - - return false; // testing comments ->false : false - - } else { - console.log("here"); // testing comments ->console.log("here") : void ->console.log : (...data: any[]) => void ->console : Console ->log : (...data: any[]) => void ->"here" : "here" - } - let i: number = 0; ->i : number ->0 : 0 - - while (i > 0) i = i - 1; ->i > 0 : boolean ->i : number ->0 : 0 ->i = i - 1 : number ->i : number ->i - 1 : number ->i : number ->1 : 1 - - do console.log("here"); ->console.log("here") : void ->console.log : (...data: any[]) => void ->console : Console ->log : (...data: any[]) => void ->"here" : "here" - - while (false); ->false : false - - try { - return true; ->true : true - - } catch (e) { ->e : any - - return false; ->false : false - } - }); -} diff --git a/tests/cases/conformance/preserveSpace.ts b/tests/cases/conformance/preserveSpace.ts deleted file mode 100644 index dd7aaf34b12c7..0000000000000 --- a/tests/cases/conformance/preserveSpace.ts +++ /dev/null @@ -1,22 +0,0 @@ -function f() { - return [].filter(x => { - if (!x) return false; // testing comments - if (x) - return true; // testing comments - if (x) { - return false; // testing comments - } else { - console.log("here"); // testing comments - } - let i: number = 0; - while (i > 0) i = i - 1; - do console.log("here"); - while (false); - - try { - return true; - } catch (e) { - return false; - } - }); -} \ No newline at end of file From 4d6ad11a86cc7d2fc7d72f3d21d5d1dab41fc604 Mon Sep 17 00:00:00 2001 From: iinicole Date: Tue, 11 Apr 2023 22:53:09 -0400 Subject: [PATCH 5/6] Create preserveSpace.ts --- tests/cases/fourslash/preserveSpace.ts | 84 ++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/cases/fourslash/preserveSpace.ts diff --git a/tests/cases/fourslash/preserveSpace.ts b/tests/cases/fourslash/preserveSpace.ts new file mode 100644 index 0000000000000..f3d456176e272 --- /dev/null +++ b/tests/cases/fourslash/preserveSpace.ts @@ -0,0 +1,84 @@ +/// + +////function foo() { +//// /*1*/if (true) console.log(1); +//// else console.log(1); +//// if (true) +//// console.log(1); +//// else +//// console.log(1); +//// +//// do console.log(1); +//// while (false); +//// do +//// console.log(1); +//// while (false); +//// +//// while (true) console.log(1); +//// while (true) +//// console.log(1); +//// +//// for (let i = 1; i < 4; i++) console.log(1); // 1,2,3 +//// for (let i = 1; i < 4; i++) +//// console.log(1); // 1,2,3 +//// +//// for (let i in [1, 2, 3]) console.log(1); +//// for (let i in [1, 2, 3]) +//// console.log(1); +//// +//// for (let i of [1, 2, 3]) console.log(1); +//// for (let i of [1, 2, 3]) +//// console.log(1); +//// +//// with ([1, 2, 3]) console.log(toString()); +//// with ([1, 2, 3]) +//// console.log(toString());/*2*/ +////} + +goTo.select("1", "2"); +edit.applyRefactor({ + refactorName: "Extract Symbol", + actionName: "function_scope_1", + actionDescription: "Extract to function in global scope", + newContent: +`function foo() { + /*RENAME*/newFunction(); +} + +function newFunction() { + if (true) console.log(1); + else console.log(1); + if (true) + console.log(1); + + else + console.log(1); + + do console.log(1); + while (false); + do + console.log(1); + while (false); + + while (true) console.log(1); + while (true) + console.log(1); + + for (let i = 1; i < 4; i++) console.log(1); // 1,2,3 + for (let i = 1; i < 4; i++) + console.log(1); // 1,2,3 + + for (let i in [1, 2, 3]) console.log(1); + for (let i in [1, 2, 3]) + console.log(1); + + for (let i of [1, 2, 3]) console.log(1); + for (let i of [1, 2, 3]) + console.log(1); + + with ([1, 2, 3]) console.log(toString()); + with ([1, 2, 3]) + console.log(toString()); +} +` +}); From 8e2143109ead3412e53351619222e7cae1770d63 Mon Sep 17 00:00:00 2001 From: Nicole <66326869+iinicole@users.noreply.github.com> Date: Tue, 18 Apr 2023 12:33:16 -0400 Subject: [PATCH 6/6] short circuit getLineTerminatorCount Co-authored-by: Andrew Branch --- src/compiler/emitter.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f382ab5188fda..d16680f7e1d24 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4866,8 +4866,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitEmbeddedStatement(parent: Node, node: Statement) { - const lines = getLeadingLineTerminatorCount(parent, node, ListFormat.None); - if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine || (preserveSourceNewlines && !lines)) { + if (isBlock(node) || + getEmitFlags(parent) & EmitFlags.SingleLine || + preserveSourceNewlines && !getLeadingLineTerminatorCount(parent, node, ListFormat.None) + ) { writeSpace(); emit(node); }