mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
Fix md rename when file does not exist
Fixes #148147 - Don't try renaming non-existent files - Also fixes a bug where renaming in untitled files would insert `untitled:`
This commit is contained in:
parent
3e182633c7
commit
8449a9f5cb
|
@ -169,8 +169,10 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide
|
|||
}
|
||||
|
||||
// First rename the file
|
||||
fileRenames.push({ from: targetUri, to: resolvedNewFilePath });
|
||||
edit.renameFile(targetUri, resolvedNewFilePath);
|
||||
if (await this.workspaceContents.fileExists(targetUri)) {
|
||||
fileRenames.push({ from: targetUri, to: resolvedNewFilePath });
|
||||
edit.renameFile(targetUri, resolvedNewFilePath);
|
||||
}
|
||||
|
||||
// Then update all refs to it
|
||||
for (const ref of allRefsInfo.references) {
|
||||
|
@ -181,9 +183,14 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide
|
|||
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('../') || newName.startsWith('.\\') && !newPath.startsWith('..\\')) {
|
||||
newPath = './' + newPath;
|
||||
const rootDir = URI.Utils.dirname(ref.link.source.resource);
|
||||
if (rootDir.scheme === rawNewFilePath.scheme && rootDir.scheme !== 'untitled') {
|
||||
newPath = path.relative(rootDir.toString(true), rawNewFilePath.toString(true));
|
||||
if (newName.startsWith('./') && !newPath.startsWith('../') || newName.startsWith('.\\') && !newPath.startsWith('..\\')) {
|
||||
newPath = './' + newPath;
|
||||
}
|
||||
} else {
|
||||
newPath = newName;
|
||||
}
|
||||
}
|
||||
edit.replace(ref.link.source.resource, this.getFilePathRange(ref), encodeURI(newPath.replace(/\\/g, '/')));
|
||||
|
@ -262,3 +269,4 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide
|
|||
return this.cachedRefs;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ export class InMemoryWorkspaceMarkdownDocuments implements MdWorkspaceContents {
|
|||
return this._documents.get(this.getKey(resource));
|
||||
}
|
||||
|
||||
public async fileExists(resource: vscode.Uri): Promise<boolean> {
|
||||
return this._documents.has(this.getKey(resource));
|
||||
}
|
||||
|
||||
private readonly _onDidChangeMarkdownDocumentEmitter = new vscode.EventEmitter<SkinnyTextDocument>();
|
||||
public onDidChangeMarkdownDocument = this._onDidChangeMarkdownDocumentEmitter.event;
|
||||
|
||||
|
|
|
@ -458,19 +458,19 @@ suite('markdown: rename', () => {
|
|||
doc1,
|
||||
doc2
|
||||
]));
|
||||
assertEditsEqual(edit!, {
|
||||
originalUri: workspacePath('images', 'more', 'image.png'),
|
||||
newUri: workspacePath('img', 'test', 'new.png'),
|
||||
}, {
|
||||
uri: uri1, edits: [
|
||||
new vscode.TextEdit(new vscode.Range(0, 7, 0, 29), '/img/test/new.png'),
|
||||
new vscode.TextEdit(new vscode.Range(2, 7, 2, 29), '/img/test/new.png'),
|
||||
]
|
||||
}, {
|
||||
uri: uri2, edits: [
|
||||
new vscode.TextEdit(new vscode.Range(0, 7, 0, 29), '/img/test/new.png'),
|
||||
]
|
||||
});
|
||||
assertEditsEqual(edit!,
|
||||
// Should not have file edits since the files don't exist here
|
||||
{
|
||||
uri: uri1, edits: [
|
||||
new vscode.TextEdit(new vscode.Range(0, 7, 0, 29), '/img/test/new.png'),
|
||||
new vscode.TextEdit(new vscode.Range(2, 7, 2, 29), '/img/test/new.png'),
|
||||
]
|
||||
},
|
||||
{
|
||||
uri: uri2, edits: [
|
||||
new vscode.TextEdit(new vscode.Range(0, 7, 0, 29), '/img/test/new.png'),
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
test('Path rename should use .md extension on extension-less link', async () => {
|
||||
|
@ -550,24 +550,27 @@ suite('markdown: rename', () => {
|
|||
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)`,
|
||||
`![text](sub2/doc3.md)`,
|
||||
));
|
||||
|
||||
const uri2 = workspacePath('doc2.md');
|
||||
const doc2 = new InMemoryDocument(uri2, joinLines(
|
||||
`![text](sub/images/cat.gif)`,
|
||||
`![text](sub/sub2/doc3.md)`,
|
||||
));
|
||||
|
||||
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), 'img/cat.gif', new InMemoryWorkspaceMarkdownDocuments([
|
||||
doc1, doc2,
|
||||
const uri3 = workspacePath('sub', 'sub2', 'doc3.md');
|
||||
const doc3 = new InMemoryDocument(uri3, joinLines());
|
||||
|
||||
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), 'sub2/cat.md', new InMemoryWorkspaceMarkdownDocuments([
|
||||
doc1, doc2, doc3
|
||||
]));
|
||||
assertEditsEqual(edit!, {
|
||||
originalUri: workspacePath('sub', 'images', 'cat.gif'),
|
||||
newUri: workspacePath('sub', 'img', 'cat.gif'),
|
||||
originalUri: workspacePath('sub', 'sub2', 'doc3.md'),
|
||||
newUri: workspacePath('sub', 'sub2', 'cat.md'),
|
||||
}, {
|
||||
uri: uri1, edits: [new vscode.TextEdit(new vscode.Range(0, 8, 0, 22), 'img/cat.gif')]
|
||||
uri: uri1, edits: [new vscode.TextEdit(new vscode.Range(0, 8, 0, 20), 'sub2/cat.md')]
|
||||
}, {
|
||||
uri: uri2, edits: [new vscode.TextEdit(new vscode.Range(0, 8, 0, 26), 'sub/img/cat.gif')]
|
||||
uri: uri2, edits: [new vscode.TextEdit(new vscode.Range(0, 8, 0, 24), 'sub/sub2/cat.md')]
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ export interface MdWorkspaceContents {
|
|||
|
||||
getMarkdownDocument(resource: vscode.Uri): Promise<SkinnyTextDocument | undefined>;
|
||||
|
||||
fileExists(resource: vscode.Uri): Promise<boolean>;
|
||||
|
||||
readonly onDidChangeMarkdownDocument: vscode.Event<SkinnyTextDocument>;
|
||||
readonly onDidCreateMarkdownDocument: vscode.Event<SkinnyTextDocument>;
|
||||
readonly onDidDeleteMarkdownDocument: vscode.Event<vscode.Uri>;
|
||||
|
@ -143,4 +145,14 @@ export class VsCodeMdWorkspaceContents extends Disposable implements MdWorkspace
|
|||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public async fileExists(target: vscode.Uri): Promise<boolean> {
|
||||
let targetResourceStat: vscode.FileStat | undefined;
|
||||
try {
|
||||
targetResourceStat = await vscode.workspace.fs.stat(target);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
return targetResourceStat.type === vscode.FileType.File;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue