From 7b1168660ac0bb2a7addf8a3cffc5b2045930844 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 20 Apr 2022 18:07:47 -0700 Subject: [PATCH] Fix resolving of links on rename We should resolve relative to the file the rename is triggered in --- .../src/languageFeatures/rename.ts | 6 +-- .../src/test/rename.test.ts | 48 +++++++++++++++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/extensions/markdown-language-features/src/languageFeatures/rename.ts b/extensions/markdown-language-features/src/languageFeatures/rename.ts index a8ce8ebe3af..8a80906fbad 100644 --- a/extensions/markdown-language-features/src/languageFeatures/rename.ts +++ b/extensions/markdown-language-features/src/languageFeatures/rename.ts @@ -135,20 +135,20 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide } else if (triggerRef.kind === 'header' || (triggerRef.kind === 'link' && triggerRef.link.source.fragmentRange?.contains(position) && (triggerRef.link.kind === 'definition' || triggerRef.link.kind === 'link' && triggerRef.link.href.kind === 'internal'))) { return this.renameFragment(allRefsInfo, newName); } else if (triggerRef.kind === 'link' && !triggerRef.link.source.fragmentRange?.contains(position) && triggerRef.link.kind === 'link' && triggerRef.link.href.kind === 'internal') { - return this.renameFilePath(triggerRef.link.href, allRefsInfo, newName); + return this.renameFilePath(triggerRef.link.source.resource, triggerRef.link.href, allRefsInfo, newName); } return undefined; } - private async renameFilePath(triggerHref: InternalHref, allRefsInfo: MdReferencesResponse, newName: string): Promise { + private async renameFilePath(triggerDocument: vscode.Uri, triggerHref: InternalHref, allRefsInfo: MdReferencesResponse, newName: string): Promise { const edit = new vscode.WorkspaceEdit(); const fileRenames: MdFileRenameEdit[] = []; const targetDoc = await tryFindMdDocumentForLink(triggerHref, this.workspaceContents); const targetUri = targetDoc?.uri ?? triggerHref.path; - let rawNewFilePath = resolveDocumentLink(newName, triggerHref.path); + const rawNewFilePath = resolveDocumentLink(newName, triggerDocument); let resolvedNewFilePath = rawNewFilePath; if (!URI.Utils.extname(resolvedNewFilePath)) { // If the newly entered path doesn't have a file extension but the original file did diff --git a/extensions/markdown-language-features/src/test/rename.test.ts b/extensions/markdown-language-features/src/test/rename.test.ts index e24405012af..e937c76574b 100644 --- a/extensions/markdown-language-features/src/test/rename.test.ts +++ b/extensions/markdown-language-features/src/test/rename.test.ts @@ -486,21 +486,25 @@ suite('markdown: rename', () => { const uri1 = workspacePath('sub', 'doc.md'); const doc1 = new InMemoryDocument(uri1, joinLines( `[text](./doc.md)`, + `[ref]: ./doc.md`, )); const uri2 = workspacePath('doc2.md'); const doc2 = new InMemoryDocument(uri2, joinLines( `[text](./sub/doc.md)`, + `[ref]: ./sub/doc.md`, )); const uri3 = workspacePath('sub2', 'doc3.md'); const doc3 = new InMemoryDocument(uri3, joinLines( `[text](../sub/doc.md)`, + `[ref]: ../sub/doc.md`, )); const uri4 = workspacePath('sub2', 'doc4.md'); const doc4 = new InMemoryDocument(uri4, joinLines( `[text](/sub/doc.md)`, + `[ref]: /sub/doc.md`, )); const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), './new/new-doc.md', new InMemoryWorkspaceMarkdownDocuments([ @@ -510,13 +514,49 @@ suite('markdown: rename', () => { originalUri: uri1, newUri: workspacePath('sub', 'new', 'new-doc.md'), }, { - uri: uri1, edits: [new vscode.TextEdit(new vscode.Range(0, 7, 0, 15), './new/new-doc.md')] + uri: uri1, edits: [ + new vscode.TextEdit(new vscode.Range(0, 7, 0, 15), './new/new-doc.md'), + new vscode.TextEdit(new vscode.Range(1, 7, 1, 15), './new/new-doc.md'), + ] }, { - uri: uri2, edits: [new vscode.TextEdit(new vscode.Range(0, 7, 0, 19), './sub/new/new-doc.md')] + uri: uri2, edits: [ + new vscode.TextEdit(new vscode.Range(0, 7, 0, 19), './sub/new/new-doc.md'), + new vscode.TextEdit(new vscode.Range(1, 7, 1, 19), './sub/new/new-doc.md'), + ] }, { - uri: uri3, edits: [new vscode.TextEdit(new vscode.Range(0, 7, 0, 20), '../sub/new/new-doc.md')] + uri: uri3, edits: [ + new vscode.TextEdit(new vscode.Range(0, 7, 0, 20), '../sub/new/new-doc.md'), + new vscode.TextEdit(new vscode.Range(1, 7, 1, 20), '../sub/new/new-doc.md'), + ] }, { - uri: uri4, edits: [new vscode.TextEdit(new vscode.Range(0, 7, 0, 18), '/sub/new/new-doc.md')] + uri: uri4, edits: [ + new vscode.TextEdit(new vscode.Range(0, 7, 0, 18), '/sub/new/new-doc.md'), + new vscode.TextEdit(new vscode.Range(1, 7, 1, 18), '/sub/new/new-doc.md'), + ] + }); + }); + + test('Path rename should resolve on links without prefix', async () => { + const uri1 = workspacePath('sub', 'doc.md'); + const doc1 = new InMemoryDocument(uri1, joinLines( + `![text](images/cat.gif)`, + )); + + const uri2 = workspacePath('doc2.md'); + const doc2 = new InMemoryDocument(uri2, joinLines( + `![text](sub/images/cat.gif)`, + )); + + const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), 'img/cat.gif', new InMemoryWorkspaceMarkdownDocuments([ + doc1, doc2, + ])); + assertEditsEqual(edit!, { + originalUri: workspacePath('sub', 'images', 'cat.gif'), + newUri: workspacePath('sub', 'img', 'cat.gif'), + }, { + uri: uri1, edits: [new vscode.TextEdit(new vscode.Range(0, 8, 0, 22), 'img/cat.gif')] + }, { + uri: uri2, edits: [new vscode.TextEdit(new vscode.Range(0, 8, 0, 26), 'sub/img/cat.gif')] }); });