mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
Enable go to definition for markdown links (#148017)
* Enable go to definition for markdown links * Add markdown definitionProvider tests
This commit is contained in:
parent
2785ac4f71
commit
44e644467d
|
@ -6,6 +6,7 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { CommandManager } from './commandManager';
|
||||
import * as commands from './commands/index';
|
||||
import { MdDefinitionProvider } from './languageFeatures/definitionProvider';
|
||||
import { MdLinkProvider } from './languageFeatures/documentLinkProvider';
|
||||
import { MdDocumentSymbolProvider } from './languageFeatures/documentSymbolProvider';
|
||||
import { registerDropIntoEditor } from './languageFeatures/dropIntoEditor';
|
||||
|
@ -72,6 +73,7 @@ function registerMarkdownLanguageFeatures(
|
|||
vscode.languages.registerWorkspaceSymbolProvider(new MdWorkspaceSymbolProvider(symbolProvider, workspaceContents)),
|
||||
vscode.languages.registerReferenceProvider(selector, referencesProvider),
|
||||
vscode.languages.registerRenameProvider(selector, new MdRenameProvider(referencesProvider, workspaceContents, githubSlugifier)),
|
||||
vscode.languages.registerDefinitionProvider(selector, new MdDefinitionProvider(referencesProvider)),
|
||||
MdPathCompletionProvider.register(selector, engine, linkProvider),
|
||||
registerDropIntoEditor(selector),
|
||||
registerFindFileReferences(commandManager, referencesProvider),
|
||||
|
@ -100,4 +102,3 @@ function registerMarkdownCommands(
|
|||
commandManager.register(new commands.ReloadPlugins(previewManager, engine));
|
||||
return commandManager;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as vscode from 'vscode';
|
||||
import { Disposable } from '../util/dispose';
|
||||
import { SkinnyTextDocument } from '../workspaceContents';
|
||||
import { MdReferencesProvider } from './references';
|
||||
|
||||
export class MdDefinitionProvider extends Disposable implements vscode.DefinitionProvider {
|
||||
|
||||
constructor(private readonly referencesProvider: MdReferencesProvider) {
|
||||
super();
|
||||
}
|
||||
|
||||
async provideDefinition(document: SkinnyTextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Definition | undefined> {
|
||||
const allRefs = await this.referencesProvider.getAllReferencesAtPosition(document, position, token);
|
||||
|
||||
return allRefs.find(ref => ref.kind === 'link' && ref.isDefinition)?.location;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import 'mocha';
|
||||
import * as vscode from 'vscode';
|
||||
import { MdDefinitionProvider } from '../languageFeatures/definitionProvider';
|
||||
import { MdLinkProvider } from '../languageFeatures/documentLinkProvider';
|
||||
import { MdReferencesProvider } from '../languageFeatures/references';
|
||||
import { githubSlugifier } from '../slugify';
|
||||
import { InMemoryDocument } from '../util/inMemoryDocument';
|
||||
import { MdWorkspaceContents } from '../workspaceContents';
|
||||
import { createNewMarkdownEngine } from './engine';
|
||||
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
|
||||
import { joinLines, noopToken, workspacePath } from './util';
|
||||
|
||||
|
||||
function getDefinition(doc: InMemoryDocument, pos: vscode.Position, workspaceContents: MdWorkspaceContents) {
|
||||
const engine = createNewMarkdownEngine();
|
||||
const linkProvider = new MdLinkProvider(engine);
|
||||
const referencesProvider = new MdReferencesProvider(linkProvider, workspaceContents, engine, githubSlugifier);
|
||||
const provider = new MdDefinitionProvider(referencesProvider);
|
||||
return provider.provideDefinition(doc, pos, noopToken);
|
||||
}
|
||||
|
||||
function assertDefinitionsEqual(actualDef: vscode.Definition, ...expectedDefs: { uri: vscode.Uri; line: number; startCharacter?: number; endCharacter?: number }[]) {
|
||||
const actualDefsArr = Array.isArray(actualDef) ? actualDef : [actualDef];
|
||||
|
||||
assert.strictEqual(actualDefsArr.length, expectedDefs.length, `Definition counts should match`);
|
||||
|
||||
for (let i = 0; i < actualDefsArr.length; ++i) {
|
||||
const actual = actualDefsArr[i];
|
||||
const expected = expectedDefs[i];
|
||||
assert.strictEqual(actual.uri.toString(), expected.uri.toString(), `Definition '${i}' has expected document`);
|
||||
assert.strictEqual(actual.range.start.line, expected.line, `Definition '${i}' has expected start line`);
|
||||
assert.strictEqual(actual.range.end.line, expected.line, `Definition '${i}' has expected end line`);
|
||||
if (typeof expected.startCharacter !== 'undefined') {
|
||||
assert.strictEqual(actual.range.start.character, expected.startCharacter, `Definition '${i}' has expected start character`);
|
||||
}
|
||||
if (typeof expected.endCharacter !== 'undefined') {
|
||||
assert.strictEqual(actual.range.end.character, expected.endCharacter, `Definition '${i}' has expected end character`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suite('markdown: Go to definition', () => {
|
||||
test('Should not return definition when on link text', async () => {
|
||||
const doc = new InMemoryDocument(workspacePath('doc.md'), joinLines(
|
||||
`[ref](#abc)`,
|
||||
`[ref]: http://example.com`,
|
||||
));
|
||||
|
||||
const defs = await getDefinition(doc, new vscode.Position(0, 1), new InMemoryWorkspaceMarkdownDocuments([doc]));
|
||||
assert.deepStrictEqual(defs, undefined);
|
||||
});
|
||||
|
||||
test('Should find definition links within file from link', async () => {
|
||||
const docUri = workspacePath('doc.md');
|
||||
const doc = new InMemoryDocument(docUri, joinLines(
|
||||
`[link 1][abc]`, // trigger here
|
||||
``,
|
||||
`[abc]: https://example.com`,
|
||||
));
|
||||
|
||||
const defs = await getDefinition(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([doc]));
|
||||
assertDefinitionsEqual(defs!,
|
||||
{ uri: docUri, line: 2 },
|
||||
);
|
||||
});
|
||||
|
||||
test('Should find definition links using shorthand', async () => {
|
||||
const docUri = workspacePath('doc.md');
|
||||
const doc = new InMemoryDocument(docUri, joinLines(
|
||||
`[ref]`, // trigger 1
|
||||
``,
|
||||
`[yes][ref]`, // trigger 2
|
||||
``,
|
||||
`[ref]: /Hello.md` // trigger 3
|
||||
));
|
||||
|
||||
{
|
||||
const defs = await getDefinition(doc, new vscode.Position(0, 2), new InMemoryWorkspaceMarkdownDocuments([doc]));
|
||||
assertDefinitionsEqual(defs!,
|
||||
{ uri: docUri, line: 4 },
|
||||
);
|
||||
}
|
||||
{
|
||||
const defs = await getDefinition(doc, new vscode.Position(2, 7), new InMemoryWorkspaceMarkdownDocuments([doc]));
|
||||
assertDefinitionsEqual(defs!,
|
||||
{ uri: docUri, line: 4 },
|
||||
);
|
||||
}
|
||||
{
|
||||
const defs = await getDefinition(doc, new vscode.Position(4, 2), new InMemoryWorkspaceMarkdownDocuments([doc]));
|
||||
assertDefinitionsEqual(defs!,
|
||||
{ uri: docUri, line: 4 },
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('Should find definition links within file from definition', async () => {
|
||||
const docUri = workspacePath('doc.md');
|
||||
const doc = new InMemoryDocument(docUri, joinLines(
|
||||
`[link 1][abc]`,
|
||||
``,
|
||||
`[abc]: https://example.com`, // trigger here
|
||||
));
|
||||
|
||||
const defs = await getDefinition(doc, new vscode.Position(2, 3), new InMemoryWorkspaceMarkdownDocuments([doc]));
|
||||
assertDefinitionsEqual(defs!,
|
||||
{ uri: docUri, line: 2 },
|
||||
);
|
||||
});
|
||||
|
||||
test('Should not find definition links across files', async () => {
|
||||
const docUri = workspacePath('doc.md');
|
||||
const doc = new InMemoryDocument(docUri, joinLines(
|
||||
`[link 1][abc]`,
|
||||
``,
|
||||
`[abc]: https://example.com`,
|
||||
));
|
||||
|
||||
const defs = await getDefinition(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([
|
||||
doc,
|
||||
new InMemoryDocument(workspacePath('other.md'), joinLines(
|
||||
`[link 1][abc]`,
|
||||
``,
|
||||
`[abc]: https://example.com?bad`,
|
||||
))
|
||||
]));
|
||||
assertDefinitionsEqual(defs!,
|
||||
{ uri: docUri, line: 2 },
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue