Enable find all references and rename of auto links and http(s) links in markdown

For #146777, #146277
This commit is contained in:
Matt Bierner
2022-04-05 15:17:48 -07:00
parent c80acef8a1
commit a56c9f10b7
6 changed files with 158 additions and 7 deletions

View File

@@ -170,6 +170,11 @@ const linkPattern = /(\[((!\[[^\]]*?\]\(\s*)([^\s\(\)]+?)\s*\)\]|(?:\\\]|[^\]])*
*/
const referenceLinkPattern = /(?:(\[((?:\\\]|[^\]])+)\]\[\s*?)([^\s\]]*?)\]|\[\s*?([^\s\]]*?)\])(?![\:\(])/g;
/**
* Matches `<http://example.com>`
*/
const autoLinkPattern = /\<(\w+:[^\>\s]+)\>/g;
/**
* Matches `[text]: link`
*/
@@ -256,6 +261,7 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
...(await this.getInlineLinks(document)),
...this.getReferenceLinks(document),
...this.getLinkDefinitions(document),
...this.getAutoLinks(document),
]);
}
@@ -277,6 +283,30 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
return results;
}
private *getAutoLinks(document: SkinnyTextDocument): Iterable<MdLink> {
const text = document.getText();
for (const match of text.matchAll(autoLinkPattern)) {
const link = match[1];
const linkTarget = parseLink(document, link);
if (linkTarget) {
const offset = (match.index ?? 0) + 1;
const linkStart = document.positionAt(offset);
const linkEnd = document.positionAt(offset + link.length);
yield {
kind: 'link',
href: linkTarget,
source: {
text: link,
resource: document.uri,
hrefRange: new vscode.Range(linkStart, linkEnd),
fragmentRange: getFragmentRange(link, linkStart, linkEnd),
}
};
}
}
}
private *getReferenceLinks(document: SkinnyTextDocument): Iterable<MdLink> {
const text = document.getText();
for (const match of text.matchAll(referenceLinkPattern)) {

View File

@@ -158,8 +158,22 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference
return Array.from(this.getReferencesToLinkReference(allLinksInWorkspace, sourceLink.href.ref, { resource: sourceLink.source.resource, range: sourceLink.source.hrefRange }));
}
if (sourceLink.href.kind !== 'internal') {
return [];
if (sourceLink.href.kind === 'external') {
const references: MdReference[] = [];
for (const link of allLinksInWorkspace) {
if (link.href.kind === 'external' && link.href.uri.scheme === sourceLink.href.uri.scheme && link.href.uri.path === sourceLink.href.uri.path) {
const isTriggerLocation = sourceLink.source.resource.fsPath === link.source.resource.fsPath && sourceLink.source.hrefRange.isEqual(link.source.hrefRange);
references.push({
kind: 'link',
isTriggerLocation,
isDefinition: false,
link,
location: new vscode.Location(link.source.resource, link.source.hrefRange),
});
}
}
return references;
}
let targetDoc = await this.workspaceContents.getMarkdownDocument(sourceLink.href.path);
@@ -190,9 +204,7 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference
headerTextLocation: entry.headerTextLocation
});
}
}
if (sourceLink.href.fragment) {
for (const link of allLinksInWorkspace) {
if (link.href.kind !== 'internal' || !this.looksLikeLinkToDoc(link.href, targetDoc.uri)) {
continue;
@@ -226,7 +238,7 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference
return Array.from(this.findAllLinksToFile(resource, allLinksInWorkspace, undefined));
}
private *findAllLinksToFile(resource: vscode.Uri, allLinksInWorkspace: readonly MdLink[], sourceLink: MdLink | undefined): Iterable<MdReference> {
private * findAllLinksToFile(resource: vscode.Uri, allLinksInWorkspace: readonly MdLink[], sourceLink: MdLink | undefined): Iterable<MdReference> {
for (const link of allLinksInWorkspace) {
if (link.href.kind !== 'internal' || !this.looksLikeLinkToDoc(link.href, resource)) {
continue;
@@ -248,7 +260,7 @@ export class MdReferencesProvider extends Disposable implements vscode.Reference
}
}
private *getReferencesToLinkReference(allLinks: Iterable<MdLink>, refToFind: string, from: { resource: vscode.Uri; range: vscode.Range }): Iterable<MdReference> {
private * getReferencesToLinkReference(allLinks: Iterable<MdLink>, refToFind: string, from: { resource: vscode.Uri; range: vscode.Range }): Iterable<MdReference> {
for (const link of allLinks) {
let ref: string;
if (link.kind === 'definition') {

View File

@@ -52,6 +52,10 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide
}
}
if (triggerRef.link.href.kind === 'external') {
return { range: triggerRef.link.source.hrefRange, placeholder: document.getText(triggerRef.link.source.hrefRange) };
}
const { fragmentRange } = triggerRef.link.source;
if (fragmentRange) {
const declaration = this.findHeaderDeclaration(allRefsInfo.references);
@@ -98,7 +102,7 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide
continue;
}
}
edit.replace(ref.link.source.resource, ref.link.source.fragmentRange ?? ref.location.range, isRefRename && !ref.link.source.fragmentRange ? newName : slug);
edit.replace(ref.link.source.resource, ref.link.source.fragmentRange ?? ref.location.range, isRefRename && !ref.link.source.fragmentRange || ref.link.href.kind === 'external' ? newName : slug);
break;
}
}