From b8ea1473451c2497febc159fc0185f9e445356af Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 20 Dec 2023 17:52:07 +0100 Subject: [PATCH 01/24] wip --- src/services/refactors/extractSymbol.ts | 2 +- src/services/refactors/moveToFile.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index f25098e2c060a..a0257cc4b9824 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -2222,7 +2222,7 @@ function isExtractableExpression(node: Node): boolean { return true; } -function isBlockLike(node: Node): node is BlockLike { +export function isBlockLike(node: Node): node is BlockLike { switch (node.kind) { case SyntaxKind.Block: case SyntaxKind.SourceFile: diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index d3801aabac74a..b5ba3e241bcbb 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -42,6 +42,7 @@ import { FindAllReferences, findIndex, findLast, + findTokenOnLeftOfPosition, firstDefined, flatMap, forEachKey, @@ -151,6 +152,7 @@ import { import { registerRefactor, } from "../refactorProvider"; +import { isBlockLike } from "./extractSymbol"; const refactorNameForMoveToFile = "Move to file"; const description = getLocaleSpecificMessage(Diagnostics.Move_to_file); @@ -167,6 +169,16 @@ registerRefactor(refactorNameForMoveToFile, { if (!interactiveRefactorArguments) { return emptyArray; } + const file = context.file; + const startPosition = context.startPosition; + const endPosition = context.endPosition; + const startNode = findTokenOnLeftOfPosition(file, textSpanEnd(span)); + const endNode = findTokenOnLeftOfPosition(file, textSpanEnd(span)); + + if (startNode && startNode.kind !== SyntaxKind.SourceFile && isBlockLike(startNode) + && endNode && endNode.kind !== SyntaxKind.SourceFile && isBlockLike(endNode)) { + return emptyArray; + } if (context.preferences.allowTextChangesInNewFiles && statements) { return [{ name: refactorNameForMoveToFile, description, actions: [moveToFileAction] }]; } @@ -175,6 +187,7 @@ registerRefactor(refactorNameForMoveToFile, { } return emptyArray; }, + getEditsForAction: function getRefactorEditsToMoveToFile(context, actionName, interactiveRefactorArguments): RefactorEditInfo | undefined { Debug.assert(actionName === refactorNameForMoveToFile, "Wrong refactor invoked"); const statements = Debug.checkDefined(getStatementsToMove(context)); From 9e8359e4aa6937dc0a72c384c2df47cada910afc Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 17 Jan 2024 15:16:06 +0100 Subject: [PATCH 02/24] adding changes --- src/services/refactors/moveToFile.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index b5ba3e241bcbb..f485ce9ffa048 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -42,7 +42,6 @@ import { FindAllReferences, findIndex, findLast, - findTokenOnLeftOfPosition, firstDefined, flatMap, forEachKey, @@ -61,6 +60,7 @@ import { getRelativePathFromFile, getSourceFileOfNode, getSynthesizedDeepClone, + getTokenAtPosition, getUniqueName, hasJSFileExtension, hasSyntacticModifier, @@ -169,15 +169,15 @@ registerRefactor(refactorNameForMoveToFile, { if (!interactiveRefactorArguments) { return emptyArray; } - const file = context.file; - const startPosition = context.startPosition; const endPosition = context.endPosition; - const startNode = findTokenOnLeftOfPosition(file, textSpanEnd(span)); - const endNode = findTokenOnLeftOfPosition(file, textSpanEnd(span)); - - if (startNode && startNode.kind !== SyntaxKind.SourceFile && isBlockLike(startNode) - && endNode && endNode.kind !== SyntaxKind.SourceFile && isBlockLike(endNode)) { - return emptyArray; + if (endPosition) { + const file = context.file; + const startNode = getTokenAtPosition(file, context.startPosition); + const endNode = getTokenAtPosition(file, endPosition); + if (startNode.kind !== SyntaxKind.SourceFile && isBlockLike(startNode) + && endNode.kind !== SyntaxKind.SourceFile && isBlockLike(endNode)) { + return emptyArray; + } } if (context.preferences.allowTextChangesInNewFiles && statements) { return [{ name: refactorNameForMoveToFile, description, actions: [moveToFileAction] }]; @@ -187,7 +187,6 @@ registerRefactor(refactorNameForMoveToFile, { } return emptyArray; }, - getEditsForAction: function getRefactorEditsToMoveToFile(context, actionName, interactiveRefactorArguments): RefactorEditInfo | undefined { Debug.assert(actionName === refactorNameForMoveToFile, "Wrong refactor invoked"); const statements = Debug.checkDefined(getStatementsToMove(context)); From 0547a8820a49c7e30157ca4faf19c931d1223ab2 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 17 Jan 2024 15:19:58 +0100 Subject: [PATCH 03/24] formatting the code correctly --- src/services/refactors/moveToFile.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index f485ce9ffa048..13043c1426fc0 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -152,7 +152,9 @@ import { import { registerRefactor, } from "../refactorProvider"; -import { isBlockLike } from "./extractSymbol"; +import { + isBlockLike +} from "./extractSymbol"; const refactorNameForMoveToFile = "Move to file"; const description = getLocaleSpecificMessage(Diagnostics.Move_to_file); @@ -174,8 +176,10 @@ registerRefactor(refactorNameForMoveToFile, { const file = context.file; const startNode = getTokenAtPosition(file, context.startPosition); const endNode = getTokenAtPosition(file, endPosition); - if (startNode.kind !== SyntaxKind.SourceFile && isBlockLike(startNode) - && endNode.kind !== SyntaxKind.SourceFile && isBlockLike(endNode)) { + if ( + startNode.kind !== SyntaxKind.SourceFile && isBlockLike(startNode) + && endNode.kind !== SyntaxKind.SourceFile && isBlockLike(endNode) + ) { return emptyArray; } } From 247225967173532ac9b0d9e5fdff28b5f328f296 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 17 Jan 2024 15:21:33 +0100 Subject: [PATCH 04/24] adding a missing comma --- src/services/refactors/moveToFile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 13043c1426fc0..ee5188e96ceb6 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -153,7 +153,7 @@ import { registerRefactor, } from "../refactorProvider"; import { - isBlockLike + isBlockLike, } from "./extractSymbol"; const refactorNameForMoveToFile = "Move to file"; From afc1fd24257142a679b81a5254a0aadc45aaeff8 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 17 Jan 2024 16:48:55 +0100 Subject: [PATCH 05/24] adding baseline change --- tests/baselines/reference/api/typescript.d.ts | 5 +++++ .../moveToFile_emptyTargetFile.js | 22 +++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1e433e55d63f3..87cd40cc3e597 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -10358,6 +10358,11 @@ declare namespace ts { readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[] | undefined, depth?: number): string[]; } } + namespace refactor { + namespace extractSymbol { + function isBlockLike(node: Node): node is BlockLike; + } + } function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatCodeSettings; /** * Represents an immutable snapshot of a script at a specified time.Once acquired, the diff --git a/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js b/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js index ade05d87033d2..c189e8a18ee18 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js +++ b/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js @@ -225,17 +225,6 @@ Info seq [hh:mm:ss:mss] response: } ] }, - { - "name": "Move to file", - "description": "Move to file", - "actions": [ - { - "name": "Move to file", - "description": "Move to file", - "kind": "refactor.move.file" - } - ] - }, { "name": "Extract Symbol", "description": "Extract function", @@ -257,6 +246,17 @@ Info seq [hh:mm:ss:mss] response: "kind": "refactor.extract.constant" } ] + }, + { + "name": "Move to file", + "description": "Move to file", + "actions": [ + { + "name": "Move to file", + "description": "Move to file", + "kind": "refactor.move.file" + } + ] } ] } From f0b00aa0b4973b33d0a806ed0a0cc6a933f125e7 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 18 Jan 2024 14:13:16 +0100 Subject: [PATCH 06/24] review changes --- src/services/refactors/extractSymbol.ts | 13 +------------ src/services/refactors/moveToFile.ts | 6 ++---- src/services/utilities.ts | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index e3662cecfed09..2781f06876e81 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -6,7 +6,6 @@ import { assertType, BindingElement, Block, - BlockLike, BreakStatement, CancellationToken, canHaveModifiers, @@ -67,6 +66,7 @@ import { isAssignmentExpression, isBinaryExpression, isBlock, + isBlockLike, isBlockScope, isCaseClause, isClassLike, @@ -2221,17 +2221,6 @@ function isExtractableExpression(node: Node): boolean { return true; } -export function isBlockLike(node: Node): node is BlockLike { - switch (node.kind) { - case SyntaxKind.Block: - case SyntaxKind.SourceFile: - case SyntaxKind.ModuleBlock: - case SyntaxKind.CaseClause: - return true; - default: - return false; - } -} function isInJSXContent(node: Node) { return isStringLiteralJsxAttribute(node) || diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index ee5188e96ceb6..53958f8ed134d 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -76,6 +76,7 @@ import { isArrayLiteralExpression, isBinaryExpression, isBindingElement, + isBlockLike, isDeclarationName, isExportDeclaration, isExportSpecifier, @@ -152,9 +153,6 @@ import { import { registerRefactor, } from "../refactorProvider"; -import { - isBlockLike, -} from "./extractSymbol"; const refactorNameForMoveToFile = "Move to file"; const description = getLocaleSpecificMessage(Diagnostics.Move_to_file); @@ -172,7 +170,7 @@ registerRefactor(refactorNameForMoveToFile, { return emptyArray; } const endPosition = context.endPosition; - if (endPosition) { + if (endPosition !== undefined) { const file = context.file; const startNode = getTokenAtPosition(file, context.startPosition); const endNode = getTokenAtPosition(file, endPosition); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 0b2072f449008..ef1118d0f73ac 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -9,6 +9,7 @@ import { BinaryExpression, binarySearchKey, BindingElement, + BlockLike, BreakOrContinueStatement, CallExpression, canHaveModifiers, @@ -4274,3 +4275,16 @@ export function fileShouldUseJavaScriptRequire(file: SourceFile | string, progra } return preferRequire; } + +/** @internal */ +export function isBlockLike(node: Node): node is BlockLike { + switch (node.kind) { + case SyntaxKind.Block: + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleBlock: + case SyntaxKind.CaseClause: + return true; + default: + return false; + } +} \ No newline at end of file From d7eedd8791ecefcef558aec55b94bf0c003ce7b5 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 12:02:33 +0100 Subject: [PATCH 07/24] adding code from review --- .vscode/launch.template.json | 64 -------------------- src/compiler/types.ts | 4 ++ src/harness/fourslashImpl.ts | 2 +- src/services/refactors/moveToFile.ts | 21 +++++-- src/services/utilities.ts | 12 ++++ tests/cases/fourslash/refactorMoveToFile1.ts | 12 ++++ 6 files changed, 46 insertions(+), 69 deletions(-) delete mode 100644 .vscode/launch.template.json create mode 100644 tests/cases/fourslash/refactorMoveToFile1.ts diff --git a/.vscode/launch.template.json b/.vscode/launch.template.json deleted file mode 100644 index 80b4c599aa4a7..0000000000000 --- a/.vscode/launch.template.json +++ /dev/null @@ -1,64 +0,0 @@ -/* - - Copy this file into '.vscode/launch.json' or merge its - contents into your existing configurations. - - If you want to remove the errors in comments for all JSON - files, add this to your settings in ~/.vscode/User/settings.json - - "files.associations": { - "*.json": "jsonc" - }, - -*/ - -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Mocha Tests (currently opened test)", - "runtimeArgs": ["--nolazy"], - "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", - "args": [ - "-u", - "bdd", - "--no-timeouts", - "--colors", - "built/local/run.js", - "-f", - // You can change this to be the name of a specific test file (without the file extension) - // to consistently launch the same test - "${fileBasenameNoExtension}", - "--skip-percent", - "0" - ], - "env": { - "NODE_ENV": "testing" - }, - "outFiles": [ - "${workspaceFolder}/built/**/*.js", - "${workspaceFolder}/built/**/*.mjs", - "${workspaceFolder}/built/**/*.cjs", - "!**/node_modules/**" - ], - "sourceMaps": true, - "smartStep": true, - "preLaunchTask": "npm: build:tests", - "console": "integratedTerminal", - "customDescriptionGenerator": "'__tsDebuggerDisplay' in this ? this.__tsDebuggerDisplay(defaultValue) : defaultValue" - }, - { - // See: https://github.com/microsoft/TypeScript/wiki/Debugging-Language-Service-in-VS-Code - "type": "node", - "request": "attach", - "name": "Attach to VS Code TS Server via Port", - "processId": "${command:PickProcess}", - "customDescriptionGenerator": "'__tsDebuggerDisplay' in this ? this.__tsDebuggerDisplay(defaultValue) : defaultValue" - } - ] -} diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3003eb43035a1..ca07ef693fe3a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3305,6 +3305,10 @@ export type BlockLike = | ModuleBlock | CaseOrDefaultClause; +export type RootNode = + | SourceFile + | Bundle; + export interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 7d9d3c6c9f9bb..0711c315089d1 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4446,7 +4446,7 @@ export class TestState { } private getApplicableRefactorsAtSelection(triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, preferences = ts.emptyOptions) { - return this.getApplicableRefactorsWorker(this.getSelection(), this.activeFile.fileName, preferences, triggerReason, kind); + return this.getApplicableRefactorsWorker(this.getSelection(), this.activeFile.fileName, preferences, triggerReason, kind, true); } private getApplicableRefactors(rangeOrMarker: Range | Marker, preferences = ts.emptyOptions, triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, includeInteractiveActions?: boolean): readonly ts.ApplicableRefactorInfo[] { return this.getApplicableRefactorsWorker("position" in rangeOrMarker ? rangeOrMarker.position : rangeOrMarker, rangeOrMarker.fileName, preferences, triggerReason, kind, includeInteractiveActions); // eslint-disable-line local/no-in-operator diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 53958f8ed134d..4f6e4e2f8043f 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -11,6 +11,7 @@ import { BinaryExpression, BindingElement, BindingName, + BlockLike, CallExpression, canHaveDecorators, canHaveModifiers, @@ -95,6 +96,7 @@ import { isPropertyAccessExpression, isPropertyAssignment, isRequireCall, + isRootNode, isSourceFile, isStatement, isStringLiteral, @@ -128,6 +130,7 @@ import { RequireOrImportCall, RequireVariableStatement, resolvePath, + RootNode, ScriptTarget, skipAlias, some, @@ -174,10 +177,9 @@ registerRefactor(refactorNameForMoveToFile, { const file = context.file; const startNode = getTokenAtPosition(file, context.startPosition); const endNode = getTokenAtPosition(file, endPosition); - if ( - startNode.kind !== SyntaxKind.SourceFile && isBlockLike(startNode) - && endNode.kind !== SyntaxKind.SourceFile && isBlockLike(endNode) - ) { + const startNodeAncestor = getBlockLikeAncestorOrRootNode(startNode); + const endNodeAncestor = getBlockLikeAncestorOrRootNode(endNode); + if (!isRootNode(startNodeAncestor) && !isRootNode(endNodeAncestor)) { return emptyArray; } } @@ -288,6 +290,17 @@ function getNewStatementsAndRemoveFromOldFile( ]; } +function getBlockLikeAncestorOrRootNode(node : Node) : BlockLike | RootNode { + let currentNode = node; + while (!isRootNode(currentNode)) { + if (isBlockLike(currentNode)) { + break; + } + currentNode = currentNode.parent; + } + return currentNode; +} + function getTargetFileImportsAndAddExportInOldFile( oldFile: SourceFile, targetFile: string, diff --git a/src/services/utilities.ts b/src/services/utilities.ts index ef1118d0f73ac..28ea21d74517a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -311,6 +311,7 @@ import { pseudoBigIntToString, QualifiedName, RefactorContext, + RootNode, Scanner, ScriptElementKind, ScriptElementKindModifier, @@ -4287,4 +4288,15 @@ export function isBlockLike(node: Node): node is BlockLike { default: return false; } +} + +/** @internal */ +export function isRootNode(node: Node) : node is RootNode { + switch (node.kind) { + case SyntaxKind.SourceFile: + case SyntaxKind.Bundle: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/tests/cases/fourslash/refactorMoveToFile1.ts b/tests/cases/fourslash/refactorMoveToFile1.ts new file mode 100644 index 0000000000000..7360f2839e94e --- /dev/null +++ b/tests/cases/fourslash/refactorMoveToFile1.ts @@ -0,0 +1,12 @@ +/// + +////namespace ns { +//// /*a*/export function fn() { +//// +//// } +//// fn(); +//// /*b*/ +////} + +goTo.select("a", "b"); +verify.not.refactorAvailable("Move to file"); From 7d21d2dadca9d1f006c480ee575012fa8e4659ea Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 12:04:58 +0100 Subject: [PATCH 08/24] code review changes --- src/compiler/types.ts | 4 ++++ src/harness/fourslashImpl.ts | 2 +- src/services/refactors/moveToFile.ts | 21 ++++++++++++++++---- src/services/utilities.ts | 12 +++++++++++ tests/cases/fourslash/refactorMoveToFile1.ts | 12 +++++++++++ 5 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 tests/cases/fourslash/refactorMoveToFile1.ts diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3003eb43035a1..ca07ef693fe3a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3305,6 +3305,10 @@ export type BlockLike = | ModuleBlock | CaseOrDefaultClause; +export type RootNode = + | SourceFile + | Bundle; + export interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 7d9d3c6c9f9bb..0711c315089d1 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4446,7 +4446,7 @@ export class TestState { } private getApplicableRefactorsAtSelection(triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, preferences = ts.emptyOptions) { - return this.getApplicableRefactorsWorker(this.getSelection(), this.activeFile.fileName, preferences, triggerReason, kind); + return this.getApplicableRefactorsWorker(this.getSelection(), this.activeFile.fileName, preferences, triggerReason, kind, true); } private getApplicableRefactors(rangeOrMarker: Range | Marker, preferences = ts.emptyOptions, triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, includeInteractiveActions?: boolean): readonly ts.ApplicableRefactorInfo[] { return this.getApplicableRefactorsWorker("position" in rangeOrMarker ? rangeOrMarker.position : rangeOrMarker, rangeOrMarker.fileName, preferences, triggerReason, kind, includeInteractiveActions); // eslint-disable-line local/no-in-operator diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 53958f8ed134d..4f6e4e2f8043f 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -11,6 +11,7 @@ import { BinaryExpression, BindingElement, BindingName, + BlockLike, CallExpression, canHaveDecorators, canHaveModifiers, @@ -95,6 +96,7 @@ import { isPropertyAccessExpression, isPropertyAssignment, isRequireCall, + isRootNode, isSourceFile, isStatement, isStringLiteral, @@ -128,6 +130,7 @@ import { RequireOrImportCall, RequireVariableStatement, resolvePath, + RootNode, ScriptTarget, skipAlias, some, @@ -174,10 +177,9 @@ registerRefactor(refactorNameForMoveToFile, { const file = context.file; const startNode = getTokenAtPosition(file, context.startPosition); const endNode = getTokenAtPosition(file, endPosition); - if ( - startNode.kind !== SyntaxKind.SourceFile && isBlockLike(startNode) - && endNode.kind !== SyntaxKind.SourceFile && isBlockLike(endNode) - ) { + const startNodeAncestor = getBlockLikeAncestorOrRootNode(startNode); + const endNodeAncestor = getBlockLikeAncestorOrRootNode(endNode); + if (!isRootNode(startNodeAncestor) && !isRootNode(endNodeAncestor)) { return emptyArray; } } @@ -288,6 +290,17 @@ function getNewStatementsAndRemoveFromOldFile( ]; } +function getBlockLikeAncestorOrRootNode(node : Node) : BlockLike | RootNode { + let currentNode = node; + while (!isRootNode(currentNode)) { + if (isBlockLike(currentNode)) { + break; + } + currentNode = currentNode.parent; + } + return currentNode; +} + function getTargetFileImportsAndAddExportInOldFile( oldFile: SourceFile, targetFile: string, diff --git a/src/services/utilities.ts b/src/services/utilities.ts index ef1118d0f73ac..28ea21d74517a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -311,6 +311,7 @@ import { pseudoBigIntToString, QualifiedName, RefactorContext, + RootNode, Scanner, ScriptElementKind, ScriptElementKindModifier, @@ -4287,4 +4288,15 @@ export function isBlockLike(node: Node): node is BlockLike { default: return false; } +} + +/** @internal */ +export function isRootNode(node: Node) : node is RootNode { + switch (node.kind) { + case SyntaxKind.SourceFile: + case SyntaxKind.Bundle: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/tests/cases/fourslash/refactorMoveToFile1.ts b/tests/cases/fourslash/refactorMoveToFile1.ts new file mode 100644 index 0000000000000..7360f2839e94e --- /dev/null +++ b/tests/cases/fourslash/refactorMoveToFile1.ts @@ -0,0 +1,12 @@ +/// + +////namespace ns { +//// /*a*/export function fn() { +//// +//// } +//// fn(); +//// /*b*/ +////} + +goTo.select("a", "b"); +verify.not.refactorAvailable("Move to file"); From 32fce2a79c606d93af46ee57ba2fdddc0322ed01 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 12:06:39 +0100 Subject: [PATCH 09/24] add back template file --- .vscode/launch.template.json | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .vscode/launch.template.json diff --git a/.vscode/launch.template.json b/.vscode/launch.template.json new file mode 100644 index 0000000000000..80b4c599aa4a7 --- /dev/null +++ b/.vscode/launch.template.json @@ -0,0 +1,64 @@ +/* + + Copy this file into '.vscode/launch.json' or merge its + contents into your existing configurations. + + If you want to remove the errors in comments for all JSON + files, add this to your settings in ~/.vscode/User/settings.json + + "files.associations": { + "*.json": "jsonc" + }, + +*/ + +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Mocha Tests (currently opened test)", + "runtimeArgs": ["--nolazy"], + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "args": [ + "-u", + "bdd", + "--no-timeouts", + "--colors", + "built/local/run.js", + "-f", + // You can change this to be the name of a specific test file (without the file extension) + // to consistently launch the same test + "${fileBasenameNoExtension}", + "--skip-percent", + "0" + ], + "env": { + "NODE_ENV": "testing" + }, + "outFiles": [ + "${workspaceFolder}/built/**/*.js", + "${workspaceFolder}/built/**/*.mjs", + "${workspaceFolder}/built/**/*.cjs", + "!**/node_modules/**" + ], + "sourceMaps": true, + "smartStep": true, + "preLaunchTask": "npm: build:tests", + "console": "integratedTerminal", + "customDescriptionGenerator": "'__tsDebuggerDisplay' in this ? this.__tsDebuggerDisplay(defaultValue) : defaultValue" + }, + { + // See: https://github.com/microsoft/TypeScript/wiki/Debugging-Language-Service-in-VS-Code + "type": "node", + "request": "attach", + "name": "Attach to VS Code TS Server via Port", + "processId": "${command:PickProcess}", + "customDescriptionGenerator": "'__tsDebuggerDisplay' in this ? this.__tsDebuggerDisplay(defaultValue) : defaultValue" + } + ] +} From bbff7528c038ca2b69ce2ca31d69182a0fb7f9e9 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 12:42:28 +0100 Subject: [PATCH 10/24] fixing formatting and linting errors --- src/harness/fourslashImpl.ts | 4 ++-- src/services/refactors/extractSymbol.ts | 1 - src/services/refactors/moveToFile.ts | 2 +- src/services/utilities.ts | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 0711c315089d1..98a6f652cbadc 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -4445,8 +4445,8 @@ export class TestState { test(renameKeys(newFileContents, key => pathUpdater(key) || key), "with file moved"); } - private getApplicableRefactorsAtSelection(triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, preferences = ts.emptyOptions) { - return this.getApplicableRefactorsWorker(this.getSelection(), this.activeFile.fileName, preferences, triggerReason, kind, true); + private getApplicableRefactorsAtSelection(triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + return this.getApplicableRefactorsWorker(this.getSelection(), this.activeFile.fileName, preferences, triggerReason, kind, includeInteractiveActions); } private getApplicableRefactors(rangeOrMarker: Range | Marker, preferences = ts.emptyOptions, triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, includeInteractiveActions?: boolean): readonly ts.ApplicableRefactorInfo[] { return this.getApplicableRefactorsWorker("position" in rangeOrMarker ? rangeOrMarker.position : rangeOrMarker, rangeOrMarker.fileName, preferences, triggerReason, kind, includeInteractiveActions); // eslint-disable-line local/no-in-operator diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 2781f06876e81..b9406e8f1b594 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -2221,7 +2221,6 @@ function isExtractableExpression(node: Node): boolean { return true; } - function isInJSXContent(node: Node) { return isStringLiteralJsxAttribute(node) || (isJsxElement(node) || isJsxSelfClosingElement(node) || isJsxFragment(node)) && (isJsxElement(node.parent) || isJsxFragment(node.parent)); diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 4f6e4e2f8043f..d348b4f6114d3 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -290,7 +290,7 @@ function getNewStatementsAndRemoveFromOldFile( ]; } -function getBlockLikeAncestorOrRootNode(node : Node) : BlockLike | RootNode { +function getBlockLikeAncestorOrRootNode(node: Node): BlockLike | RootNode { let currentNode = node; while (!isRootNode(currentNode)) { if (isBlockLike(currentNode)) { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 28ea21d74517a..09afd0db884c4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -4291,7 +4291,7 @@ export function isBlockLike(node: Node): node is BlockLike { } /** @internal */ -export function isRootNode(node: Node) : node is RootNode { +export function isRootNode(node: Node): node is RootNode { switch (node.kind) { case SyntaxKind.SourceFile: case SyntaxKind.Bundle: @@ -4299,4 +4299,4 @@ export function isRootNode(node: Node) : node is RootNode { default: return false; } -} \ No newline at end of file +} From dea141aa92488df0dbaf82d10236b3227a82566b Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 13:06:11 +0100 Subject: [PATCH 11/24] making the preferences object also parameter for the tests --- src/harness/fourslashImpl.ts | 4 ++-- src/harness/fourslashInterfaceImpl.ts | 8 ++++---- tests/cases/fourslash/fourslash.ts | 4 ++-- tests/cases/fourslash/refactorMoveToFile1.ts | 8 +++++++- tests/cases/fourslash/refactorMoveToFile2.ts | 18 ++++++++++++++++++ 5 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 tests/cases/fourslash/refactorMoveToFile2.ts diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 98a6f652cbadc..949395f138e96 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -3979,8 +3979,8 @@ export class TestState { }; } - public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string) { - let refactors = this.getApplicableRefactorsAtSelection(triggerReason); + public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + let refactors = this.getApplicableRefactorsAtSelection(triggerReason, undefined, preferences, includeInteractiveActions); refactors = refactors.filter(r => r.name === name); if (actionName !== undefined) { diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 309dc84fb45f4..246598c4a7ab1 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -212,12 +212,12 @@ export class VerifyNegatable { this.state.verifyRefactorsAvailable(names); } - public refactorAvailable(name: string, actionName?: string, actionDescription?: string) { - this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName, actionDescription); + public refactorAvailable(name: string, actionName?: string, actionDescription?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName, actionDescription, preferences, includeInteractiveActions); } - public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string) { - this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName); + public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName, undefined, preferences, includeInteractiveActions); } public refactorKindAvailable(kind: string, expected: string[], preferences = ts.emptyOptions) { diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 5daa7c0b3167e..8fd5235470b0c 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -281,8 +281,8 @@ declare namespace FourSlashInterface { codeFixDiagnosticsAvailableAtMarkers(markerNames: string[], diagnosticCode?: number): void; applicableRefactorAvailableForRange(): void; - refactorAvailable(name: string, actionName?: string, actionDescription?: string): void; - refactorAvailableForTriggerReason(triggerReason: RefactorTriggerReason, name: string, action?: string): void; + refactorAvailable(name: string, actionName?: string, actionDescription?: string, preferences?: {}, includeInteractiveActions?: boolean): void; + refactorAvailableForTriggerReason(triggerReason: RefactorTriggerReason, name: string, action?: string, preferences?: {}, includeInteractiveActions?: boolean): void; refactorKindAvailable(refactorKind: string, expected: string[], preferences?: {}): void; } class verify extends verifyNegatable { diff --git a/tests/cases/fourslash/refactorMoveToFile1.ts b/tests/cases/fourslash/refactorMoveToFile1.ts index 7360f2839e94e..5bbc0b2508d4f 100644 --- a/tests/cases/fourslash/refactorMoveToFile1.ts +++ b/tests/cases/fourslash/refactorMoveToFile1.ts @@ -9,4 +9,10 @@ ////} goTo.select("a", "b"); -verify.not.refactorAvailable("Move to file"); +verify.not.refactorAvailable("Move to file", +undefined, +undefined, +{ + allowTextChangesInNewFiles : true +}, +true); diff --git a/tests/cases/fourslash/refactorMoveToFile2.ts b/tests/cases/fourslash/refactorMoveToFile2.ts new file mode 100644 index 0000000000000..a489a12c7e142 --- /dev/null +++ b/tests/cases/fourslash/refactorMoveToFile2.ts @@ -0,0 +1,18 @@ +/// + +/////*a*/ +////namespace ns { +//// export function fn() { +//// } +//// fn(); +////} +/////*b*/ + +goTo.select("a", "b"); +verify.refactorAvailable("Move to file", +undefined, +undefined, +{ + allowTextChangesInNewFiles : true +}, +true); From 3b78378e086231e6dc86cb64e2ad9a5e705cd501 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 13:16:55 +0100 Subject: [PATCH 12/24] fixing formatting errors --- src/harness/fourslashImpl.ts | 4 ++-- src/harness/fourslashInterfaceImpl.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 949395f138e96..08698bf8b2721 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -3979,8 +3979,8 @@ export class TestState { }; } - public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { - let refactors = this.getApplicableRefactorsAtSelection(triggerReason, undefined, preferences, includeInteractiveActions); + public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, kind?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + let refactors = this.getApplicableRefactorsAtSelection(triggerReason, kind, preferences, includeInteractiveActions); refactors = refactors.filter(r => r.name === name); if (actionName !== undefined) { diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 246598c4a7ab1..e23554831bf51 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -212,12 +212,12 @@ export class VerifyNegatable { this.state.verifyRefactorsAvailable(names); } - public refactorAvailable(name: string, actionName?: string, actionDescription?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { - this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName, actionDescription, preferences, includeInteractiveActions); + public refactorAvailable(name: string, actionName?: string, actionDescription?: string, kind?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName, actionDescription, kind, preferences, includeInteractiveActions); } - public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { - this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName, undefined, preferences, includeInteractiveActions); + public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, kind?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName, actionDescription, kind, preferences, includeInteractiveActions); } public refactorKindAvailable(kind: string, expected: string[], preferences = ts.emptyOptions) { From 1cad4fe1059c35abf699be7c2c55b2b752fb6ce7 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 13:17:59 +0100 Subject: [PATCH 13/24] adding changes --- tests/baselines/reference/api/typescript.d.ts | 6 +---- .../fixExtractToInnerFunctionDuplicaton.js | 18 ++++++++++----- .../moveToFile_emptyTargetFile.js | 22 +++++++++---------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 87cd40cc3e597..fb7e7cabd3eef 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5789,6 +5789,7 @@ declare namespace ts { readonly name?: Identifier; } type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause; + type RootNode = SourceFile | Bundle; interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; @@ -10358,11 +10359,6 @@ declare namespace ts { readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[] | undefined, depth?: number): string[]; } } - namespace refactor { - namespace extractSymbol { - function isBlockLike(node: Node): node is BlockLike; - } - } function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatCodeSettings; /** * Represents an immutable snapshot of a script at a specified time.Once acquired, the diff --git a/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js b/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js index 0fcedaa595690..bb343478bba40 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js +++ b/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js @@ -114,7 +114,8 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit" + "triggerReason": "implicit", + "includeInteractiveActions": true }, "command": "getApplicableRefactors" } @@ -204,7 +205,8 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit" + "triggerReason": "implicit", + "includeInteractiveActions": true }, "command": "getApplicableRefactors" } @@ -294,7 +296,8 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit" + "triggerReason": "implicit", + "includeInteractiveActions": true }, "command": "getApplicableRefactors" } @@ -384,7 +387,8 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit" + "triggerReason": "implicit", + "includeInteractiveActions": true }, "command": "getApplicableRefactors" } @@ -474,7 +478,8 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit" + "triggerReason": "implicit", + "includeInteractiveActions": true }, "command": "getApplicableRefactors" } @@ -564,7 +569,8 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit" + "triggerReason": "implicit", + "includeInteractiveActions": true }, "command": "getApplicableRefactors" } diff --git a/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js b/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js index c189e8a18ee18..ade05d87033d2 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js +++ b/tests/baselines/reference/tsserver/fourslashServer/moveToFile_emptyTargetFile.js @@ -225,6 +225,17 @@ Info seq [hh:mm:ss:mss] response: } ] }, + { + "name": "Move to file", + "description": "Move to file", + "actions": [ + { + "name": "Move to file", + "description": "Move to file", + "kind": "refactor.move.file" + } + ] + }, { "name": "Extract Symbol", "description": "Extract function", @@ -246,17 +257,6 @@ Info seq [hh:mm:ss:mss] response: "kind": "refactor.extract.constant" } ] - }, - { - "name": "Move to file", - "description": "Move to file", - "actions": [ - { - "name": "Move to file", - "description": "Move to file", - "kind": "refactor.move.file" - } - ] } ] } From be3e49ca9fa6e6e0ee54a23b705b2c47769085cf Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 13:25:36 +0100 Subject: [PATCH 14/24] polishing --- src/services/utilities.ts | 5 ++++- tests/baselines/reference/api/typescript.d.ts | 1 - tests/cases/fourslash/refactorMoveToFile1.ts | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 09afd0db884c4..98b9111c366af 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -11,6 +11,7 @@ import { BindingElement, BlockLike, BreakOrContinueStatement, + Bundle, CallExpression, canHaveModifiers, CaseClause, @@ -311,7 +312,6 @@ import { pseudoBigIntToString, QualifiedName, RefactorContext, - RootNode, Scanner, ScriptElementKind, ScriptElementKindModifier, @@ -4300,3 +4300,6 @@ export function isRootNode(node: Node): node is RootNode { return false; } } + +/** @internal */ +export type RootNode = SourceFile | Bundle; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index fb7e7cabd3eef..1e433e55d63f3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5789,7 +5789,6 @@ declare namespace ts { readonly name?: Identifier; } type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause; - type RootNode = SourceFile | Bundle; interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; diff --git a/tests/cases/fourslash/refactorMoveToFile1.ts b/tests/cases/fourslash/refactorMoveToFile1.ts index 5bbc0b2508d4f..22550395b0f9d 100644 --- a/tests/cases/fourslash/refactorMoveToFile1.ts +++ b/tests/cases/fourslash/refactorMoveToFile1.ts @@ -2,7 +2,6 @@ ////namespace ns { //// /*a*/export function fn() { -//// //// } //// fn(); //// /*b*/ From 4e607102abb5ffe3151cfe23ed251970c2a0e9ad Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 13:27:41 +0100 Subject: [PATCH 15/24] removing duplicate type --- src/services/utilities.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 98b9111c366af..09afd0db884c4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -11,7 +11,6 @@ import { BindingElement, BlockLike, BreakOrContinueStatement, - Bundle, CallExpression, canHaveModifiers, CaseClause, @@ -312,6 +311,7 @@ import { pseudoBigIntToString, QualifiedName, RefactorContext, + RootNode, Scanner, ScriptElementKind, ScriptElementKindModifier, @@ -4300,6 +4300,3 @@ export function isRootNode(node: Node): node is RootNode { return false; } } - -/** @internal */ -export type RootNode = SourceFile | Bundle; From e59f00611e40507958d0a1452d19752b5b994c34 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 14:40:43 +0100 Subject: [PATCH 16/24] polishing tsts --- tests/baselines/reference/api/typescript.d.ts | 1 + tests/cases/fourslash/fourslash.ts | 4 ++-- tests/cases/fourslash/refactorMoveToFile1.ts | 1 + tests/cases/fourslash/refactorMoveToFile2.ts | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1e433e55d63f3..fb7e7cabd3eef 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5789,6 +5789,7 @@ declare namespace ts { readonly name?: Identifier; } type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause; + type RootNode = SourceFile | Bundle; interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 8fd5235470b0c..ff8fad9abff01 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -281,8 +281,8 @@ declare namespace FourSlashInterface { codeFixDiagnosticsAvailableAtMarkers(markerNames: string[], diagnosticCode?: number): void; applicableRefactorAvailableForRange(): void; - refactorAvailable(name: string, actionName?: string, actionDescription?: string, preferences?: {}, includeInteractiveActions?: boolean): void; - refactorAvailableForTriggerReason(triggerReason: RefactorTriggerReason, name: string, action?: string, preferences?: {}, includeInteractiveActions?: boolean): void; + refactorAvailable(name: string, actionName?: string, actionDescription?: string, kind?: string, preferences?: {}, includeInteractiveActions?: boolean): void; + refactorAvailableForTriggerReason(triggerReason: RefactorTriggerReason, name: string, action?: string, actionDescription?: string, kind?: string, preferences?: {}, includeInteractiveActions?: boolean): void; refactorKindAvailable(refactorKind: string, expected: string[], preferences?: {}): void; } class verify extends verifyNegatable { diff --git a/tests/cases/fourslash/refactorMoveToFile1.ts b/tests/cases/fourslash/refactorMoveToFile1.ts index 22550395b0f9d..1e4b02b3b3462 100644 --- a/tests/cases/fourslash/refactorMoveToFile1.ts +++ b/tests/cases/fourslash/refactorMoveToFile1.ts @@ -11,6 +11,7 @@ goTo.select("a", "b"); verify.not.refactorAvailable("Move to file", undefined, undefined, +undefined, { allowTextChangesInNewFiles : true }, diff --git a/tests/cases/fourslash/refactorMoveToFile2.ts b/tests/cases/fourslash/refactorMoveToFile2.ts index a489a12c7e142..2da31df999bab 100644 --- a/tests/cases/fourslash/refactorMoveToFile2.ts +++ b/tests/cases/fourslash/refactorMoveToFile2.ts @@ -12,7 +12,9 @@ goTo.select("a", "b"); verify.refactorAvailable("Move to file", undefined, undefined, +undefined, { allowTextChangesInNewFiles : true }, true); + From 1e74fc34d55f3829ee99cc48766aa59de245469a Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Feb 2024 14:53:14 +0100 Subject: [PATCH 17/24] adding baseline change --- .../fixExtractToInnerFunctionDuplicaton.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js b/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js index bb343478bba40..0fcedaa595690 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js +++ b/tests/baselines/reference/tsserver/fourslashServer/fixExtractToInnerFunctionDuplicaton.js @@ -114,8 +114,7 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit", - "includeInteractiveActions": true + "triggerReason": "implicit" }, "command": "getApplicableRefactors" } @@ -205,8 +204,7 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit", - "includeInteractiveActions": true + "triggerReason": "implicit" }, "command": "getApplicableRefactors" } @@ -296,8 +294,7 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit", - "includeInteractiveActions": true + "triggerReason": "implicit" }, "command": "getApplicableRefactors" } @@ -387,8 +384,7 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit", - "includeInteractiveActions": true + "triggerReason": "implicit" }, "command": "getApplicableRefactors" } @@ -478,8 +474,7 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit", - "includeInteractiveActions": true + "triggerReason": "implicit" }, "command": "getApplicableRefactors" } @@ -569,8 +564,7 @@ Info seq [hh:mm:ss:mss] request: "startOffset": 24, "endLine": 1, "endOffset": 41, - "triggerReason": "implicit", - "includeInteractiveActions": true + "triggerReason": "implicit" }, "command": "getApplicableRefactors" } From db1078e2ec7d7046f2932dc5b19cf3d1d329b38d Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 14 Feb 2024 09:43:49 +0100 Subject: [PATCH 18/24] adding review changes --- src/services/refactors/moveToFile.ts | 20 ++++++------------- src/services/utilities.ts | 12 ----------- ...e1.ts => moveToFile_refactorAvailable1.ts} | 0 ...e2.ts => moveToFile_refactorAvailable2.ts} | 0 4 files changed, 6 insertions(+), 26 deletions(-) rename tests/cases/fourslash/{refactorMoveToFile1.ts => moveToFile_refactorAvailable1.ts} (100%) rename tests/cases/fourslash/{refactorMoveToFile2.ts => moveToFile_refactorAvailable2.ts} (100%) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index d348b4f6114d3..46ec280e29836 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -96,7 +96,6 @@ import { isPropertyAccessExpression, isPropertyAssignment, isRequireCall, - isRootNode, isSourceFile, isStatement, isStringLiteral, @@ -130,7 +129,6 @@ import { RequireOrImportCall, RequireVariableStatement, resolvePath, - RootNode, ScriptTarget, skipAlias, some, @@ -172,14 +170,11 @@ registerRefactor(refactorNameForMoveToFile, { if (!interactiveRefactorArguments) { return emptyArray; } - const endPosition = context.endPosition; - if (endPosition !== undefined) { + if (context.endPosition !== undefined) { const file = context.file; - const startNode = getTokenAtPosition(file, context.startPosition); - const endNode = getTokenAtPosition(file, endPosition); - const startNodeAncestor = getBlockLikeAncestorOrRootNode(startNode); - const endNodeAncestor = getBlockLikeAncestorOrRootNode(endNode); - if (!isRootNode(startNodeAncestor) && !isRootNode(endNodeAncestor)) { + const startNodeAncestor = getBlockLikeAncestor(getTokenAtPosition(file, context.startPosition)); + const endNodeAncestor = getBlockLikeAncestor(getTokenAtPosition(file, context.endPosition)); + if (!isSourceFile(startNodeAncestor) && !isSourceFile(endNodeAncestor)) { return emptyArray; } } @@ -290,12 +285,9 @@ function getNewStatementsAndRemoveFromOldFile( ]; } -function getBlockLikeAncestorOrRootNode(node: Node): BlockLike | RootNode { +function getBlockLikeAncestor(node: Node): BlockLike { let currentNode = node; - while (!isRootNode(currentNode)) { - if (isBlockLike(currentNode)) { - break; - } + while (!isBlockLike(currentNode)) { currentNode = currentNode.parent; } return currentNode; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 09afd0db884c4..dc5c6c777528e 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -311,7 +311,6 @@ import { pseudoBigIntToString, QualifiedName, RefactorContext, - RootNode, Scanner, ScriptElementKind, ScriptElementKindModifier, @@ -4289,14 +4288,3 @@ export function isBlockLike(node: Node): node is BlockLike { return false; } } - -/** @internal */ -export function isRootNode(node: Node): node is RootNode { - switch (node.kind) { - case SyntaxKind.SourceFile: - case SyntaxKind.Bundle: - return true; - default: - return false; - } -} diff --git a/tests/cases/fourslash/refactorMoveToFile1.ts b/tests/cases/fourslash/moveToFile_refactorAvailable1.ts similarity index 100% rename from tests/cases/fourslash/refactorMoveToFile1.ts rename to tests/cases/fourslash/moveToFile_refactorAvailable1.ts diff --git a/tests/cases/fourslash/refactorMoveToFile2.ts b/tests/cases/fourslash/moveToFile_refactorAvailable2.ts similarity index 100% rename from tests/cases/fourslash/refactorMoveToFile2.ts rename to tests/cases/fourslash/moveToFile_refactorAvailable2.ts From fa0a7d6aab2bded72928249e82f96e1519982370 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 14 Feb 2024 09:50:32 +0100 Subject: [PATCH 19/24] removing the rest of the rootNode code --- src/compiler/types.ts | 4 ---- tests/baselines/reference/api/typescript.d.ts | 1 - 2 files changed, 5 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ca07ef693fe3a..3003eb43035a1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3305,10 +3305,6 @@ export type BlockLike = | ModuleBlock | CaseOrDefaultClause; -export type RootNode = - | SourceFile - | Bundle; - export interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index fb7e7cabd3eef..1e433e55d63f3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5789,7 +5789,6 @@ declare namespace ts { readonly name?: Identifier; } type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause; - type RootNode = SourceFile | Bundle; interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; From 89d5a880329caddad0a613c90018ed4df2ba2ac1 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 16 Feb 2024 09:32:38 +0100 Subject: [PATCH 20/24] adding review changes --- src/services/refactors/moveToFile.ts | 17 +++++------------ .../fourslash/moveToFile_refactorAvailable1.ts | 8 ++++---- .../fourslash/moveToFile_refactorAvailable2.ts | 10 +++++----- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 46ec280e29836..15178cb3035bb 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -11,7 +11,6 @@ import { BinaryExpression, BindingElement, BindingName, - BlockLike, CallExpression, canHaveDecorators, canHaveModifiers, @@ -41,6 +40,7 @@ import { filter, find, FindAllReferences, + findAncestor, findIndex, findLast, firstDefined, @@ -170,11 +170,12 @@ registerRefactor(refactorNameForMoveToFile, { if (!interactiveRefactorArguments) { return emptyArray; } + // If the start/end nodes of the selection are inside a block like node do not show the `Move to file` code action if (context.endPosition !== undefined) { const file = context.file; - const startNodeAncestor = getBlockLikeAncestor(getTokenAtPosition(file, context.startPosition)); - const endNodeAncestor = getBlockLikeAncestor(getTokenAtPosition(file, context.endPosition)); - if (!isSourceFile(startNodeAncestor) && !isSourceFile(endNodeAncestor)) { + const startNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike); + const endNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike) + if (startNodeAncestor && !isSourceFile(startNodeAncestor) && endNodeAncestor && !isSourceFile(endNodeAncestor)) { return emptyArray; } } @@ -285,14 +286,6 @@ function getNewStatementsAndRemoveFromOldFile( ]; } -function getBlockLikeAncestor(node: Node): BlockLike { - let currentNode = node; - while (!isBlockLike(currentNode)) { - currentNode = currentNode.parent; - } - return currentNode; -} - function getTargetFileImportsAndAddExportInOldFile( oldFile: SourceFile, targetFile: string, diff --git a/tests/cases/fourslash/moveToFile_refactorAvailable1.ts b/tests/cases/fourslash/moveToFile_refactorAvailable1.ts index 1e4b02b3b3462..3681be5cf49b6 100644 --- a/tests/cases/fourslash/moveToFile_refactorAvailable1.ts +++ b/tests/cases/fourslash/moveToFile_refactorAvailable1.ts @@ -9,10 +9,10 @@ goTo.select("a", "b"); verify.not.refactorAvailable("Move to file", -undefined, -undefined, -undefined, +/*actionName*/ undefined, +/*actionDescription*/ undefined, +/*kind*/ undefined, { allowTextChangesInNewFiles : true }, -true); +/*includeInteractiveActions*/ true); diff --git a/tests/cases/fourslash/moveToFile_refactorAvailable2.ts b/tests/cases/fourslash/moveToFile_refactorAvailable2.ts index 2da31df999bab..164b41753d063 100644 --- a/tests/cases/fourslash/moveToFile_refactorAvailable2.ts +++ b/tests/cases/fourslash/moveToFile_refactorAvailable2.ts @@ -9,12 +9,12 @@ /////*b*/ goTo.select("a", "b"); -verify.refactorAvailable("Move to file", -undefined, -undefined, -undefined, +verify.not.refactorAvailable("Move to file", +/*actionName*/ undefined, +/*actionDescription*/ undefined, +/*kind*/ undefined, { allowTextChangesInNewFiles : true }, -true); +/*includeInteractiveActions*/ true); From 154fcc569b55bab0965b628bc56021a1fe2a7d71 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 16 Feb 2024 09:34:27 +0100 Subject: [PATCH 21/24] adding a reason also into the comment --- src/services/refactors/moveToFile.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 15178cb3035bb..6b025054d12f5 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -170,7 +170,8 @@ registerRefactor(refactorNameForMoveToFile, { if (!interactiveRefactorArguments) { return emptyArray; } - // If the start/end nodes of the selection are inside a block like node do not show the `Move to file` code action + /** If the start/end nodes of the selection are inside a block like node do not show the `Move to file` code action + * This condition is used in order to show less often the `Move to file` code action */ if (context.endPosition !== undefined) { const file = context.file; const startNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike); From c6b461ceedeec27cd76d6a7389e59a966d5dceee Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 16 Feb 2024 09:35:20 +0100 Subject: [PATCH 22/24] adding a semi colon --- src/services/refactors/moveToFile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 6b025054d12f5..7864a057828a9 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -175,7 +175,7 @@ registerRefactor(refactorNameForMoveToFile, { if (context.endPosition !== undefined) { const file = context.file; const startNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike); - const endNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike) + const endNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike); if (startNodeAncestor && !isSourceFile(startNodeAncestor) && endNodeAncestor && !isSourceFile(endNodeAncestor)) { return emptyArray; } From 22c8fb34f3667f99e66c4bf688cb6ee0ef37501a Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 16 Feb 2024 10:33:58 +0100 Subject: [PATCH 23/24] changing to fetching the token at the end position --- src/services/refactors/moveToFile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 7864a057828a9..03a9cfda7668b 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -175,7 +175,7 @@ registerRefactor(refactorNameForMoveToFile, { if (context.endPosition !== undefined) { const file = context.file; const startNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike); - const endNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike); + const endNodeAncestor = findAncestor(getTokenAtPosition(file, context.endPosition), isBlockLike); if (startNodeAncestor && !isSourceFile(startNodeAncestor) && endNodeAncestor && !isSourceFile(endNodeAncestor)) { return emptyArray; } From dcf2ffb7822de827c13df4593d451c0fd5f870cd Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 16 Feb 2024 10:37:49 +0100 Subject: [PATCH 24/24] correcting the test --- tests/cases/fourslash/moveToFile_refactorAvailable2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/fourslash/moveToFile_refactorAvailable2.ts b/tests/cases/fourslash/moveToFile_refactorAvailable2.ts index 164b41753d063..7353c76cb0cff 100644 --- a/tests/cases/fourslash/moveToFile_refactorAvailable2.ts +++ b/tests/cases/fourslash/moveToFile_refactorAvailable2.ts @@ -9,7 +9,7 @@ /////*b*/ goTo.select("a", "b"); -verify.not.refactorAvailable("Move to file", +verify.refactorAvailable("Move to file", /*actionName*/ undefined, /*actionDescription*/ undefined, /*kind*/ undefined,