Skip to content

Commit 11d1e23

Browse files
committed
feat: add out of the box keybinding to unleash TypeScript's mechanism of overriding variable name in string & comments in renaming files (ctrl+shift+enter) 🚀
1 parent bc0d31a commit 11d1e23

File tree

6 files changed

+97
-1
lines changed

6 files changed

+97
-1
lines changed

README.MD

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,34 @@ Some settings examples:
228228
> Note: changeSorting might not preserve sorting of other existing suggestions which not defined by rules, there is WIP
229229
> Also I'm thinking of making it learn and syncing of most-used imports automatically
230230
231+
## Rename Features
232+
233+
There is builtin mechanism to rename variable occurrences in strings & comments, it is disabled in VS Code without a way to enable it.
234+
235+
However this extension also has builtin keybinding `Ctrl+Shift+Enter` that can be pressed when input box is visible to enable aforementioned behavior for renaming with preview.
236+
237+
But note renaming in strings & comments will happen only for files in which variable is actually referenced.
238+
239+
You can add this to `keybindings.json` to disable previewing before renaming:
240+
241+
```js
242+
{
243+
"key": "ctrl+shift+enter",
244+
"command": "tsEssentialPlugins.acceptRenameWithParams",
245+
"args": {
246+
"strings": true,
247+
"comments": true,
248+
// "preview": true // true by default
249+
// "alias": true // you can also specify here wether to introduce alias on rename if applicable (overriding global setting)
250+
},
251+
"when": "renameInputVisible"
252+
}
253+
```
254+
255+
Another options that is accepted is
256+
257+
> Note: VS Code has builtin setting to disable introducing aliases (e.g. for imports & object properties)
258+
231259
## Special Commands List
232260

233261
### Go to / Select Nodes by Kind

package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,19 @@
5353
"category": "TS Essentials"
5454
}
5555
],
56+
"keybindings": [
57+
{
58+
"key": "ctrl+shift+enter",
59+
"mac": "cmd+shift+enter",
60+
"command": "tsEssentialPlugins.acceptRenameWithParams",
61+
"args": {
62+
"strings": true,
63+
"comments": true,
64+
"preview": true
65+
},
66+
"when": "renameInputVisible && editorLangId =~ /javascript|javascriptreact|typescript|typescriptreact|vue/"
67+
}
68+
],
5669
"typescriptServerPlugins": [
5770
{
5871
"name": "typescript-essential-plugins",

src/specialCommands.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,25 @@ export default () => {
265265
await vscode.workspace.applyEdit(edit)
266266
})
267267

268+
registerExtensionCommand('acceptRenameWithParams' as any, async (_, { preview = false, comments = null, strings = null, alias = null } = {}) => {
269+
const editor = vscode.window.activeTextEditor
270+
if (!editor) return
271+
const {
272+
document,
273+
selection: { active: position },
274+
} = editor
275+
await sendCommand<RequestOptionsTypes['acceptRenameWithParams']>('acceptRenameWithParams', {
276+
document,
277+
position,
278+
inputOptions: {
279+
alias,
280+
comments,
281+
strings,
282+
} satisfies RequestOptionsTypes['acceptRenameWithParams'],
283+
})
284+
await vscode.commands.executeCommand(preview ? 'acceptRenameInputWithPreview' : 'acceptRenameInput')
285+
})
286+
268287
// its actually a code action, but will be removed from there soon
269288
vscode.languages.registerCodeActionsProvider(defaultJsSupersetLangsWithVue, {
270289
async provideCodeActions(document, range, context, token) {

typescript/src/decorateProxy.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getCompletionsAtPosition, PrevCompletionMap, PrevCompletionsAdditionalData } from './completionsAtPosition'
2-
import { TriggerCharacterCommand } from './ipcTypes'
2+
import { RequestOptionsTypes, TriggerCharacterCommand } from './ipcTypes'
33
import { getNavTreeItems } from './getPatchedNavTree'
44
import decorateCodeActions from './codeActions/decorateProxy'
55
import decorateSemanticDiagnostics from './semanticDiagnostics'
@@ -25,6 +25,10 @@ export const getInitialProxy = (languageService: ts.LanguageService, proxy = Obj
2525
return proxy
2626
}
2727

28+
export const overrideRequestPreferences = {
29+
rename: undefined as undefined | RequestOptionsTypes['acceptRenameWithParams'],
30+
}
31+
2832
export const decorateLanguageService = (
2933
info: ts.server.PluginCreateInfo,
3034
existingProxy: ts.LanguageService | undefined,
@@ -109,6 +113,23 @@ export const decorateLanguageService = (
109113
decorateReferences(proxy, languageService, c)
110114
decorateDocumentHighlights(proxy, languageService, c)
111115
decorateWorkspaceSymbolSearch(proxy, languageService, c, languageServiceHost)
116+
proxy.findRenameLocations = (fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename) => {
117+
if (overrideRequestPreferences.rename) {
118+
try {
119+
const { comments, strings, alias } = overrideRequestPreferences.rename
120+
return languageService.findRenameLocations(
121+
fileName,
122+
position,
123+
strings ?? findInStrings,
124+
comments ?? findInComments,
125+
alias ?? providePrefixAndSuffixTextForRename,
126+
)
127+
} finally {
128+
overrideRequestPreferences.rename = undefined
129+
}
130+
}
131+
return languageService.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename)
132+
}
112133

113134
if (pluginSpecificSyntaxServerConfigCheck) {
114135
if (!__WEB__) {

typescript/src/ipcTypes.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const triggerCharacterCommands = [
1010
'getRangeOfSpecialValue',
1111
'turnArrayIntoObject',
1212
'getFixAllEdits',
13+
'acceptRenameWithParams',
1314
] as const
1415

1516
export type TriggerCharacterCommand = typeof triggerCharacterCommands[number]
@@ -57,6 +58,11 @@ export type RequestOptionsTypes = {
5758
range: [number, number]
5859
selectedKeyName?: string
5960
}
61+
acceptRenameWithParams: {
62+
comments: boolean
63+
strings: boolean
64+
alias: boolean
65+
}
6066
}
6167

6268
// export type EmmetResult = {

typescript/src/specialCommands/handle.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { compact } from '@zardoy/utils'
22
import postfixesAtPosition from '../completions/postfixesAtPosition'
3+
import { overrideRequestPreferences } from '../decorateProxy'
34
import { NodeAtPositionResponse, RequestOptionsTypes, RequestResponseTypes, TriggerCharacterCommand, triggerCharacterCommands } from '../ipcTypes'
45
import { findChildContainingExactPosition, findChildContainingPosition, getNodePath } from '../utils'
56
import getEmmetCompletions from './emmet'
@@ -181,6 +182,14 @@ export default (
181182
return
182183
}
183184
}
185+
if (specialCommand === 'acceptRenameWithParams') {
186+
changeType<RequestOptionsTypes['acceptRenameWithParams']>(specialCommandArg)
187+
overrideRequestPreferences.rename = specialCommandArg
188+
return {
189+
entries: [],
190+
typescriptEssentialsResponse: undefined,
191+
}
192+
}
184193
if (specialCommand === 'pickAndInsertFunctionArguments') {
185194
// const sourceFile = (info.languageService as ReturnType<typeof tsFull['createLanguageService']>).getProgram()!.getSourceFile(fileName)!
186195
// if (!sourceFile.identifiers) throw new Error('TS: no exposed identifiers map')

0 commit comments

Comments
 (0)