mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-19 08:08:39 +01:00
Don't try parsing non-markdown files (#152661)
This fixes our references and rename provider to not try parsing non-markdown files as if they were markdown
This commit is contained in:
@@ -13,12 +13,12 @@ import { MdTableOfContentsWatcher } from '../test/tableOfContentsWatcher';
|
||||
import { Delayer } from '../util/async';
|
||||
import { noopToken } from '../util/cancellation';
|
||||
import { Disposable } from '../util/dispose';
|
||||
import { isMarkdownFile } from '../util/file';
|
||||
import { isMarkdownFile, looksLikeMarkdownPath } from '../util/file';
|
||||
import { Limiter } from '../util/limiter';
|
||||
import { ResourceMap } from '../util/resourceMap';
|
||||
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
|
||||
import { InternalHref, LinkDefinitionSet, MdLink, MdLinkProvider, MdLinkSource } from './documentLinkProvider';
|
||||
import { MdReferencesProvider, tryFindMdDocumentForLink } from './references';
|
||||
import { MdReferencesProvider, tryResolveLinkPath } from './references';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -374,7 +374,7 @@ export class DiagnosticManager extends Disposable {
|
||||
this.pendingDiagnostics.clear();
|
||||
|
||||
await Promise.all(pending.map(async resource => {
|
||||
const doc = await this.workspaceContents.getMarkdownDocument(resource);
|
||||
const doc = await this.workspaceContents.getOrLoadMarkdownDocument(resource);
|
||||
if (doc) {
|
||||
await this.inFlightDiagnostics.trigger(doc.uri, async (token) => {
|
||||
const state = await this.recomputeDiagnosticState(doc, token);
|
||||
@@ -540,19 +540,19 @@ export class DiagnosticComputer {
|
||||
return;
|
||||
}
|
||||
|
||||
const hrefDoc = await tryFindMdDocumentForLink({ kind: 'internal', path: path, fragment: '' }, this.workspaceContents);
|
||||
if (!hrefDoc && !await this.workspaceContents.pathExists(path)) {
|
||||
const resolvedHrefPath = await tryResolveLinkPath(path, this.workspaceContents);
|
||||
if (!resolvedHrefPath) {
|
||||
const msg = localize('invalidPathLink', 'File does not exist at path: {0}', path.fsPath);
|
||||
for (const link of links) {
|
||||
if (!this.isIgnoredLink(options, link.source.pathText)) {
|
||||
diagnostics.push(new LinkDoesNotExistDiagnostic(link.source.hrefRange, msg, pathErrorSeverity, link.source.pathText));
|
||||
}
|
||||
}
|
||||
} else if (hrefDoc && typeof fragmentErrorSeverity !== 'undefined') {
|
||||
} else if (typeof fragmentErrorSeverity !== 'undefined' && this.isMarkdownPath(resolvedHrefPath)) {
|
||||
// Validate each of the links to headers in the file
|
||||
const fragmentLinks = links.filter(x => x.fragment);
|
||||
if (fragmentLinks.length) {
|
||||
const toc = await this.tocProvider.get(hrefDoc.uri);
|
||||
const toc = await this.tocProvider.get(resolvedHrefPath);
|
||||
for (const link of fragmentLinks) {
|
||||
if (!toc.lookup(link.fragment) && !this.isIgnoredLink(options, link.source.pathText) && !this.isIgnoredLink(options, link.source.text)) {
|
||||
const msg = localize('invalidLinkToHeaderInOtherFile', 'Header does not exist in file: {0}', link.fragment);
|
||||
@@ -567,6 +567,10 @@ export class DiagnosticComputer {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
private isMarkdownPath(resolvedHrefPath: vscode.Uri) {
|
||||
return this.workspaceContents.hasMarkdownDocument(resolvedHrefPath) || looksLikeMarkdownPath(resolvedHrefPath);
|
||||
}
|
||||
|
||||
private isIgnoredLink(options: DiagnosticOptions, link: string): boolean {
|
||||
return options.ignoreLinks.some(glob => picomatch.isMatch(link, glob));
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { MarkdownEngine } from '../markdownEngine';
|
||||
import { MdTableOfContentsProvider, TocEntry } from '../tableOfContents';
|
||||
import { noopToken } from '../util/cancellation';
|
||||
import { Disposable } from '../util/dispose';
|
||||
import { looksLikeMarkdownPath } from '../util/file';
|
||||
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
|
||||
import { InternalHref, MdLink, MdLinkComputer } from './documentLinkProvider';
|
||||
import { MdWorkspaceInfoCache } from './workspaceCache';
|
||||
@@ -177,15 +178,15 @@ export class MdReferencesProvider extends Disposable {
|
||||
return references;
|
||||
}
|
||||
|
||||
const targetDoc = await tryFindMdDocumentForLink(sourceLink.href, this.workspaceContents);
|
||||
const resolvedResource = await tryResolveLinkPath(sourceLink.href.path, this.workspaceContents);
|
||||
if (token.isCancellationRequested) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const references: MdReference[] = [];
|
||||
|
||||
if (targetDoc && sourceLink.href.fragment && sourceLink.source.fragmentRange?.contains(triggerPosition)) {
|
||||
const toc = await this.tocProvider.get(targetDoc.uri);
|
||||
if (resolvedResource && this.isMarkdownPath(resolvedResource) && sourceLink.href.fragment && sourceLink.source.fragmentRange?.contains(triggerPosition)) {
|
||||
const toc = await this.tocProvider.get(resolvedResource);
|
||||
const entry = toc.lookup(sourceLink.href.fragment);
|
||||
if (entry) {
|
||||
references.push({
|
||||
@@ -199,7 +200,7 @@ export class MdReferencesProvider extends Disposable {
|
||||
}
|
||||
|
||||
for (const link of allLinksInWorkspace) {
|
||||
if (link.href.kind !== 'internal' || !this.looksLikeLinkToDoc(link.href, targetDoc.uri)) {
|
||||
if (link.href.kind !== 'internal' || !this.looksLikeLinkToDoc(link.href, resolvedResource)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -215,12 +216,16 @@ export class MdReferencesProvider extends Disposable {
|
||||
}
|
||||
}
|
||||
} else { // Triggered on a link without a fragment so we only require matching the file and ignore fragments
|
||||
references.push(...this.findAllLinksToFile(targetDoc?.uri ?? sourceLink.href.path, allLinksInWorkspace, sourceLink));
|
||||
references.push(...this.findAllLinksToFile(resolvedResource ?? sourceLink.href.path, allLinksInWorkspace, sourceLink));
|
||||
}
|
||||
|
||||
return references;
|
||||
}
|
||||
|
||||
private isMarkdownPath(resolvedHrefPath: vscode.Uri) {
|
||||
return this.workspaceContents.hasMarkdownDocument(resolvedHrefPath) || looksLikeMarkdownPath(resolvedHrefPath);
|
||||
}
|
||||
|
||||
private looksLikeLinkToDoc(href: InternalHref, targetDoc: vscode.Uri) {
|
||||
return href.path.fsPath === targetDoc.fsPath
|
||||
|| uri.Utils.extname(href.path) === '' && href.path.with({ path: href.path.path + '.md' }).fsPath === targetDoc.fsPath;
|
||||
@@ -310,16 +315,17 @@ export function registerReferencesSupport(
|
||||
return vscode.languages.registerReferenceProvider(selector, new MdVsCodeReferencesProvider(referencesProvider));
|
||||
}
|
||||
|
||||
export async function tryFindMdDocumentForLink(href: InternalHref, workspaceContents: MdWorkspaceContents): Promise<SkinnyTextDocument | undefined> {
|
||||
const targetDoc = await workspaceContents.getMarkdownDocument(href.path);
|
||||
if (targetDoc) {
|
||||
return targetDoc;
|
||||
export async function tryResolveLinkPath(originalUri: vscode.Uri, workspaceContents: MdWorkspaceContents): Promise<vscode.Uri | undefined> {
|
||||
if (await workspaceContents.pathExists(originalUri)) {
|
||||
return originalUri;
|
||||
}
|
||||
|
||||
// We don't think the file exists. If it doesn't already have an extension, try tacking on a `.md` and using that instead
|
||||
if (uri.Utils.extname(href.path) === '') {
|
||||
const dotMdResource = href.path.with({ path: href.path.path + '.md' });
|
||||
return workspaceContents.getMarkdownDocument(dotMdResource);
|
||||
if (uri.Utils.extname(originalUri) === '') {
|
||||
const dotMdResource = originalUri.with({ path: originalUri.path + '.md' });
|
||||
if (await workspaceContents.pathExists(dotMdResource)) {
|
||||
return dotMdResource;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -11,7 +11,7 @@ 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 { MdHeaderReference, MdLinkReference, MdReference, MdReferencesProvider, tryResolveLinkPath } from './references';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -153,8 +153,7 @@ export class MdVsCodeRenameProvider extends Disposable implements vscode.RenameP
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
const fileRenames: MdFileRenameEdit[] = [];
|
||||
|
||||
const targetDoc = await tryFindMdDocumentForLink(triggerHref, this.workspaceContents);
|
||||
const targetUri = targetDoc?.uri ?? triggerHref.path;
|
||||
const targetUri = await tryResolveLinkPath(triggerHref.path, this.workspaceContents) ?? triggerHref.path;
|
||||
|
||||
const rawNewFilePath = resolveDocumentLink(newName, triggerDocument);
|
||||
let resolvedNewFilePath = rawNewFilePath;
|
||||
|
||||
@@ -61,7 +61,7 @@ export class MdDocumentInfoCache<T> extends Disposable {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const doc = await this.workspaceContents.getMarkdownDocument(resource);
|
||||
const doc = await this.workspaceContents.getOrLoadMarkdownDocument(resource);
|
||||
return doc && this.onDidChangeDocument(doc, true)?.value;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user