diff --git a/src/harness/unittests/extractConstants.ts b/src/harness/unittests/extractConstants.ts index e2c64afb526..d37f9b2036c 100644 --- a/src/harness/unittests/extractConstants.ts +++ b/src/harness/unittests/extractConstants.ts @@ -40,7 +40,7 @@ namespace ts { } }`); - testExtractConstant("extractConstant_ClassInsertionPosition", + testExtractConstant("extractConstant_ClassInsertionPosition1", `class C { a = 1; b = 2; @@ -51,6 +51,28 @@ namespace ts { } }`); + testExtractConstant("extractConstant_ClassInsertionPosition2", + `class C { + a = 1; + M1() { } + b = 2; + M2() { } + M3() { + let x = [#|1|]; + } +}`); + + testExtractConstant("extractConstant_ClassInsertionPosition3", + `class C { + M1() { } + a = 1; + b = 2; + M2() { } + M3() { + let x = [#|1|]; + } +}`); + testExtractConstant("extractConstant_Parameters", `function F() { let w = 1; @@ -62,7 +84,7 @@ namespace ts { let x = [#|t + 1|]; }`); -// TODO (acasey): handle repeated substitution +// TODO (18857): handle repeated substitution // testExtractConstant("extractConstant_RepeatedSubstitution", // `namespace X { // export const j = 10; @@ -75,6 +97,121 @@ namespace ts { let x = [#|i + 1|]; } }`); + + testExtractConstant("extractConstant_VariableList_const", + `const a = 1, b = [#|a + 1|];`); + + // NOTE: this test isn't normative - it just documents our sub-optimal behavior. + testExtractConstant("extractConstant_VariableList_let", + `let a = 1, b = [#|a + 1|];`); + + // NOTE: this test isn't normative - it just documents our sub-optimal behavior. + testExtractConstant("extractConstant_VariableList_MultipleLines", + `const /*About A*/a = 1, + /*About B*/b = [#|a + 1|];`); + + // NOTE: this test isn't normative - it just documents our sub-optimal behavior. + // `i` doesn't bind in the target scope (file-level), so the extraction is disallowed. + // TODO (17098): should probably allow extraction into the same scope + testExtractConstantFailed("extractConstant_BlockScopeMismatch", ` +for (let i = 0; i < 10; i++) { + for (let j = 0; j < 10; j++) { + const x = [#|i + 1|]; + } +} + `); + + testExtractConstant("extractConstant_StatementInsertionPosition1", ` +const i = 0; +for (let j = 0; j < 10; j++) { + const x = [#|i + 1|]; +} + `); + + testExtractConstant("extractConstant_StatementInsertionPosition2", ` +const i = 0; +function F() { + for (let j = 0; j < 10; j++) { + const x = [#|i + 1|]; + } +} + `); + + testExtractConstant("extractConstant_StatementInsertionPosition3", ` +for (let j = 0; j < 10; j++) { + const x = [#|2 + 1|]; +} + `); + + testExtractConstant("extractConstant_StatementInsertionPosition4", ` +function F() { + for (let j = 0; j < 10; j++) { + const x = [#|2 + 1|]; + } +} + `); + + testExtractConstant("extractConstant_StatementInsertionPosition5", ` +function F0() { + function F1() { + function F2(x = [#|2 + 1|]) { + } + } +} + `); + + testExtractConstant("extractConstant_StatementInsertionPosition6", ` +class C { + x = [#|2 + 1|]; +} + `); + + testExtractConstant("extractConstant_StatementInsertionPosition7", ` +const i = 0; +class C { + M() { + for (let j = 0; j < 10; j++) { + x = [#|i + 1|]; + } + } +} + `); + + testExtractConstant("extractConstant_TripleSlash", ` +/// + +const x = [#|2 + 1|]; + `); + + testExtractConstant("extractConstant_PinnedComment", ` +/*! Copyright */ + +const x = [#|2 + 1|]; + `); + + testExtractConstant("extractConstant_Directive", ` +"strict"; + +const x = [#|2 + 1|]; + `); + + testExtractConstant("extractConstant_MultipleHeaders", ` +/*! Copyright */ + +/// + +"strict"; + +const x = [#|2 + 1|]; + `); + + // NOTE: this test isn't normative - it just documents our sub-optimal behavior. + testExtractConstant("extractConstant_PinnedCommentAndDocComment", ` +/*! Copyright */ + +/* About x */ +const x = [#|2 + 1|]; + `); }); function testExtractConstant(caption: string, text: string) { diff --git a/src/harness/unittests/extractFunctions.ts b/src/harness/unittests/extractFunctions.ts index 522ea7b1293..c4cbadacdc3 100644 --- a/src/harness/unittests/extractFunctions.ts +++ b/src/harness/unittests/extractFunctions.ts @@ -365,7 +365,7 @@ function parsePrimaryExpression(): any { [#|function G() { }|] }`); -// TODO (acasey): handle repeated substitution +// TODO (18857): handle repeated substitution // testExtractFunction("extractFunction_RepeatedSubstitution", // `namespace X { // export const j = 10; diff --git a/src/harness/unittests/extractTestHelpers.ts b/src/harness/unittests/extractTestHelpers.ts index ea1cccd32ea..0d739919e1f 100644 --- a/src/harness/unittests/extractTestHelpers.ts +++ b/src/harness/unittests/extractTestHelpers.ts @@ -113,7 +113,7 @@ namespace ts { if (hasSyntacticDiagnostics(program)) { // Don't bother generating JS baselines for inputs that aren't valid JS. - assert.equal(Extension.Js, extension); + assert.equal(Extension.Js, extension, "Syntactic diagnostics found in non-JS file"); return; } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 375acb7e585..ad4da2c61fc 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -890,33 +890,56 @@ namespace ts.refactor.extractSymbol { createIdentifier(localNameText)); // Declare - const minInsertionPos = node.end; - const nodeToInsertBefore = getNodeToInsertConstantBefore(minInsertionPos, scope); + const maxInsertionPos = node.pos; + const nodeToInsertBefore = getNodeToInsertPropertyBefore(maxInsertionPos, scope); changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, { suffix: context.newLineCharacter + context.newLineCharacter }); // Consume changeTracker.replaceNodeWithNodes(context.file, node, [localReference], { nodeSeparator: context.newLineCharacter }); } else { - const newVariable = createVariableStatement( - /*modifiers*/ undefined, - createVariableDeclarationList( - [createVariableDeclaration(localNameText, variableType, initializer)], - NodeFlags.Const)); + const newVariableDeclaration = createVariableDeclaration(localNameText, variableType, initializer); - // If the parent is an expression statement, replace the statement with the declaration - if (node.parent.kind === SyntaxKind.ExpressionStatement) { - changeTracker.replaceNodeWithNodes(context.file, node.parent, [newVariable], { nodeSeparator: context.newLineCharacter }); - } - else { + // If the node is part of an initializer in a list of variable declarations, insert a new + // variable declaration into the list (in case it depends on earlier ones). + // CONSIDER: If the declaration list isn't const, we might want to split it into multiple + // lists so that the newly extracted one can be const. + const oldVariableDeclaration = getContainingVariableDeclarationIfInList(node, scope); + if (oldVariableDeclaration) { // Declare - const minInsertionPos = node.end; - const nodeToInsertBefore = getNodeToInsertConstantBefore(minInsertionPos, scope); - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, { suffix: context.newLineCharacter + context.newLineCharacter }); + // CONSIDER: could detect that each is on a separate line + changeTracker.insertNodeAt(context.file, oldVariableDeclaration.getStart(), newVariableDeclaration, { suffix: ", " }); // Consume const localReference = createIdentifier(localNameText); - changeTracker.replaceNodeWithNodes(context.file, node, [localReference], { nodeSeparator: context.newLineCharacter }); + changeTracker.replaceRange(context.file, { pos: node.getStart(), end: node.end }, localReference); + } + else if (node.parent.kind === SyntaxKind.ExpressionStatement) { + // If the parent is an expression statement, replace the statement with the declaration. + const newVariableStatement = createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); + changeTracker.replaceNodeWithNodes(context.file, node.parent, [newVariableStatement], { nodeSeparator: context.newLineCharacter }); + } + else { + const newVariableStatement = createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); + + // Declare + const nodeToInsertBefore = getNodeToInsertConstantBefore(node, scope); + if (nodeToInsertBefore.pos === 0) { + // If we're at the beginning of the file, we need to take care not to insert before header comments + // (e.g. copyright, triple-slash references). + changeTracker.insertNodeAt(context.file, nodeToInsertBefore.getStart(), newVariableStatement, { suffix: context.newLineCharacter + context.newLineCharacter }); + } + else { + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, { suffix: context.newLineCharacter + context.newLineCharacter }); + } + + // Consume + const localReference = createIdentifier(localNameText); + changeTracker.replaceRange(context.file, { pos: node.getStart(), end: node.end }, localReference); } } @@ -927,6 +950,22 @@ namespace ts.refactor.extractSymbol { return { renameFilename, renameLocation, edits }; } + function getContainingVariableDeclarationIfInList(node: Node, scope: Scope) { + let prevNode = undefined; + while (node !== undefined && node !== scope) { + if (isVariableDeclaration(node) && + node.initializer === prevNode && + isVariableDeclarationList(node.parent) && + node.parent.declarations.length > 1) { + + return node; + } + + prevNode = node; + node = node.parent; + } + } + /** * @return The index of the (only) reference to the extracted symbol. We want the cursor * to be on the reference, rather than the declaration, because it's closer to where the @@ -1109,26 +1148,61 @@ namespace ts.refactor.extractSymbol { child.pos >= minPos && isFunctionLikeDeclaration(child) && !isConstructorDeclaration(child)); } - // TODO (acasey): need to dig into nested statements - // TODO (acasey): don't insert before pinned comments, directives, or triple-slash references - function getNodeToInsertConstantBefore(maxPos: number, scope: Scope): Node { - const children = getStatementsOrClassElements(scope); - Debug.assert(children.length > 0); // There must be at least one child, since we extracted from one. + function getNodeToInsertPropertyBefore(maxPos: number, scope: ClassLikeDeclaration): Node { + const members = scope.members; + Debug.assert(members.length > 0); // There must be at least one child, since we extracted from one. - const isClassLikeScope = isClassLike(scope); - let prevChild: Statement | ClassElement | undefined = undefined; - for (const child of children) { - if (child.pos >= maxPos) { - break; + let prevMember: ClassElement | undefined = undefined; + let allProperties = true; + for (const member of members) { + if (member.pos > maxPos) { + return prevMember || members[0]; } - prevChild = child; - if (isClassLikeScope && !isPropertyDeclaration(child)) { - break; + if (allProperties && !isPropertyDeclaration(member)) { + // If it is non-vacuously true that all preceding members are properties, + // insert before the current member (i.e. at the end of the list of properties). + if (prevMember !== undefined) { + return member; + } + + allProperties = false; + } + prevMember = member; + } + + Debug.assert(prevMember !== undefined); // If the loop didn't return, then it did set prevMember. + return prevMember; + } + + function getNodeToInsertConstantBefore(node: Node, scope: Scope): Node { + Debug.assert(!isClassLike(scope)); + + let prevScope: Scope | undefined = undefined; + for (let curr = node; curr !== scope; curr = curr.parent) { + if (isScope(curr)) { + prevScope = curr; } } - Debug.assert(prevChild !== undefined); - return prevChild; + for (let curr = (prevScope || node).parent; ; curr = curr.parent) { + if (isBlockLike(curr)) { + let prevStatement = undefined; + for (const statement of curr.statements) { + if (statement.pos > node.pos) { + break; + } + prevStatement = statement; + } + // There must be at least one statement since we started in one. + Debug.assert(prevStatement !== undefined); + return prevStatement; + } + + if (curr === scope) { + Debug.fail("Didn't encounter a block-like before encountering scope"); + break; + } + } } function getPropertyAssignmentsForWrites(writes: ReadonlyArray): ShorthandPropertyAssignment[] { diff --git a/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.js b/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.js index 25609a3a801..b934af59550 100644 --- a/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.js +++ b/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.js @@ -5,10 +5,10 @@ for (let i = 0; i < 10; i++) { } } // ==SCOPE::Extract to constant in global scope== -const newLocal = 1; - for (let i = 0; i < 10; i++) { for (let j = 0; j < 10; j++) { + const newLocal = 1; + let x = /*RENAME*/newLocal; } } \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.ts b/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.ts index 25609a3a801..b934af59550 100644 --- a/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.ts +++ b/tests/baselines/reference/extractConstant/extractConstant_BlockScopes_NoDependencies.ts @@ -5,10 +5,10 @@ for (let i = 0; i < 10; i++) { } } // ==SCOPE::Extract to constant in global scope== -const newLocal = 1; - for (let i = 0; i < 10; i++) { for (let j = 0; j < 10; j++) { + const newLocal = 1; + let x = /*RENAME*/newLocal; } } \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition.js b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition1.js similarity index 100% rename from tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition.js rename to tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition1.js diff --git a/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition.ts b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition1.ts similarity index 100% rename from tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition.ts rename to tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition1.ts diff --git a/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition2.js b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition2.js new file mode 100644 index 00000000000..137fc5ff0bb --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition2.js @@ -0,0 +1,34 @@ +// ==ORIGINAL== +class C { + a = 1; + M1() { } + b = 2; + M2() { } + M3() { + let x = 1; + } +} +// ==SCOPE::Extract to constant in method 'M3== +class C { + a = 1; + M1() { } + b = 2; + M2() { } + M3() { + const newLocal = 1; + + let x = /*RENAME*/newLocal; + } +} +// ==SCOPE::Extract to constant in global scope== +const newLocal = 1; + +class C { + a = 1; + M1() { } + b = 2; + M2() { } + M3() { + let x = /*RENAME*/newLocal; + } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition2.ts b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition2.ts new file mode 100644 index 00000000000..5bd239c0e63 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition2.ts @@ -0,0 +1,46 @@ +// ==ORIGINAL== +class C { + a = 1; + M1() { } + b = 2; + M2() { } + M3() { + let x = 1; + } +} +// ==SCOPE::Extract to constant in method 'M3== +class C { + a = 1; + M1() { } + b = 2; + M2() { } + M3() { + const newLocal = 1; + + let x = /*RENAME*/newLocal; + } +} +// ==SCOPE::Extract to readonly field in class 'C'== +class C { + a = 1; + private readonly newProperty = 1; + + M1() { } + b = 2; + M2() { } + M3() { + let x = this./*RENAME*/newProperty; + } +} +// ==SCOPE::Extract to constant in global scope== +const newLocal = 1; + +class C { + a = 1; + M1() { } + b = 2; + M2() { } + M3() { + let x = /*RENAME*/newLocal; + } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition3.js b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition3.js new file mode 100644 index 00000000000..1679e46d8d5 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition3.js @@ -0,0 +1,34 @@ +// ==ORIGINAL== +class C { + M1() { } + a = 1; + b = 2; + M2() { } + M3() { + let x = 1; + } +} +// ==SCOPE::Extract to constant in method 'M3== +class C { + M1() { } + a = 1; + b = 2; + M2() { } + M3() { + const newLocal = 1; + + let x = /*RENAME*/newLocal; + } +} +// ==SCOPE::Extract to constant in global scope== +const newLocal = 1; + +class C { + M1() { } + a = 1; + b = 2; + M2() { } + M3() { + let x = /*RENAME*/newLocal; + } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition3.ts b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition3.ts new file mode 100644 index 00000000000..4cc44565fa0 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_ClassInsertionPosition3.ts @@ -0,0 +1,46 @@ +// ==ORIGINAL== +class C { + M1() { } + a = 1; + b = 2; + M2() { } + M3() { + let x = 1; + } +} +// ==SCOPE::Extract to constant in method 'M3== +class C { + M1() { } + a = 1; + b = 2; + M2() { } + M3() { + const newLocal = 1; + + let x = /*RENAME*/newLocal; + } +} +// ==SCOPE::Extract to readonly field in class 'C'== +class C { + M1() { } + a = 1; + b = 2; + M2() { } + private readonly newProperty = 1; + + M3() { + let x = this./*RENAME*/newProperty; + } +} +// ==SCOPE::Extract to constant in global scope== +const newLocal = 1; + +class C { + M1() { } + a = 1; + b = 2; + M2() { } + M3() { + let x = /*RENAME*/newLocal; + } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_Directive.js b/tests/baselines/reference/extractConstant/extractConstant_Directive.js new file mode 100644 index 00000000000..5ba48e27de9 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_Directive.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +"strict"; + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +"strict"; + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_Directive.ts b/tests/baselines/reference/extractConstant/extractConstant_Directive.ts new file mode 100644 index 00000000000..5ba48e27de9 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_Directive.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +"strict"; + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +"strict"; + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_MultipleHeaders.js b/tests/baselines/reference/extractConstant/extractConstant_MultipleHeaders.js new file mode 100644 index 00000000000..d2d0f14c01e --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_MultipleHeaders.js @@ -0,0 +1,22 @@ +// ==ORIGINAL== + +/*! Copyright */ + +/// + +"strict"; + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/*! Copyright */ + +/// + +"strict"; + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_MultipleHeaders.ts b/tests/baselines/reference/extractConstant/extractConstant_MultipleHeaders.ts new file mode 100644 index 00000000000..d2d0f14c01e --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_MultipleHeaders.ts @@ -0,0 +1,22 @@ +// ==ORIGINAL== + +/*! Copyright */ + +/// + +"strict"; + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/*! Copyright */ + +/// + +"strict"; + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_PinnedComment.js b/tests/baselines/reference/extractConstant/extractConstant_PinnedComment.js new file mode 100644 index 00000000000..a372457fc48 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_PinnedComment.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*! Copyright */ + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/*! Copyright */ + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_PinnedComment.ts b/tests/baselines/reference/extractConstant/extractConstant_PinnedComment.ts new file mode 100644 index 00000000000..a372457fc48 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_PinnedComment.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*! Copyright */ + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/*! Copyright */ + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_PinnedCommentAndDocComment.js b/tests/baselines/reference/extractConstant/extractConstant_PinnedCommentAndDocComment.js new file mode 100644 index 00000000000..763473d49cd --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_PinnedCommentAndDocComment.js @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +/*! Copyright */ + +/* About x */ +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/*! Copyright */ + +/* About x */ +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_PinnedCommentAndDocComment.ts b/tests/baselines/reference/extractConstant/extractConstant_PinnedCommentAndDocComment.ts new file mode 100644 index 00000000000..763473d49cd --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_PinnedCommentAndDocComment.ts @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +/*! Copyright */ + +/* About x */ +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/*! Copyright */ + +/* About x */ +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition1.js b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition1.js new file mode 100644 index 00000000000..f881a021232 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition1.js @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +const i = 0; +for (let j = 0; j < 10; j++) { + const x = i + 1; +} + +// ==SCOPE::Extract to constant in global scope== + +const i = 0; +for (let j = 0; j < 10; j++) { + const newLocal = i + 1; + + const x = /*RENAME*/newLocal; +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition1.ts b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition1.ts new file mode 100644 index 00000000000..f881a021232 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition1.ts @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +const i = 0; +for (let j = 0; j < 10; j++) { + const x = i + 1; +} + +// ==SCOPE::Extract to constant in global scope== + +const i = 0; +for (let j = 0; j < 10; j++) { + const newLocal = i + 1; + + const x = /*RENAME*/newLocal; +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition2.js b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition2.js new file mode 100644 index 00000000000..7ffd89161a2 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition2.js @@ -0,0 +1,31 @@ +// ==ORIGINAL== + +const i = 0; +function F() { + for (let j = 0; j < 10; j++) { + const x = i + 1; + } +} + +// ==SCOPE::Extract to constant in function 'F'== + +const i = 0; +function F() { + for (let j = 0; j < 10; j++) { + const newLocal = i + 1; + + const x = /*RENAME*/newLocal; + } +} + +// ==SCOPE::Extract to constant in global scope== + +const i = 0; +const newLocal = i + 1; + +function F() { + for (let j = 0; j < 10; j++) { + const x = /*RENAME*/newLocal; + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition2.ts b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition2.ts new file mode 100644 index 00000000000..7ffd89161a2 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition2.ts @@ -0,0 +1,31 @@ +// ==ORIGINAL== + +const i = 0; +function F() { + for (let j = 0; j < 10; j++) { + const x = i + 1; + } +} + +// ==SCOPE::Extract to constant in function 'F'== + +const i = 0; +function F() { + for (let j = 0; j < 10; j++) { + const newLocal = i + 1; + + const x = /*RENAME*/newLocal; + } +} + +// ==SCOPE::Extract to constant in global scope== + +const i = 0; +const newLocal = i + 1; + +function F() { + for (let j = 0; j < 10; j++) { + const x = /*RENAME*/newLocal; + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition3.js b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition3.js new file mode 100644 index 00000000000..6ba0b2dfaae --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition3.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +for (let j = 0; j < 10; j++) { + const x = 2 + 1; +} + +// ==SCOPE::Extract to constant in global scope== + +for (let j = 0; j < 10; j++) { + const newLocal = 2 + 1; + + const x = /*RENAME*/newLocal; +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition3.ts b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition3.ts new file mode 100644 index 00000000000..6ba0b2dfaae --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition3.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +for (let j = 0; j < 10; j++) { + const x = 2 + 1; +} + +// ==SCOPE::Extract to constant in global scope== + +for (let j = 0; j < 10; j++) { + const newLocal = 2 + 1; + + const x = /*RENAME*/newLocal; +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition4.js b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition4.js new file mode 100644 index 00000000000..19fd25382e8 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition4.js @@ -0,0 +1,28 @@ +// ==ORIGINAL== + +function F() { + for (let j = 0; j < 10; j++) { + const x = 2 + 1; + } +} + +// ==SCOPE::Extract to constant in function 'F'== + +function F() { + for (let j = 0; j < 10; j++) { + const newLocal = 2 + 1; + + const x = /*RENAME*/newLocal; + } +} + +// ==SCOPE::Extract to constant in global scope== + +const newLocal = 2 + 1; + +function F() { + for (let j = 0; j < 10; j++) { + const x = /*RENAME*/newLocal; + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition4.ts b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition4.ts new file mode 100644 index 00000000000..19fd25382e8 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition4.ts @@ -0,0 +1,28 @@ +// ==ORIGINAL== + +function F() { + for (let j = 0; j < 10; j++) { + const x = 2 + 1; + } +} + +// ==SCOPE::Extract to constant in function 'F'== + +function F() { + for (let j = 0; j < 10; j++) { + const newLocal = 2 + 1; + + const x = /*RENAME*/newLocal; + } +} + +// ==SCOPE::Extract to constant in global scope== + +const newLocal = 2 + 1; + +function F() { + for (let j = 0; j < 10; j++) { + const x = /*RENAME*/newLocal; + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition5.js b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition5.js new file mode 100644 index 00000000000..a19bd6afa28 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition5.js @@ -0,0 +1,42 @@ +// ==ORIGINAL== + +function F0() { + function F1() { + function F2(x = 2 + 1) { + } + } +} + +// ==SCOPE::Extract to constant in function 'F1'== + +function F0() { + function F1() { + const newLocal = 2 + 1; + + function F2(x = /*RENAME*/newLocal) { + } + } +} + +// ==SCOPE::Extract to constant in function 'F0'== + +function F0() { + const newLocal = 2 + 1; + + function F1() { + function F2(x = /*RENAME*/newLocal) { + } + } +} + +// ==SCOPE::Extract to constant in global scope== + +const newLocal = 2 + 1; + +function F0() { + function F1() { + function F2(x = /*RENAME*/newLocal) { + } + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition5.ts b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition5.ts new file mode 100644 index 00000000000..a19bd6afa28 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition5.ts @@ -0,0 +1,42 @@ +// ==ORIGINAL== + +function F0() { + function F1() { + function F2(x = 2 + 1) { + } + } +} + +// ==SCOPE::Extract to constant in function 'F1'== + +function F0() { + function F1() { + const newLocal = 2 + 1; + + function F2(x = /*RENAME*/newLocal) { + } + } +} + +// ==SCOPE::Extract to constant in function 'F0'== + +function F0() { + const newLocal = 2 + 1; + + function F1() { + function F2(x = /*RENAME*/newLocal) { + } + } +} + +// ==SCOPE::Extract to constant in global scope== + +const newLocal = 2 + 1; + +function F0() { + function F1() { + function F2(x = /*RENAME*/newLocal) { + } + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition6.js b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition6.js new file mode 100644 index 00000000000..06a665140d9 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition6.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +class C { + x = 2 + 1; +} + +// ==SCOPE::Extract to constant in global scope== + +const newLocal = 2 + 1; + +class C { + x = /*RENAME*/newLocal; +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition6.ts b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition6.ts new file mode 100644 index 00000000000..a34b0a9ecc3 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition6.ts @@ -0,0 +1,22 @@ +// ==ORIGINAL== + +class C { + x = 2 + 1; +} + +// ==SCOPE::Extract to readonly field in class 'C'== + +class C { + private readonly newProperty = 2 + 1; + + x = this./*RENAME*/newProperty; +} + +// ==SCOPE::Extract to constant in global scope== + +const newLocal = 2 + 1; + +class C { + x = /*RENAME*/newLocal; +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition7.js b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition7.js new file mode 100644 index 00000000000..f73cba1b34c --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition7.js @@ -0,0 +1,37 @@ +// ==ORIGINAL== + +const i = 0; +class C { + M() { + for (let j = 0; j < 10; j++) { + x = i + 1; + } + } +} + +// ==SCOPE::Extract to constant in method 'M== + +const i = 0; +class C { + M() { + for (let j = 0; j < 10; j++) { + const newLocal = i + 1; + + x = /*RENAME*/newLocal; + } + } +} + +// ==SCOPE::Extract to constant in global scope== + +const i = 0; +const newLocal = i + 1; + +class C { + M() { + for (let j = 0; j < 10; j++) { + x = /*RENAME*/newLocal; + } + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition7.ts b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition7.ts new file mode 100644 index 00000000000..308df5785fb --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_StatementInsertionPosition7.ts @@ -0,0 +1,50 @@ +// ==ORIGINAL== + +const i = 0; +class C { + M() { + for (let j = 0; j < 10; j++) { + x = i + 1; + } + } +} + +// ==SCOPE::Extract to constant in method 'M== + +const i = 0; +class C { + M() { + for (let j = 0; j < 10; j++) { + const newLocal: any = i + 1; + + x = /*RENAME*/newLocal; + } + } +} + +// ==SCOPE::Extract to readonly field in class 'C'== + +const i = 0; +class C { + private readonly newProperty: any = i + 1; + + M() { + for (let j = 0; j < 10; j++) { + x = this./*RENAME*/newProperty; + } + } +} + +// ==SCOPE::Extract to constant in global scope== + +const i = 0; +const newLocal: any = i + 1; + +class C { + M() { + for (let j = 0; j < 10; j++) { + x = /*RENAME*/newLocal; + } + } +} + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_TripleSlash.js b/tests/baselines/reference/extractConstant/extractConstant_TripleSlash.js new file mode 100644 index 00000000000..5003e8aa33e --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_TripleSlash.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/// + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/// + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_TripleSlash.ts b/tests/baselines/reference/extractConstant/extractConstant_TripleSlash.ts new file mode 100644 index 00000000000..5003e8aa33e --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_TripleSlash.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/// + +const x = 2 + 1; + +// ==SCOPE::Extract to constant in global scope== + +/// + +const newLocal = 2 + 1; + +const x = /*RENAME*/newLocal; + \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_VariableList_MultipleLines.js b/tests/baselines/reference/extractConstant/extractConstant_VariableList_MultipleLines.js new file mode 100644 index 00000000000..7582195a458 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_VariableList_MultipleLines.js @@ -0,0 +1,6 @@ +// ==ORIGINAL== +const /*About A*/a = 1, + /*About B*/b = a + 1; +// ==SCOPE::Extract to constant in global scope== +const /*About A*/a = 1, + /*About B*/newLocal = a + 1, b = /*RENAME*/newLocal; \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_VariableList_MultipleLines.ts b/tests/baselines/reference/extractConstant/extractConstant_VariableList_MultipleLines.ts new file mode 100644 index 00000000000..7582195a458 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_VariableList_MultipleLines.ts @@ -0,0 +1,6 @@ +// ==ORIGINAL== +const /*About A*/a = 1, + /*About B*/b = a + 1; +// ==SCOPE::Extract to constant in global scope== +const /*About A*/a = 1, + /*About B*/newLocal = a + 1, b = /*RENAME*/newLocal; \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_VariableList_const.js b/tests/baselines/reference/extractConstant/extractConstant_VariableList_const.js new file mode 100644 index 00000000000..efcc7a5a00c --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_VariableList_const.js @@ -0,0 +1,4 @@ +// ==ORIGINAL== +const a = 1, b = a + 1; +// ==SCOPE::Extract to constant in global scope== +const a = 1, newLocal = a + 1, b = /*RENAME*/newLocal; \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_VariableList_const.ts b/tests/baselines/reference/extractConstant/extractConstant_VariableList_const.ts new file mode 100644 index 00000000000..efcc7a5a00c --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_VariableList_const.ts @@ -0,0 +1,4 @@ +// ==ORIGINAL== +const a = 1, b = a + 1; +// ==SCOPE::Extract to constant in global scope== +const a = 1, newLocal = a + 1, b = /*RENAME*/newLocal; \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_VariableList_let.js b/tests/baselines/reference/extractConstant/extractConstant_VariableList_let.js new file mode 100644 index 00000000000..dc0796596cb --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_VariableList_let.js @@ -0,0 +1,4 @@ +// ==ORIGINAL== +let a = 1, b = a + 1; +// ==SCOPE::Extract to constant in global scope== +let a = 1, newLocal = a + 1, b = /*RENAME*/newLocal; \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_VariableList_let.ts b/tests/baselines/reference/extractConstant/extractConstant_VariableList_let.ts new file mode 100644 index 00000000000..dc0796596cb --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_VariableList_let.ts @@ -0,0 +1,4 @@ +// ==ORIGINAL== +let a = 1, b = a + 1; +// ==SCOPE::Extract to constant in global scope== +let a = 1, newLocal = a + 1, b = /*RENAME*/newLocal; \ No newline at end of file