diff --git a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts index cc2159aebd0015..13a2dafbda0810 100644 --- a/src/vs/workbench/contrib/debug/browser/baseDebugView.ts +++ b/src/vs/workbench/contrib/debug/browser/baseDebugView.ts @@ -93,7 +93,7 @@ export function renderExpressionValue(expressionOrValue: IExpressionContainer | if (options.linkDetector) { container.textContent = ''; const session = (expressionOrValue instanceof ExpressionContainer) ? expressionOrValue.getSession() : undefined; - container.appendChild(options.linkDetector.linkify(value, false, session ? session.root : undefined)); + container.appendChild(options.linkDetector.linkify(value, false, session ? session.root : undefined, true)); } else { container.textContent = value; } diff --git a/src/vs/workbench/contrib/debug/browser/linkDetector.ts b/src/vs/workbench/contrib/debug/browser/linkDetector.ts index d6cd075ffa2ed7..4615c12f47a68a 100644 --- a/src/vs/workbench/contrib/debug/browser/linkDetector.ts +++ b/src/vs/workbench/contrib/debug/browser/linkDetector.ts @@ -57,7 +57,7 @@ export class LinkDetector { * When splitLines is true, each line of the text, even if it contains no links, is wrapped in a * and added as a child of the returned . */ - linkify(text: string, splitLines?: boolean, workspaceFolder?: IWorkspaceFolder): HTMLElement { + linkify(text: string, splitLines?: boolean, workspaceFolder?: IWorkspaceFolder, includeFulltext?: boolean): HTMLElement { if (splitLines) { const lines = text.split('\n'); for (let i = 0; i < lines.length - 1; i++) { @@ -67,7 +67,7 @@ export class LinkDetector { // Remove the last element ('') that split added. lines.pop(); } - const elements = lines.map(line => this.linkify(line, false, workspaceFolder)); + const elements = lines.map(line => this.linkify(line, false, workspaceFolder, includeFulltext)); if (elements.length === 1) { // Do not wrap single line with extra span. return elements[0]; @@ -85,13 +85,13 @@ export class LinkDetector { container.appendChild(document.createTextNode(part.value)); break; case 'web': - container.appendChild(this.createWebLink(part.value)); + container.appendChild(this.createWebLink(includeFulltext ? text : undefined, part.value)); break; case 'path': { const path = part.captures[0]; const lineNumber = part.captures[1] ? Number(part.captures[1]) : 0; const columnNumber = part.captures[2] ? Number(part.captures[2]) : 0; - container.appendChild(this.createPathLink(part.value, path, lineNumber, columnNumber, workspaceFolder)); + container.appendChild(this.createPathLink(includeFulltext ? text : undefined, part.value, path, lineNumber, columnNumber, workspaceFolder)); break; } } @@ -102,7 +102,7 @@ export class LinkDetector { return container; } - private createWebLink(url: string): Node { + private createWebLink(fulltext: string | undefined, url: string): Node { const link = this.createLink(url); let uri = URI.parse(url); @@ -116,7 +116,7 @@ export class LinkDetector { }); } - this.decorateLink(link, uri, async () => { + this.decorateLink(link, uri, fulltext, async () => { if (uri.scheme === Schemas.file) { // Just using fsPath here is unsafe: https://github.com/microsoft/vscode/issues/109076 @@ -146,7 +146,7 @@ export class LinkDetector { return link; } - private createPathLink(text: string, path: string, lineNumber: number, columnNumber: number, workspaceFolder: IWorkspaceFolder | undefined): Node { + private createPathLink(fulltext: string | undefined, text: string, path: string, lineNumber: number, columnNumber: number, workspaceFolder: IWorkspaceFolder | undefined): Node { if (path[0] === '/' && path[1] === '/') { // Most likely a url part which did not match, for example ftp://path. return document.createTextNode(text); @@ -159,7 +159,7 @@ export class LinkDetector { } const uri = workspaceFolder.toResource(path); const link = this.createLink(text); - this.decorateLink(link, uri, (preserveFocus: boolean) => this.editorService.openEditor({ resource: uri, options: { ...options, preserveFocus } })); + this.decorateLink(link, uri, fulltext, (preserveFocus: boolean) => this.editorService.openEditor({ resource: uri, options: { ...options, preserveFocus } })); return link; } @@ -177,7 +177,7 @@ export class LinkDetector { if (stat.isDirectory) { return; } - this.decorateLink(link, uri, (preserveFocus: boolean) => this.editorService.openEditor({ resource: uri, options: { ...options, preserveFocus } })); + this.decorateLink(link, uri, fulltext, (preserveFocus: boolean) => this.editorService.openEditor({ resource: uri, options: { ...options, preserveFocus } })); }).catch(() => { // If the uri can not be resolved we should not spam the console with error, remain quite #86587 }); @@ -190,10 +190,12 @@ export class LinkDetector { return link; } - private decorateLink(link: HTMLElement, uri: URI, onClick: (preserveFocus: boolean) => void) { + private decorateLink(link: HTMLElement, uri: URI, fulltext: string | undefined, onClick: (preserveFocus: boolean) => void) { link.classList.add('link'); const followLink = this.tunnelService.canTunnel(uri) ? localize('followForwardedLink', "follow link using forwarded port") : localize('followLink', "follow link"); - link.title = platform.isMacintosh ? localize('fileLinkMac', "Cmd + click to {0}", followLink) : localize('fileLink', "Ctrl + click to {0}", followLink); + link.title = fulltext + ? (platform.isMacintosh ? localize('fileLinkWithPathMac', "Cmd + click to {0}\n{1}", followLink, fulltext) : localize('fileLinkWithPath', "Ctrl + click to {0}\n{1}", followLink, fulltext)) + : (platform.isMacintosh ? localize('fileLinkMac', "Cmd + click to {0}", followLink) : localize('fileLink', "Ctrl + click to {0}", followLink)); link.onmousemove = (event) => { link.classList.toggle('pointer', platform.isMacintosh ? event.metaKey : event.ctrlKey); }; link.onmouseleave = () => link.classList.remove('pointer'); link.onclick = (event) => {