11import lodashGet from 'lodash.get'
2+ import { camelCase } from 'change-case'
3+ import _ from 'lodash'
24import { getCompletionsAtPosition , PrevCompletionMap , PrevCompletionsAdditionalData } from './completionsAtPosition'
35import { RequestOptionsTypes , TriggerCharacterCommand } from './ipcTypes'
46import { getNavTreeItems } from './getPatchedNavTree'
@@ -15,6 +17,7 @@ import decorateWorkspaceSymbolSearch from './workspaceSymbolSearch'
1517import decorateFormatFeatures from './decorateFormatFeatures'
1618import libDomPatching from './libDomPatching'
1719import decorateSignatureHelp from './decorateSignatureHelp'
20+ import { approveCast , findChildContainingExactPosition } from './utils'
1821
1922/** @internal */
2023export 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