提交 f3b8d15b 编写于 作者: M Matt Bierner

Add DocumentLink.tooltip api proposal

For #72824
上级 5b9869eb
...@@ -5,17 +5,20 @@ ...@@ -5,17 +5,20 @@
import * as path from 'path'; import * as path from 'path';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { OpenDocumentLinkCommand } from '../commands/openDocumentLink'; import { OpenDocumentLinkCommand } from '../commands/openDocumentLink';
import { getUriForLinkWithKnownExternalScheme } from '../util/links'; import { getUriForLinkWithKnownExternalScheme } from '../util/links';
function normalizeLink( const localize = nls.loadMessageBundle();
function parseLink(
document: vscode.TextDocument, document: vscode.TextDocument,
link: string, link: string,
base: string base: string
): vscode.Uri { ): { uri: vscode.Uri, tooltip?: string } {
const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link); const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link);
if (externalSchemeUri) { if (externalSchemeUri) {
return externalSchemeUri; return { uri: externalSchemeUri };
} }
// Assume it must be an relative or absolute file path // Assume it must be an relative or absolute file path
...@@ -34,7 +37,10 @@ function normalizeLink( ...@@ -34,7 +37,10 @@ function normalizeLink(
resourcePath = base ? path.join(base, tempUri.path) : tempUri.path; resourcePath = base ? path.join(base, tempUri.path) : tempUri.path;
} }
return OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment); return {
uri: OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment),
tooltip: localize('documentLink.tooltip', 'follow link')
};
} }
function matchAll( function matchAll(
...@@ -61,9 +67,12 @@ function extractDocumentLink( ...@@ -61,9 +67,12 @@ function extractDocumentLink(
const linkStart = document.positionAt(offset); const linkStart = document.positionAt(offset);
const linkEnd = document.positionAt(offset + link.length); const linkEnd = document.positionAt(offset + link.length);
try { try {
return new vscode.DocumentLink( const { uri, tooltip } = parseLink(document, link, base);
const documentLink = new vscode.DocumentLink(
new vscode.Range(linkStart, linkEnd), new vscode.Range(linkStart, linkEnd),
normalizeLink(document, link, base)); uri);
documentLink.tooltip = tooltip;
return documentLink;
} catch (e) { } catch (e) {
return undefined; return undefined;
} }
...@@ -144,11 +153,10 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { ...@@ -144,11 +153,10 @@ export default class LinkProvider implements vscode.DocumentLinkProvider {
} }
} }
for (const definition of Array.from(definitions.values())) { for (const definition of definitions.values()) {
try { try {
results.push(new vscode.DocumentLink( const { uri } = parseLink(document, definition.link, base);
definition.linkRange, results.push(new vscode.DocumentLink(definition.linkRange, uri));
normalizeLink(document, definition.link, base)));
} catch (e) { } catch (e) {
// noop // noop
} }
......
...@@ -1000,6 +1000,7 @@ export interface IInplaceReplaceSupportResult { ...@@ -1000,6 +1000,7 @@ export interface IInplaceReplaceSupportResult {
export interface ILink { export interface ILink {
range: IRange; range: IRange;
url?: URI | string; url?: URI | string;
tooltip?: string;
} }
export interface ILinksList { export interface ILinksList {
......
...@@ -27,7 +27,8 @@ export class Link implements ILink { ...@@ -27,7 +27,8 @@ export class Link implements ILink {
toJSON(): ILink { toJSON(): ILink {
return { return {
range: this.range, range: this.range,
url: this.url url: this.url,
tooltip: this.tooltip
}; };
} }
...@@ -39,6 +40,10 @@ export class Link implements ILink { ...@@ -39,6 +40,10 @@ export class Link implements ILink {
return this._link.url; return this._link.url;
} }
get tooltip(): string | undefined {
return this._link.tooltip;
}
resolve(token: CancellationToken): Promise<URI> { resolve(token: CancellationToken): Promise<URI> {
if (this._link.url) { if (this._link.url) {
try { try {
......
...@@ -111,6 +111,23 @@ class LinkOccurrence { ...@@ -111,6 +111,23 @@ class LinkOccurrence {
} }
private static _getOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions { private static _getOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions {
const options = { ...this._getBaseOptions(link, useMetaKey, isActive) };
if (typeof link.tooltip === 'string') {
const message = new MarkdownString().appendText(
platform.isMacintosh
? useMetaKey
? nls.localize('links.custom.mac', "Cmd + click to {0}", link.tooltip)
: nls.localize('links.custom.mac.al', "Option + click to {0}", link.tooltip)
: useMetaKey
? nls.localize('links.custom', "Ctrl + click to {0}", link.tooltip)
: nls.localize('links.custom.al', "Alt + click to {0}", link.tooltip)
);
options.hoverMessage = message;
}
return options;
}
private static _getBaseOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions {
if (link.url && /^command:/i.test(link.url.toString())) { if (link.url && /^command:/i.test(link.url.toString())) {
if (useMetaKey) { if (useMetaKey) {
return (isActive ? decoration.metaCommandActive : decoration.metaCommand); return (isActive ? decoration.metaCommandActive : decoration.metaCommand);
......
...@@ -5254,6 +5254,7 @@ declare namespace monaco.languages { ...@@ -5254,6 +5254,7 @@ declare namespace monaco.languages {
export interface ILink { export interface ILink {
range: IRange; range: IRange;
url?: Uri | string; url?: Uri | string;
tooltip?: string;
} }
export interface ILinksList { export interface ILinksList {
......
...@@ -1426,4 +1426,14 @@ declare module 'vscode' { ...@@ -1426,4 +1426,14 @@ declare module 'vscode' {
//#endregion //#endregion
//#region DocumentLink tooltip mjbvz
interface DocumentLink {
/**
* The tooltip text when you hover over this link.
*/
tooltip?: string;
}
// #endregion
} }
...@@ -996,6 +996,7 @@ export interface LinkDto { ...@@ -996,6 +996,7 @@ export interface LinkDto {
cacheId?: ChainedCacheId; cacheId?: ChainedCacheId;
range: IRange; range: IRange;
url?: string | UriComponents; url?: string | UriComponents;
tooltip?: string;
} }
export interface CodeLensDto extends ObjectIdentifier { export interface CodeLensDto extends ObjectIdentifier {
......
...@@ -808,7 +808,8 @@ export namespace DocumentLink { ...@@ -808,7 +808,8 @@ export namespace DocumentLink {
export function from(link: vscode.DocumentLink): modes.ILink { export function from(link: vscode.DocumentLink): modes.ILink {
return { return {
range: Range.from(link.range), range: Range.from(link.range),
url: link.target url: link.target,
tooltip: link.tooltip
}; };
} }
......
...@@ -1440,6 +1440,8 @@ export class DocumentLink { ...@@ -1440,6 +1440,8 @@ export class DocumentLink {
target?: URI; target?: URI;
tooltip?: string;
constructor(range: Range, target: URI | undefined) { constructor(range: Range, target: URI | undefined) {
if (target && !(target instanceof URI)) { if (target && !(target instanceof URI)) {
throw illegalArgument('target'); throw illegalArgument('target');
......
...@@ -1041,7 +1041,9 @@ suite('ExtHostLanguageFeatures', function () { ...@@ -1041,7 +1041,9 @@ suite('ExtHostLanguageFeatures', function () {
disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider { disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
provideDocumentLinks() { provideDocumentLinks() {
return [new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'))]; const link = new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'));
link.tooltip = 'tooltip';
return [link];
} }
})); }));
...@@ -1051,6 +1053,7 @@ suite('ExtHostLanguageFeatures', function () { ...@@ -1051,6 +1053,7 @@ suite('ExtHostLanguageFeatures', function () {
let [first] = links; let [first] = links;
assert.equal(first.url, 'foo:bar#3'); assert.equal(first.url, 'foo:bar#3');
assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 }); assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 });
assert.equal(first.tooltip, 'tooltip');
}); });
test('Links, evil provider', async () => { test('Links, evil provider', async () => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册