Skip to content

Commit a45ad97

Browse files
committed
feat: renameImportNameOfFileRename - disabled by default, but super recommended
1 parent 2bde27c commit a45ad97

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

src/configurationType.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,13 @@ export type Configuration = {
205205
* @default true
206206
* */
207207
'removeCodeFixes.enable': boolean
208+
/**
209+
* Also rename name of default or namespace import on refactor caused by file move / rename
210+
* Probably will be enabled by default in future
211+
* @default false
212+
* @recommended
213+
*/
214+
renameImportNameOfFileRename: boolean
208215
/**
209216
* Additional file extension to include in completions (suggestions)
210217
*

typescript/src/decorateProxy.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import lodashGet from 'lodash.get'
2+
import { camelCase } from 'change-case'
3+
import _ from 'lodash'
24
import { getCompletionsAtPosition, PrevCompletionMap, PrevCompletionsAdditionalData } from './completionsAtPosition'
35
import { RequestOptionsTypes, TriggerCharacterCommand } from './ipcTypes'
46
import { getNavTreeItems } from './getPatchedNavTree'
@@ -15,6 +17,7 @@ import decorateWorkspaceSymbolSearch from './workspaceSymbolSearch'
1517
import decorateFormatFeatures from './decorateFormatFeatures'
1618
import libDomPatching from './libDomPatching'
1719
import decorateSignatureHelp from './decorateSignatureHelp'
20+
import { approveCast, findChildContainingExactPosition } from './utils'
1821

1922
/** @internal */
2023
export const thisPluginMarker = '__essentialPluginsMarker__'
@@ -46,6 +49,49 @@ export const decorateLanguageService = (
4649
let prevCompletionsMap: PrevCompletionMap
4750
let prevCompletionsAdittionalData: PrevCompletionsAdditionalData
4851

52+
proxy.getEditsForFileRename = (oldFilePath, newFilePath, formatOptions, preferences) => {
53+
let edits = languageService.getEditsForFileRename(oldFilePath, newFilePath, formatOptions, preferences)
54+
if (c('renameImportNameOfFileRename')) {
55+
const predictedNameFromPath = (p: string) => camelCase(p.split(/[/\\]/g).pop()!.replace(/\..+/, ''))
56+
const oldPredictedName = predictedNameFromPath(oldFilePath)
57+
const newPredictedName = predictedNameFromPath(newFilePath)
58+
for (const edit of edits) {
59+
const possiblyAddRename = (identifier: ts.Identifier | undefined) => {
60+
if (identifier?.text !== oldPredictedName) return
61+
const sourceFile = languageService.getProgram()!.getSourceFile(edit.fileName)!
62+
const newRenameEdits = proxy.findRenameLocations(edit.fileName, identifier.pos, false, false) ?? []
63+
if (!newRenameEdits) return
64+
// maybe cancel symbol rename on collision instead?
65+
const newInsertName = tsFull.getUniqueName(newPredictedName, sourceFile as any)
66+
const addEdits = Object.entries(_.groupBy(newRenameEdits, ({ fileName }) => fileName)).map(
67+
([fileName, changes]): ts.FileTextChanges => ({
68+
fileName,
69+
textChanges: changes.map(
70+
({ prefixText = '', suffixText = '', textSpan }): ts.TextChange => ({
71+
newText: prefixText + newInsertName + suffixText,
72+
span: textSpan,
73+
}),
74+
),
75+
}),
76+
)
77+
edits = [...edits, ...addEdits]
78+
}
79+
for (const textChange of edit.textChanges) {
80+
const node = findChildContainingExactPosition(languageService.getProgram()!.getSourceFile(edit.fileName)!, textChange.span.start)
81+
if (!node) continue
82+
if (node && ts.isStringLiteral(node) && ts.isImportDeclaration(node.parent) && node.parent.importClause) {
83+
const { importClause } = node.parent
84+
possiblyAddRename(importClause?.name)
85+
if (approveCast(importClause.namedBindings, ts.isNamespaceImport)) {
86+
possiblyAddRename(importClause.namedBindings.name)
87+
}
88+
}
89+
}
90+
}
91+
}
92+
return edits
93+
}
94+
4995
proxy.getCompletionsAtPosition = (fileName, position, options, formatOptions) => {
5096
if (options?.triggerCharacter && typeof options.triggerCharacter !== 'string') {
5197
return languageService.getCompletionsAtPosition(fileName, position, options)

0 commit comments

Comments
 (0)