Skip to content

Commit 6b57334

Browse files
committed
Fixing references on header when looking at file extensions
1 parent 8a6a300 commit 6b57334

File tree

3 files changed

+100
-21
lines changed

3 files changed

+100
-21
lines changed

extensions/markdown-language-features/src/languageFeatures/references.ts

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,10 @@ import { Slugifier } from '../slugify';
99
import { TableOfContents, TocEntry } from '../tableOfContents';
1010
import { Disposable } from '../util/dispose';
1111
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
12-
import { InternalHref, LinkHref, MdLink, MdLinkProvider } from './documentLinkProvider';
12+
import { InternalHref, MdLink, MdLinkProvider } from './documentLinkProvider';
1313
import { MdWorkspaceCache } from './workspaceCache';
1414

1515

16-
function isLinkToHeader(target: LinkHref, header: TocEntry, headerDocument: vscode.Uri, slugifier: Slugifier): target is InternalHref {
17-
return target.kind === 'internal'
18-
&& target.path.fsPath === headerDocument.fsPath
19-
&& slugifier.fromHeading(target.fragment).value === header.slug.value;
20-
}
21-
22-
2316
/**
2417
* A link in a markdown file.
2518
*/
@@ -121,15 +114,10 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference
121114
});
122115

123116
for (const link of links) {
124-
if (isLinkToHeader(link.href, header, document.uri, this.slugifier)) {
125-
references.push({
126-
kind: 'link',
127-
isTriggerLocation: false,
128-
isDefinition: false,
129-
location: new vscode.Location(link.sourceResource, link.sourceRange),
130-
fragmentLocation: getFragmentLocation(link),
131-
});
132-
} else if (link.kind === 'definition' && isLinkToHeader(link.href, header, document.uri, this.slugifier)) {
117+
if (link.href.kind === 'internal'
118+
&& this.looksLikeLinkToDoc(link.href, document)
119+
&& this.slugifier.fromHeading(link.href.fragment).value === header.slug.value
120+
) {
133121
references.push({
134122
kind: 'link',
135123
isTriggerLocation: false,
@@ -194,10 +182,7 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference
194182
continue;
195183
}
196184

197-
const matchesFilePart = link.href.path.fsPath === targetDoc.uri.fsPath
198-
|| uri.Utils.extname(link.href.path) === '' && link.href.path.with({ path: link.href.path.path + '.md' }).fsPath === targetDoc.uri.fsPath;
199-
200-
if (!matchesFilePart) {
185+
if (!this.looksLikeLinkToDoc(link.href, targetDoc)) {
201186
continue;
202187
}
203188

@@ -231,6 +216,11 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference
231216
return references;
232217
}
233218

219+
private looksLikeLinkToDoc(href: InternalHref, targetDoc: SkinnyTextDocument) {
220+
return href.path.fsPath === targetDoc.uri.fsPath
221+
|| uri.Utils.extname(href.path) === '' && href.path.with({ path: href.path.path + '.md' }).fsPath === targetDoc.uri.fsPath;
222+
}
223+
234224
private * getReferencesToReferenceLink(allLinks: Iterable<MdLink>, sourceLink: MdLink): Iterable<MdReference> {
235225
if (sourceLink.href.kind !== 'reference') {
236226
return;

extensions/markdown-language-features/src/test/references.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,37 @@ suite('markdown: find all references', () => {
215215
);
216216
});
217217

218+
test('Should find references without requiring file extensions', async () => {
219+
const docUri = workspacePath('doc.md');
220+
const other1Uri = workspacePath('other.md');
221+
222+
const doc = new InMemoryDocument(docUri, joinLines(
223+
`# a B c`,
224+
``,
225+
`[link 1](#a-b-c)`,
226+
));
227+
const refs = await getReferences(doc, new vscode.Position(2, 10), new InMemoryWorkspaceMarkdownDocuments([
228+
doc,
229+
new InMemoryDocument(other1Uri, joinLines(
230+
`[not link](#a-b-c)`,
231+
`[not link](/doc.md#a-b-z)`,
232+
`[with ext](/doc.md#a-b-c)`,
233+
`[without ext](/doc#a-b-c)`,
234+
`[rel with ext](./doc.md#a-b-c)`,
235+
`[rel without ext](./doc#a-b-c)`,
236+
)),
237+
]));
238+
239+
assertReferencesEqual(refs!,
240+
{ uri: docUri, line: 0 }, // Header definition
241+
{ uri: docUri, line: 2 },
242+
{ uri: other1Uri, line: 2 }, // Other with ext
243+
{ uri: other1Uri, line: 3 }, // Other without ext
244+
{ uri: other1Uri, line: 4 }, // Other relative link with ext
245+
{ uri: other1Uri, line: 5 }, // Other relative link without ext
246+
);
247+
});
248+
218249
test('Should find references from link across files when triggered on link without file extension', async () => {
219250
const docUri = workspacePath('doc.md');
220251
const other1Uri = workspacePath('sub', 'other.md');

extensions/markdown-language-features/src/test/rename.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,62 @@ suite('markdown: rename', () => {
149149
]
150150
});
151151
});
152+
153+
test('Rename on header should pick up links across files', async () => {
154+
const uri = workspacePath('doc.md');
155+
const otherUri = workspacePath('other.md');
156+
const doc = new InMemoryDocument(uri, joinLines(
157+
`### A b C`, // rename here
158+
`[text](#a-b-c)`,
159+
));
160+
161+
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryWorkspaceMarkdownDocuments([
162+
doc,
163+
new InMemoryDocument(otherUri, joinLines(
164+
`[text](#a-b-c)`, // Should not find this
165+
`[text](./doc.md#a-b-c)`, // But should find this
166+
`[text](./doc#a-b-c)`, // And this
167+
))
168+
]));
169+
assertEditsEqual(edit!, {
170+
uri: uri, edits: [
171+
new vscode.TextEdit(new vscode.Range(0, 4, 0, 9), 'New Header'),
172+
new vscode.TextEdit(new vscode.Range(1, 8, 1, 13), 'new-header'),
173+
]
174+
}, {
175+
uri: otherUri, edits: [
176+
new vscode.TextEdit(new vscode.Range(1, 16, 1, 21), 'new-header'),
177+
new vscode.TextEdit(new vscode.Range(2, 13, 2, 18), 'new-header'),
178+
]
179+
});
180+
});
181+
182+
test('Rename on link should pick up links across files', async () => {
183+
const uri = workspacePath('doc.md');
184+
const otherUri = workspacePath('other.md');
185+
const doc = new InMemoryDocument(uri, joinLines(
186+
`### A b C`,
187+
`[text](#a-b-c)`, // rename here
188+
));
189+
190+
const edit = await getRenameEdits(doc, new vscode.Position(1, 10), "New Header", new InMemoryWorkspaceMarkdownDocuments([
191+
doc,
192+
new InMemoryDocument(otherUri, joinLines(
193+
`[text](#a-b-c)`, // Should not find this
194+
`[text](./doc.md#a-b-c)`, // But should find this
195+
`[text](./doc#a-b-c)`, // And this
196+
))
197+
]));
198+
assertEditsEqual(edit!, {
199+
uri: uri, edits: [
200+
new vscode.TextEdit(new vscode.Range(0, 4, 0, 9), 'New Header'),
201+
new vscode.TextEdit(new vscode.Range(1, 8, 1, 13), 'new-header'),
202+
]
203+
}, {
204+
uri: otherUri, edits: [
205+
new vscode.TextEdit(new vscode.Range(1, 16, 1, 21), 'new-header'),
206+
new vscode.TextEdit(new vscode.Range(2, 13, 2, 18), 'new-header'),
207+
]
208+
});
209+
});
152210
});

0 commit comments

Comments
 (0)