diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts
index dea0ebc4c43e1..f060940454132 100644
--- a/src/services/refactors/moveToFile.ts
+++ b/src/services/refactors/moveToFile.ts
@@ -175,7 +175,7 @@ registerRefactor(refactorNameForMoveToFile, {
}
/** 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) {
+ if (context.triggerReason === "implicit" && context.endPosition !== undefined) {
const startNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike);
const endNodeAncestor = findAncestor(getTokenAtPosition(file, context.endPosition), isBlockLike);
if (startNodeAncestor && !isSourceFile(startNodeAncestor) && endNodeAncestor && !isSourceFile(endNodeAncestor)) {
diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts
index 2665239e10483..37cdd35d07019 100644
--- a/src/services/refactors/moveToNewFile.ts
+++ b/src/services/refactors/moveToNewFile.ts
@@ -5,9 +5,13 @@ import {
Debug,
Diagnostics,
emptyArray,
+ findAncestor,
getLineAndCharacterOfPosition,
getLocaleSpecificMessage,
+ getTokenAtPosition,
hostGetCanonicalFileName,
+ isBlockLike,
+ isSourceFile,
LanguageServiceHost,
last,
ModuleKind,
@@ -40,6 +44,16 @@ registerRefactor(refactorName, {
kinds: [moveToNewFileAction.kind],
getAvailableActions: function getRefactorActionsToMoveToNewFile(context): readonly ApplicableRefactorInfo[] {
const statements = getStatementsToMove(context);
+
+ const file = context.file;
+ if (context.triggerReason === "implicit" && context.endPosition !== undefined) {
+ const startNodeAncestor = findAncestor(getTokenAtPosition(file, context.startPosition), isBlockLike);
+ const endNodeAncestor = findAncestor(getTokenAtPosition(file, context.endPosition), isBlockLike);
+ if (startNodeAncestor && !isSourceFile(startNodeAncestor) && endNodeAncestor && !isSourceFile(endNodeAncestor)) {
+ return emptyArray;
+ }
+ }
+
if (context.preferences.allowTextChangesInNewFiles && statements) {
const file = context.file;
const affectedTextRange = {
diff --git a/tests/cases/fourslash/moveToNewFile_prologueDirectives4.ts b/tests/cases/fourslash/moveToNewFile_prologueDirectives4.ts
index d30090bbe3df3..bfadbfd3e2e7a 100644
--- a/tests/cases/fourslash/moveToNewFile_prologueDirectives4.ts
+++ b/tests/cases/fourslash/moveToNewFile_prologueDirectives4.ts
@@ -5,15 +5,4 @@
//// [|"use strict";|]
////}
-verify.moveToNewFile({
- newFileContents: {
- "/a.ts":
-``,
-
- "/foo.ts":
-`function foo() {
- "use strict";
-}
-`,
- },
-});
+verify.noMoveToNewFile();
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailable1.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailable1.ts
new file mode 100644
index 0000000000000..ab0689f481304
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailable1.ts
@@ -0,0 +1,18 @@
+///
+
+////namespace ns {
+//// /*a*/export function fn() {
+//// }
+//// fn();
+//// /*b*/
+////}
+
+goTo.select("a", "b");
+verify.not.refactorAvailable("Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailable2.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailable2.ts
new file mode 100644
index 0000000000000..3b191a7c6df85
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailable2.ts
@@ -0,0 +1,20 @@
+///
+
+/////*a*/
+////namespace ns {
+//// export function fn() {
+//// }
+//// fn();
+////}
+/////*b*/
+
+goTo.select("a", "b");
+verify.refactorAvailable("Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);
+
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit1.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit1.ts
new file mode 100644
index 0000000000000..cb552982f9c49
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit1.ts
@@ -0,0 +1,19 @@
+///
+
+
+//// export /*a*//*b*/function fn() {
+//// console.log('Hello')
+//// }
+//// fn();
+
+
+
+goTo.select("a", "b");
+verify.refactorAvailableForTriggerReason("implicit", "Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit2.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit2.ts
new file mode 100644
index 0000000000000..7391bbe48ef70
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit2.ts
@@ -0,0 +1,16 @@
+///
+
+//// export function fn(){
+//// console.log('Hello')/*a*//*b*/
+//// }
+//// fn();
+
+goTo.select("a", "b");
+verify.not.refactorAvailableForTriggerReason("implicit", "Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit3.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit3.ts
new file mode 100644
index 0000000000000..d1b5606214842
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailableImplicit3.ts
@@ -0,0 +1,23 @@
+///
+
+
+////class ns /*a*//*b*/extends ap{
+//// constructor() {}
+////
+//// export function fn() {
+//// console.log("Hello");
+//// }
+//// fn();
+////
+////}
+
+
+goTo.select("a", "b");
+verify.refactorAvailableForTriggerReason("implicit", "Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked1.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked1.ts
new file mode 100644
index 0000000000000..2e360588fb510
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked1.ts
@@ -0,0 +1,16 @@
+///
+
+//// export function fn(){
+//// console.log('Hello')/*a*//*b*/
+//// }
+//// fn();
+
+goTo.select("a", "b");
+verify.refactorAvailableForTriggerReason("invoked", "Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked2.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked2.ts
new file mode 100644
index 0000000000000..904e6cf96f351
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked2.ts
@@ -0,0 +1,23 @@
+///
+
+
+////class ns extends ap{
+//// constructor() {}
+////
+//// export function fn() {
+//// console.log("Hello"); /*a*//*b*/
+//// }
+//// fn();
+////
+////}
+
+
+goTo.select("a", "b");
+verify.refactorAvailableForTriggerReason("invoked", "Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);
diff --git a/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked3.ts b/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked3.ts
new file mode 100644
index 0000000000000..7476fe09db6e9
--- /dev/null
+++ b/tests/cases/fourslash/moveToNewFile_refactorAvailableInvoked3.ts
@@ -0,0 +1,20 @@
+///
+
+
+
+//// export function fn() {
+//// /*a*/console.log("Hello"); /*b*/
+//// }
+//// fn();
+
+
+
+goTo.select("a", "b");
+verify.refactorAvailableForTriggerReason("invoked", "Move to a new file",
+/*actionName*/ undefined,
+/*actionDescription*/ undefined,
+/*kind*/ undefined,
+ {
+ allowTextChangesInNewFiles: true
+ },
+/*includeInteractiveActions*/ true);