mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
Fixing rename to use correct file paths relative to containing files
This commit is contained in:
parent
0610f195fb
commit
b438e8438d
|
@ -2,15 +2,16 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as URI from 'vscode-uri';
|
||||
import { Slugifier } from '../slugify';
|
||||
import { Disposable } from '../util/dispose';
|
||||
import { resolveDocumentLink } from '../util/openDocumentLink';
|
||||
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
|
||||
import { InternalHref } from './documentLinkProvider';
|
||||
import { MdHeaderReference, MdLinkReference, MdReference, MdReferencesProvider, tryFindMdDocumentForLink } from './references';
|
||||
import * as URI from 'vscode-uri';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
|
@ -147,25 +148,37 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide
|
|||
const targetDoc = await tryFindMdDocumentForLink(triggerHref, this.workspaceContents);
|
||||
const targetUri = targetDoc?.uri ?? triggerHref.path;
|
||||
|
||||
let newFilePath = resolveDocumentLink(newName, triggerHref.path);
|
||||
if (!URI.Utils.extname(newFilePath)) {
|
||||
let rawNewFilePath = resolveDocumentLink(newName, triggerHref.path);
|
||||
let resolvedNewFilePath = rawNewFilePath;
|
||||
if (!URI.Utils.extname(resolvedNewFilePath)) {
|
||||
// If the newly entered path doesn't have a file extension but the original file did
|
||||
// tack on a .md file extension
|
||||
if (URI.Utils.extname(targetUri)) {
|
||||
newFilePath = newFilePath.with({
|
||||
path: newFilePath.path + '.md'
|
||||
resolvedNewFilePath = resolvedNewFilePath.with({
|
||||
path: resolvedNewFilePath.path + '.md'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// First rename the file
|
||||
fileRenames.push({ from: targetUri.toString(), to: newFilePath.toString() });
|
||||
edit.renameFile(targetUri, newFilePath);
|
||||
fileRenames.push({ from: targetUri.toString(), to: resolvedNewFilePath.toString() });
|
||||
edit.renameFile(targetUri, resolvedNewFilePath);
|
||||
|
||||
// Then update all refs to it
|
||||
for (const ref of allRefsInfo.references) {
|
||||
if (ref.kind === 'link') {
|
||||
edit.replace(ref.link.source.resource, this.getFilePathRange(ref), encodeURI(newName));
|
||||
// Try to preserve style of existing links
|
||||
let newPath: string;
|
||||
if (ref.link.source.text.startsWith('/')) {
|
||||
const root = resolveDocumentLink('/', ref.link.source.resource);
|
||||
newPath = '/' + path.relative(root.toString(true), rawNewFilePath.toString(true));
|
||||
} else {
|
||||
newPath = path.relative(URI.Utils.dirname(ref.link.source.resource).toString(true), rawNewFilePath.toString(true));
|
||||
if (newName.startsWith('./') && !newPath.startsWith('../')) {
|
||||
newPath = './' + newPath;
|
||||
}
|
||||
}
|
||||
edit.replace(ref.link.source.resource, this.getFilePathRange(ref), encodeURI(newPath));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -473,15 +473,53 @@ suite('markdown: rename', () => {
|
|||
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), '/new File', new InMemoryWorkspaceMarkdownDocuments([doc]));
|
||||
assertEditsEqual(edit!, {
|
||||
originalUri: uri,
|
||||
newUri: workspacePath('new File.md'),
|
||||
newUri: workspacePath('new File.md'), // Rename on disk should use file extension
|
||||
}, {
|
||||
uri: uri, edits: [
|
||||
new vscode.TextEdit(new vscode.Range(0, 7, 0, 11), '/new%20File'),
|
||||
new vscode.TextEdit(new vscode.Range(0, 7, 0, 11), '/new%20File'), // Links should continue to use extension-less paths
|
||||
new vscode.TextEdit(new vscode.Range(1, 7, 1, 11), '/new%20File'),
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
test('Path rename should use correctly resolved paths across files', async () => {
|
||||
const uri1 = workspacePath('sub', 'doc.md');
|
||||
const doc1 = new InMemoryDocument(uri1, joinLines(
|
||||
`[text](./doc.md)`,
|
||||
));
|
||||
|
||||
const uri2 = workspacePath('doc2.md');
|
||||
const doc2 = new InMemoryDocument(uri2, joinLines(
|
||||
`[text](./sub/doc.md)`,
|
||||
));
|
||||
|
||||
const uri3 = workspacePath('sub2', 'doc3.md');
|
||||
const doc3 = new InMemoryDocument(uri3, joinLines(
|
||||
`[text](../sub/doc.md)`,
|
||||
));
|
||||
|
||||
const uri4 = workspacePath('sub2', 'doc4.md');
|
||||
const doc4 = new InMemoryDocument(uri4, joinLines(
|
||||
`[text](/sub/doc.md)`,
|
||||
));
|
||||
|
||||
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), './new/new-doc.md', new InMemoryWorkspaceMarkdownDocuments([
|
||||
doc1, doc2, doc3, doc4,
|
||||
]));
|
||||
assertEditsEqual(edit!, {
|
||||
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: uri2, edits: [new vscode.TextEdit(new vscode.Range(0, 7, 0, 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: uri4, edits: [new vscode.TextEdit(new vscode.Range(0, 7, 0, 18), '/sub/new/new-doc.md')]
|
||||
});
|
||||
});
|
||||
|
||||
test('Rename on link should use header text as placeholder', async () => {
|
||||
const uri = workspacePath('doc.md');
|
||||
const doc = new InMemoryDocument(uri, joinLines(
|
||||
|
|
Loading…
Reference in a new issue