From 432aac18f1c2929872ebd475a77145195a22c965 Mon Sep 17 00:00:00 2001 From: Vitaly Date: Wed, 9 Aug 2023 23:29:30 +0300 Subject: [PATCH] [typescript] Better paths matching for move to existing file quickpick (#181231) * Better paths matching for move to existing file quickpick * fix resolving selected item * fix: select file dialog point to existing file * skip computing if use coalesce * Improve typings --------- Co-authored-by: Matt Bierner --- .../src/languageFeatures/refactor.ts | 103 ++++++++++++------ 1 file changed, 68 insertions(+), 35 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/refactor.ts b/extensions/typescript-language-features/src/languageFeatures/refactor.ts index a99b92685fc..ae36fbffb22 100644 --- a/extensions/typescript-language-features/src/languageFeatures/refactor.ts +++ b/extensions/typescript-language-features/src/languageFeatures/refactor.ts @@ -175,47 +175,80 @@ class MoveToFileRefactorCommand implements Command { if (response.type !== 'response' || !response.body) { return; } + const body = response.body; - const selectExistingFileItem: vscode.QuickPickItem = { - label: vscode.l10n.t("Select existing file..."), - }; - const selectNewFileItem: vscode.QuickPickItem = { - label: vscode.l10n.t("Enter new file path..."), - }; - - type DestinationItem = vscode.QuickPickItem & { readonly file: string }; + type DestinationItem = vscode.QuickPickItem & { readonly file?: string }; + const selectExistingFileItem: vscode.QuickPickItem = { label: vscode.l10n.t("Select existing file...") }; + const selectNewFileItem: vscode.QuickPickItem = { label: vscode.l10n.t("Enter new file path...") }; const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri); - const destinationItems = response.body.files.map((file): DestinationItem => { - const uri = this.client.toResource(file); - const parentDir = Utils.dirname(uri); + const quickPick = vscode.window.createQuickPick(); + quickPick.ignoreFocusOut = true; - let description; - if (workspaceFolder) { - if (uri.scheme === Schemes.file) { - description = path.relative(workspaceFolder.uri.fsPath, parentDir.fsPath); - } else { - description = path.posix.relative(workspaceFolder.uri.path, parentDir.path); - } - } else { - description = parentDir.fsPath; + // true so we don't skip computing in the first call + let quickPickInRelativeMode = true; + const updateItems = () => { + const relativeQuery = ['./', '../'].find(str => quickPick.value.startsWith(str)); + if (quickPickInRelativeMode === false && !!relativeQuery === false) { + return; } + quickPickInRelativeMode = !!relativeQuery; + const destinationItems = body.files.map((file): DestinationItem | undefined => { + const uri = this.client.toResource(file); + const parentDir = Utils.dirname(uri); + const filename = Utils.basename(uri); - return { - file, - label: Utils.basename(uri), - description, - }; - }); + let description: string | undefined; + if (workspaceFolder) { + if (uri.scheme === Schemes.file) { + description = path.relative(workspaceFolder.uri.fsPath, parentDir.fsPath); + } else { + description = path.posix.relative(workspaceFolder.uri.path, parentDir.path); + } + if (relativeQuery) { + const convertRelativePath = (str: string) => { + return !str.startsWith('../') ? `./${str}` : str; + }; - const picked = await vscode.window.showQuickPick([ - selectExistingFileItem, - selectNewFileItem, - { label: vscode.l10n.t("Destination Files"), kind: vscode.QuickPickItemKind.Separator }, - ...destinationItems - ], { - title: vscode.l10n.t("Move to File"), - placeHolder: vscode.l10n.t("Select move destination"), + const relativePath = convertRelativePath(path.relative(path.dirname(document.uri.fsPath), uri.fsPath)); + if (!relativePath.startsWith(relativeQuery)) { + return; + } + description = relativePath; + } + } else { + description = parentDir.fsPath; + } + + return { + file, + label: Utils.basename(uri), + description: relativeQuery ? description : path.join(description, filename), + }; + }); + quickPick.items = [ + selectExistingFileItem, + selectNewFileItem, + { label: vscode.l10n.t("Destination Files"), kind: vscode.QuickPickItemKind.Separator }, + ...coalesce(destinationItems) + ]; + }; + quickPick.title = vscode.l10n.t("Move to File"); + quickPick.placeholder = vscode.l10n.t("Enter file path"); + quickPick.matchOnDescription = true; + quickPick.onDidChangeValue(updateItems); + updateItems(); + + const picked = await new Promise(resolve => { + quickPick.onDidAccept(() => { + resolve(quickPick.selectedItems[0]); + quickPick.dispose(); + }); + quickPick.onDidHide(() => { + resolve(undefined); + quickPick.dispose(); + }); + quickPick.show(); }); if (!picked) { return; @@ -236,7 +269,7 @@ class MoveToFileRefactorCommand implements Command { }); return picked ? this.client.toTsFilePath(picked) : undefined; } else { - return (picked as DestinationItem).file; + return picked.file; } } }