diff --git a/extensions/markdown-language-features/src/languageFeatures/references.ts b/extensions/markdown-language-features/src/languageFeatures/references.ts index c2d56f8e3fb..65db2003423 100644 --- a/extensions/markdown-language-features/src/languageFeatures/references.ts +++ b/extensions/markdown-language-features/src/languageFeatures/references.ts @@ -218,8 +218,8 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference } } else { // Triggered on a link without a fragment so we only require matching the file and ignore fragments - // But exclude cases where the file is referencing itself - if (link.sourceResource.fsPath !== targetDoc.uri.fsPath) { + // But exclude cases where the file is implicitly referencing itself + if (!link.sourceText.startsWith('#') || link.sourceResource.fsPath !== targetDoc.uri.fsPath) { references.push({ kind: 'link', isTriggerLocation, diff --git a/extensions/markdown-language-features/src/languageFeatures/rename.ts b/extensions/markdown-language-features/src/languageFeatures/rename.ts index 19478795e65..66f05a2173d 100644 --- a/extensions/markdown-language-features/src/languageFeatures/rename.ts +++ b/extensions/markdown-language-features/src/languageFeatures/rename.ts @@ -56,7 +56,10 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide return triggerRef.link.sourceHrefRange; } } else { - return triggerRef.fragmentLocation?.range ?? triggerRef.location.range; + if (triggerRef.fragmentLocation) { + return triggerRef.fragmentLocation.range; + } + throw new Error(localize('renameNoFiles', "Renaming files is currently not supported")); } } } diff --git a/extensions/markdown-language-features/src/test/references.test.ts b/extensions/markdown-language-features/src/test/references.test.ts index 4b7f9532cec..319fcec7817 100644 --- a/extensions/markdown-language-features/src/test/references.test.ts +++ b/extensions/markdown-language-features/src/test/references.test.ts @@ -312,7 +312,7 @@ suite('markdown: find all references', () => { const otherUri = workspacePath('sub', 'other.md'); const doc = new InMemoryDocument(docUri, joinLines( - `[other](./sub/other)`, + `[other](./sub/other)`, // trigger here )); const refs = await getReferences(doc, new vscode.Position(0, 15), new InMemoryWorkspaceMarkdownDocuments([ @@ -328,6 +328,22 @@ suite('markdown: find all references', () => { ); }); + test('Should find explicit references to own file ', async () => { + const uri = workspacePath('doc.md'); + const doc = new InMemoryDocument(uri, joinLines( + `[bare](doc.md)`, // trigger here + `[rel](./doc.md)`, + `[abs](/doc.md)`, + )); + + const refs = await getReferences(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([doc])); + assertReferencesEqual(refs!, + { uri, line: 0 }, + { uri, line: 1 }, + { uri, line: 2 }, + ); + }); + suite('Reference links', () => { test('Should find reference links within file from link', async () => { const docUri = workspacePath('doc.md'); diff --git a/extensions/markdown-language-features/src/test/rename.test.ts b/extensions/markdown-language-features/src/test/rename.test.ts index e22453f3e02..3f92f70e8bd 100644 --- a/extensions/markdown-language-features/src/test/rename.test.ts +++ b/extensions/markdown-language-features/src/test/rename.test.ts @@ -208,6 +208,52 @@ suite('markdown: rename', () => { }); }); + test('Rename on link in other file should pick up all refs', async () => { + const uri = workspacePath('doc.md'); + const otherUri = workspacePath('other.md'); + const doc = new InMemoryDocument(uri, joinLines( + `### A b C`, + `[text](#a-b-c)`, + )); + + const otherDoc = new InMemoryDocument(otherUri, joinLines( + `[text](#a-b-c)`, + `[text](./doc.md#a-b-c)`, + `[text](./doc#a-b-c)` + )); + + const expectedEdits = [ + { + uri: uri, edits: [ + new vscode.TextEdit(new vscode.Range(0, 4, 0, 9), 'New Header'), + new vscode.TextEdit(new vscode.Range(1, 8, 1, 13), 'new-header'), + ] + }, { + uri: otherUri, edits: [ + new vscode.TextEdit(new vscode.Range(1, 16, 1, 21), 'new-header'), + new vscode.TextEdit(new vscode.Range(2, 13, 2, 18), 'new-header'), + ] + } + ]; + + { + // Rename on header with file extension + const edit = await getRenameEdits(otherDoc, new vscode.Position(1, 17), "New Header", new InMemoryWorkspaceMarkdownDocuments([ + doc, + otherDoc + ])); + assertEditsEqual(edit!, ...expectedEdits); + } + { + // Rename on header without extension + const edit = await getRenameEdits(otherDoc, new vscode.Position(2, 15), "New Header", new InMemoryWorkspaceMarkdownDocuments([ + doc, + otherDoc + ])); + assertEditsEqual(edit!, ...expectedEdits); + } + }); + test('Rename on ref should rename refs and def', async () => { const uri = workspacePath('doc.md'); const doc = new InMemoryDocument(uri, joinLines( @@ -246,7 +292,6 @@ suite('markdown: rename', () => { }); }); - test('Rename should not be supported on link text', async () => { const uri = workspacePath('doc.md'); const doc = new InMemoryDocument(uri, joinLines( @@ -256,4 +301,14 @@ suite('markdown: rename', () => { await assert.rejects(getRenameRange(doc, new vscode.Position(1, 2), new InMemoryWorkspaceMarkdownDocuments([doc]))); }); + + test('Rename should not be supported on bare file references', async () => { + const uri = workspacePath('doc.md'); + const doc = new InMemoryDocument(uri, joinLines( + `[text](./doc.md)`, + `[other](./doc.md)`, + )); + + await assert.rejects(getRenameRange(doc, new vscode.Position(0, 10), new InMemoryWorkspaceMarkdownDocuments([doc]))); + }); });