-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Expand file tree
/
Copy pathmoveToNewFile.ts
More file actions
88 lines (82 loc) · 4.32 KB
/
moveToNewFile.ts
File metadata and controls
88 lines (82 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import {
ApplicableRefactorInfo,
codefix,
createFutureSourceFile,
Debug,
Diagnostics,
emptyArray,
findAncestor,
getLineAndCharacterOfPosition,
getLocaleSpecificMessage,
getTokenAtPosition,
hostGetCanonicalFileName,
isBlockLike,
isSourceFile,
LanguageServiceHost,
last,
ModuleKind,
Program,
RefactorContext,
RefactorEditInfo,
SourceFile,
textChanges,
UserPreferences,
} from "../_namespaces/ts.js";
import {
addNewFileToTsconfig,
createNewFileName,
getNewStatementsAndRemoveFromOldFile,
getStatementsToMove,
getUsageInfo,
registerRefactor,
ToMove,
} from "../_namespaces/ts.refactor.js";
const refactorName = "Move to a new file";
const description = getLocaleSpecificMessage(Diagnostics.Move_to_a_new_file);
const moveToNewFileAction = {
name: refactorName,
description,
kind: "refactor.move.newFile",
};
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 = {
start: { line: getLineAndCharacterOfPosition(file, statements.all[0].getStart(file)).line, offset: getLineAndCharacterOfPosition(file, statements.all[0].getStart(file)).character },
end: { line: getLineAndCharacterOfPosition(file, last(statements.all).end).line, offset: getLineAndCharacterOfPosition(file, last(statements.all).end).character },
};
return [{ name: refactorName, description, actions: [{ ...moveToNewFileAction, range: affectedTextRange }] }];
}
if (context.preferences.provideRefactorNotApplicableReason) {
return [{ name: refactorName, description, actions: [{ ...moveToNewFileAction, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Selection_is_not_a_valid_statement_or_statements) }] }];
}
return emptyArray;
},
getEditsForAction: function getRefactorEditsToMoveToNewFile(context, actionName): RefactorEditInfo {
Debug.assert(actionName === refactorName, "Wrong refactor invoked");
const statements = Debug.checkDefined(getStatementsToMove(context));
const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, statements, t, context.host, context, context.preferences));
return { edits, renameFilename: undefined, renameLocation: undefined };
},
});
function doChange(oldFile: SourceFile, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, context: RefactorContext, preferences: UserPreferences): void {
const checker = program.getTypeChecker();
const usage = getUsageInfo(oldFile, toMove.all, checker);
const newFilename = createNewFileName(oldFile, program, host, toMove);
const newSourceFile = createFutureSourceFile(newFilename, oldFile.externalModuleIndicator ? ModuleKind.ESNext : oldFile.commonJsModuleIndicator ? ModuleKind.CommonJS : undefined, program, host);
const importAdderForOldFile = codefix.createImportAdder(oldFile, context.program, context.preferences, context.host);
const importAdderForNewFile = codefix.createImportAdder(newSourceFile, context.program, context.preferences, context.host);
getNewStatementsAndRemoveFromOldFile(oldFile, newSourceFile, usage, changes, toMove, program, host, preferences, importAdderForNewFile, importAdderForOldFile);
addNewFileToTsconfig(program, changes, oldFile.fileName, newFilename, hostGetCanonicalFileName(host));
}