diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 5c43806131f17..cdbaf2293d4c5 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -927,35 +927,6 @@ declare module 'vscode' { //#endregion - //#region Terminal link handlers https://github.com/microsoft/vscode/issues/91606 - - export namespace window { - /** - * Register a [TerminalLinkHandler](#TerminalLinkHandler) that can be used to intercept and - * handle links that are activated within terminals. - * @param handler The link handler being registered. - * @return A disposable that unregisters the link handler. - */ - export function registerTerminalLinkHandler(handler: TerminalLinkHandler): Disposable; - } - - /** - * Describes how to handle terminal links. - */ - export interface TerminalLinkHandler { - /** - * Handles a link that is activated within the terminal. - * - * @param terminal The terminal the link was activated on. - * @param link The text of the link activated. - * @return Whether the link was handled, if the link was handled this link will not be - * considered by any other extension or by the default built-in link handler. - */ - handleLink(terminal: Terminal, link: string): ProviderResult; - } - - //#endregion - //#region @jrieken -> exclusive document filters export interface DocumentFilter { diff --git a/src/vs/workbench/api/browser/mainThreadTerminalService.ts b/src/vs/workbench/api/browser/mainThreadTerminalService.ts index ffd7fb0faee56..d518ec92f6e99 100644 --- a/src/vs/workbench/api/browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/browser/mainThreadTerminalService.ts @@ -9,7 +9,7 @@ import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceS import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { URI } from 'vs/base/common/uri'; import { StopWatch } from 'vs/base/common/stopwatch'; -import { ITerminalInstanceService, ITerminalService, ITerminalInstance, ITerminalBeforeHandleLinkEvent, ITerminalExternalLinkProvider, ITerminalLink } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalInstanceService, ITerminalService, ITerminalInstance, ITerminalExternalLinkProvider, ITerminalLink } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering'; @@ -25,7 +25,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape private readonly _toDispose = new DisposableStore(); private readonly _terminalProcessProxies = new Map(); private _dataEventTracker: TerminalDataEventTracker | undefined; - private _linkHandler: IDisposable | undefined; /** * A single shared terminal link provider for the exthost. When an ext registers a link * provider, this is registered with the terminal on the renderer side and all links are @@ -95,7 +94,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape public dispose(): void { this._toDispose.dispose(); - this._linkHandler?.dispose(); this._linkProvider?.dispose(); // TODO@Daniel: Should all the previously created terminals be disposed @@ -166,16 +164,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape } } - public $startHandlingLinks(): void { - this._linkHandler?.dispose(); - this._linkHandler = this._terminalService.addLinkHandler(this._remoteAuthority || '', e => this._handleLink(e)); - } - - public $stopHandlingLinks(): void { - this._linkHandler?.dispose(); - this._linkHandler = undefined; - } - public $startLinkProvider(): void { this._linkProvider?.dispose(); this._linkProvider = this._terminalService.registerLinkProvider(new ExtensionTerminalLinkProvider(this._proxy)); @@ -186,13 +174,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape this._linkProvider = undefined; } - private async _handleLink(e: ITerminalBeforeHandleLinkEvent): Promise { - if (!e.terminal) { - return false; - } - return this._proxy.$handleLink(e.terminal.id, e.link); - } - private _onActiveTerminalChanged(terminalId: number | null): void { this._proxy.$acceptActiveTerminalChanged(terminalId); } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index d31f206b57877..77f89a398a727 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -579,10 +579,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I } return extHostTerminalService.createTerminal(nameOrOptions, shellPath, shellArgs); }, - registerTerminalLinkHandler(handler: vscode.TerminalLinkHandler): vscode.Disposable { - checkProposedApiEnabled(extension); - return extHostTerminalService.registerLinkHandler(handler); - }, registerTerminalLinkProvider(handler: vscode.TerminalLinkProvider): vscode.Disposable { return extHostTerminalService.registerLinkProvider(handler); }, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 6caf716b6c6e3..0ad328d3549b5 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -448,8 +448,6 @@ export interface MainThreadTerminalServiceShape extends IDisposable { $show(terminalId: number, preserveFocus: boolean): void; $startSendingDataEvents(): void; $stopSendingDataEvents(): void; - $startHandlingLinks(): void; - $stopHandlingLinks(): void; $startLinkProvider(): void; $stopLinkProvider(): void; $setEnvironmentVariableCollection(extensionIdentifier: string, persistent: boolean, collection: ISerializableEnvironmentVariableCollection | undefined): void; @@ -1434,7 +1432,6 @@ export interface ExtHostTerminalServiceShape { $acceptWorkspacePermissionsChanged(isAllowed: boolean): void; $getAvailableShells(): Promise; $getDefaultShellAndArgs(useAutomationShell: boolean): Promise; - $handleLink(id: number, link: string): Promise; $provideLinks(id: number, line: string): Promise; $activateLink(id: number, linkId: number): void; $initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void; diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index ed8fd570cdd29..d49cb264c21b3 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -41,7 +41,6 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape { attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): void; getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string; getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string; - registerLinkHandler(handler: vscode.TerminalLinkHandler): vscode.Disposable; registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable; getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection; } @@ -318,7 +317,6 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ protected _environmentVariableCollections: Map = new Map(); private readonly _bufferer: TerminalDataBufferer; - private readonly _linkHandlers: Set = new Set(); private readonly _linkProviders: Set = new Set(); private readonly _terminalLinkCache: Map> = new Map(); private readonly _terminalLinkCancellationSource: Map = new Map(); @@ -559,19 +557,6 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ return id; } - public registerLinkHandler(handler: vscode.TerminalLinkHandler): vscode.Disposable { - this._linkHandlers.add(handler); - if (this._linkHandlers.size === 1 && this._linkProviders.size === 0) { - this._proxy.$startHandlingLinks(); - } - return new VSCodeDisposable(() => { - this._linkHandlers.delete(handler); - if (this._linkHandlers.size === 0 && this._linkProviders.size === 0) { - this._proxy.$stopHandlingLinks(); - } - }); - } - public registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable { this._linkProviders.add(provider); if (this._linkProviders.size === 1) { @@ -585,25 +570,6 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ }); } - public async $handleLink(id: number, link: string): Promise { - const terminal = this._getTerminalById(id); - if (!terminal) { - return false; - } - - // Call each handler synchronously so multiple handlers aren't triggered at once - const it = this._linkHandlers.values(); - let next = it.next(); - while (!next.done) { - const handled = await next.value.handleLink(terminal, link); - if (handled) { - return true; - } - next = it.next(); - } - return false; - } - public async $provideLinks(terminalId: number, line: string): Promise { const terminal = this._getTerminalById(terminalId); if (!terminal) { diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index 64434e1354850..00d3c14b5421d 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -16,11 +16,9 @@ import { IFileService } from 'vs/platform/files/common/files'; import { Terminal, IViewportRange, ILinkProvider } from 'xterm'; import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts'; import { posix, win32 } from 'vs/base/common/path'; -import { ITerminalBeforeHandleLinkEvent, LINK_INTERCEPT_THRESHOLD, ITerminalExternalLinkProvider, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalExternalLinkProvider, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; import { OperatingSystem, isMacintosh, OS } from 'vs/base/common/platform'; import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; -import { Emitter, Event } from 'vs/base/common/event'; -import { ILogService } from 'vs/platform/log/common/log'; import { TerminalProtocolLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalProtocolLinkProvider'; import { TerminalValidatedLocalLinkProvider, lineAndColumnClause, unixLocalLinkClause, winLocalLinkClause, winDrivePrefix, winLineAndColumnMatchIndex, unixLineAndColumnMatchIndex, lineAndColumnClauseGroupCount } from 'vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider'; import { TerminalWordLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalWordLinkProvider'; @@ -44,24 +42,9 @@ interface IPath { export class TerminalLinkManager extends DisposableStore { private _widgetManager: TerminalWidgetManager | undefined; private _processCwd: string | undefined; - private _hasBeforeHandleLinkListeners = false; private _standardLinkProviders: ILinkProvider[] = []; private _standardLinkProvidersDisposables: IDisposable[] = []; - protected static _LINK_INTERCEPT_THRESHOLD = LINK_INTERCEPT_THRESHOLD; - public static readonly LINK_INTERCEPT_THRESHOLD = TerminalLinkManager._LINK_INTERCEPT_THRESHOLD; - - private readonly _onBeforeHandleLink = this.add(new Emitter({ - onFirstListenerAdd: () => this._hasBeforeHandleLinkListeners = true, - onLastListenerRemove: () => this._hasBeforeHandleLinkListeners = false - })); - /** - * Allows intercepting links and handling them outside of the default link handler. When fired - * the listener has a set amount of time to handle the link or the default handler will fire. - * This was designed to only be handled by a single listener. - */ - public get onBeforeHandleLink(): Event { return this._onBeforeHandleLink.event; } - constructor( private _xterm: Terminal, private readonly _processManager: ITerminalProcessManager, @@ -69,14 +52,13 @@ export class TerminalLinkManager extends DisposableStore { @IEditorService private readonly _editorService: IEditorService, @IConfigurationService private readonly _configurationService: IConfigurationService, @IFileService private readonly _fileService: IFileService, - @ILogService private readonly _logService: ILogService, @IInstantiationService private readonly _instantiationService: IInstantiationService ) { super(); // Protocol links const wrappedActivateCallback = this._wrapLinkHandler((_, link) => this._handleProtocolLink(link)); - const protocolProvider = this._instantiationService.createInstance(TerminalProtocolLinkProvider, this._xterm, wrappedActivateCallback, this._tooltipCallback2.bind(this)); + const protocolProvider = this._instantiationService.createInstance(TerminalProtocolLinkProvider, this._xterm, wrappedActivateCallback, this._tooltipCallback.bind(this)); this._standardLinkProviders.push(protocolProvider); // Validated local links @@ -87,19 +69,19 @@ export class TerminalLinkManager extends DisposableStore { this._processManager.os || OS, wrappedTextLinkActivateCallback, this._wrapLinkHandler.bind(this), - this._tooltipCallback2.bind(this), + this._tooltipCallback.bind(this), async (link, cb) => cb(await this._resolvePath(link))); this._standardLinkProviders.push(validatedProvider); } // Word links - const wordProvider = this._instantiationService.createInstance(TerminalWordLinkProvider, this._xterm, this._wrapLinkHandler.bind(this), this._tooltipCallback2.bind(this)); + const wordProvider = this._instantiationService.createInstance(TerminalWordLinkProvider, this._xterm, this._wrapLinkHandler.bind(this), this._tooltipCallback.bind(this)); this._standardLinkProviders.push(wordProvider); this._registerStandardLinkProviders(); } - private _tooltipCallback2(link: TerminalLink, viewportRange: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) { + private _tooltipCallback(link: TerminalLink, viewportRange: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) { if (!this._widgetManager) { return; } @@ -156,7 +138,7 @@ export class TerminalLinkManager extends DisposableStore { } public registerExternalLinkProvider(instance: ITerminalInstance, linkProvider: ITerminalExternalLinkProvider): IDisposable { - const wrappedLinkProvider = this._instantiationService.createInstance(TerminalExternalLinkProviderAdapter, this._xterm, instance, linkProvider, this._wrapLinkHandler.bind(this), this._tooltipCallback2.bind(this)); + const wrappedLinkProvider = this._instantiationService.createInstance(TerminalExternalLinkProviderAdapter, this._xterm, instance, linkProvider, this._wrapLinkHandler.bind(this), this._tooltipCallback.bind(this)); const newLinkProvider = this._xterm.registerLinkProvider(wrappedLinkProvider); // Re-register the standard link providers so they are a lower priority that the new one this._registerStandardLinkProviders(); @@ -173,38 +155,11 @@ export class TerminalLinkManager extends DisposableStore { return; } - // Allow the link to be intercepted if there are listeners - if (this._hasBeforeHandleLinkListeners) { - const wasHandled = await this._triggerBeforeHandleLinkListeners(link); - if (!wasHandled) { - handler(event, link); - } - return; - } - // Just call the handler if there is no before listener handler(event, link); }; } - private async _triggerBeforeHandleLinkListeners(link: string): Promise { - return new Promise(r => { - const timeoutId = setTimeout(() => { - canceled = true; - this._logService.error(`An extension intecepted a terminal link but it timed out after ${TerminalLinkManager.LINK_INTERCEPT_THRESHOLD / 1000} seconds`); - r(false); - }, TerminalLinkManager.LINK_INTERCEPT_THRESHOLD); - let canceled = false; - const resolve = (handled: boolean) => { - if (!canceled) { - clearTimeout(timeoutId); - r(handled); - } - }; - this._onBeforeHandleLink.fire({ link, resolve }); - }); - } - protected get _localLinkRegex(): RegExp { if (!this._processManager) { throw new Error('Process manager is required'); @@ -369,7 +324,6 @@ export class TerminalLinkManager extends DisposableStore { * @param link Url link which may contain line and column number. */ public extractLineColumnInfo(link: string): LineColumnInfo { - const matches: string[] | null = this._localLinkRegex.exec(link); const lineColumnInfo: LineColumnInfo = { lineNumber: 1, diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 3909857123455..81c21a4351186 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -136,14 +136,6 @@ export interface ITerminalService { findNext(): void; findPrevious(): void; - /** - * Link handlers can be registered here to allow intercepting links clicked in the terminal. - * When a link is clicked, the link will be considered handled when the first interceptor - * resolves with true. It will be considered not handled when _all_ link handlers resolve with - * false, or 3 seconds have elapsed. - */ - addLinkHandler(key: string, callback: TerminalLinkHandlerCallback): IDisposable; - /** * Registers a link provider that enables integrators to add links to the terminal. * @param linkProvider When registered, the link provider is asked whenever a cell is hovered @@ -215,8 +207,6 @@ export enum WindowsShellType { } export type TerminalShellType = WindowsShellType | undefined; -export const LINK_INTERCEPT_THRESHOLD = 3000; - export interface ITerminalBeforeHandleLinkEvent { terminal?: ITerminalInstance; /** The text of the link */ @@ -225,8 +215,6 @@ export interface ITerminalBeforeHandleLinkEvent { resolve(wasHandled: boolean): void; } -export type TerminalLinkHandlerCallback = (e: ITerminalBeforeHandleLinkEvent) => Promise; - export interface ITerminalInstance { /** * The ID of the terminal instance, this is an arbitrary number only used to identify the @@ -289,11 +277,6 @@ export interface ITerminalInstance { */ onExit: Event; - /** - * Attach a listener to intercept and handle link clicks in the terminal. - */ - onBeforeHandleLink: Event; - readonly exitCode: number | undefined; readonly areLinksReady: boolean; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 6ca7013814707..ee16eb81e97e6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -30,7 +30,7 @@ import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGR import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; -import { ITerminalInstanceService, ITerminalInstance, TerminalShellType, WindowsShellType, ITerminalBeforeHandleLinkEvent, ITerminalExternalLinkProvider } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalInstanceService, ITerminalInstance, TerminalShellType, WindowsShellType, ITerminalExternalLinkProvider } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager'; import { Terminal as XTermTerminal, IBuffer, ITerminalAddon } from 'xterm'; import { SearchAddon, ISearchOptions } from 'xterm-addon-search'; @@ -164,8 +164,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { public get onMaximumDimensionsChanged(): Event { return this._onMaximumDimensionsChanged.event; } private readonly _onFocus = new Emitter(); public get onFocus(): Event { return this._onFocus.event; } - private readonly _onBeforeHandleLink = new Emitter(); - public get onBeforeHandleLink(): Event { return this._onBeforeHandleLink.event; } public constructor( private readonly _terminalFocusContextKey: IContextKey, @@ -419,10 +417,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { }); } this._linkManager = this._instantiationService.createInstance(TerminalLinkManager, xterm, this._processManager!); - this._linkManager.onBeforeHandleLink(e => { - e.terminal = this; - this._onBeforeHandleLink.fire(e); - }); this._areLinksReady = true; this._onLinksReady.fire(this); }); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index cb0c8c2fca021..2fcce1787c217 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -14,7 +14,7 @@ import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; -import { ITerminalService, ITerminalInstance, ITerminalTab, TerminalShellType, WindowsShellType, TerminalLinkHandlerCallback, LINK_INTERCEPT_THRESHOLD, ITerminalExternalLinkProvider } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalService, ITerminalInstance, ITerminalTab, TerminalShellType, WindowsShellType, ITerminalExternalLinkProvider } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; @@ -50,7 +50,6 @@ export class TerminalService implements ITerminalService { private _findState: FindReplaceState; private _extHostsReady: { [authority: string]: IExtHostReadyEntry | undefined } = {}; private _activeTabIndex: number; - private _linkHandlers: { [key: string]: TerminalLinkHandlerCallback } = {}; private _linkProviders: Set = new Set(); private _linkProviderDisposables: Map = new Map(); @@ -428,50 +427,6 @@ export class TerminalService implements ITerminalService { instance.addDisposable(instance.onDimensionsChanged(() => this._onInstanceDimensionsChanged.fire(instance))); instance.addDisposable(instance.onMaximumDimensionsChanged(() => this._onInstanceMaximumDimensionsChanged.fire(instance))); instance.addDisposable(instance.onFocus(this._onActiveInstanceChanged.fire, this._onActiveInstanceChanged)); - instance.addDisposable(instance.onBeforeHandleLink(async e => { - // No link handlers have been registered - const keys = Object.keys(this._linkHandlers); - if (keys.length === 0) { - e.resolve(false); - return; - } - - // Fire each link interceptor and wait for either a true, all false or the cancel time - let resolved = false; - const promises: Promise[] = []; - const timeout = setTimeout(() => { - resolved = true; - e.resolve(false); - }, LINK_INTERCEPT_THRESHOLD); - for (let i = 0; i < keys.length; i++) { - const p = this._linkHandlers[keys[i]](e); - p.then(handled => { - if (!resolved && handled) { - resolved = true; - clearTimeout(timeout); - e.resolve(true); - } - }); - promises.push(p); - } - await Promise.all(promises); - if (!resolved) { - resolved = true; - clearTimeout(timeout); - e.resolve(false); - } - })); - } - - public addLinkHandler(key: string, callback: TerminalLinkHandlerCallback): IDisposable { - this._linkHandlers[key] = callback; - return { - dispose: () => { - if (this._linkHandlers[key] === callback) { - delete this._linkHandlers[key]; - } - } - }; } public registerLinkProvider(linkProvider: ITerminalExternalLinkProvider): IDisposable { diff --git a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts deleted file mode 100644 index 2223e0d082a8e..0000000000000 --- a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts +++ /dev/null @@ -1,163 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { OperatingSystem } from 'vs/base/common/platform'; -import { TerminalLinkManager, XtermLinkMatcherHandler } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; -import { Terminal as XtermTerminal } from 'xterm'; -import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { Event } from 'vs/base/common/event'; -import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; -import { TestPathService, TestEnvironmentService } from 'vs/workbench/test/browser/workbenchTestServices'; -import { IPathService } from 'vs/workbench/services/path/common/pathService'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; - -class TestTerminalLinkManager extends TerminalLinkManager { - public get localLinkRegex(): RegExp { - return this._localLinkRegex; - } - public preprocessPath(link: string): string | null { - return this._preprocessPath(link); - } - protected _isLinkActivationModifierDown(event: MouseEvent): boolean { - return true; - } - public wrapLinkHandler(handler: (link: string) => void): XtermLinkMatcherHandler { - TerminalLinkManager._LINK_INTERCEPT_THRESHOLD = 0; - return this._wrapLinkHandler((_, link) => handler(link)); - } -} - -class MockTerminalInstanceService implements ITerminalInstanceService { - onRequestDefaultShellAndArgs?: Event | undefined; - getDefaultShellAndArgs(): Promise<{ shell: string; args: string | string[] | undefined; }> { - throw new Error('Method not implemented.'); - } - declare readonly _serviceBrand: undefined; - getXtermConstructor(): Promise { - throw new Error('Method not implemented.'); - } - getXtermSearchConstructor(): Promise { - throw new Error('Method not implemented.'); - } - getXtermUnicode11Constructor(): Promise { - throw new Error('Method not implemented.'); - } - getXtermWebglConstructor(): Promise { - throw new Error('Method not implemented.'); - } - createWindowsShellHelper(): any { - throw new Error('Method not implemented.'); - } - createTerminalProcess(): any { - throw new Error('Method not implemented.'); - } - getMainProcessParentEnv(): any { - throw new Error('Method not implemented.'); - } -} - -suite('Workbench - TerminalLinkManager', () => { - let instantiationService: TestInstantiationService; - - setup(async () => { - const configurationService = new TestConfigurationService(); - await configurationService.setUserConfiguration('terminal', { integrated: { enableFileLinks: true } }); - - instantiationService = new TestInstantiationService(); - instantiationService.stub(IEnvironmentService, TestEnvironmentService); - instantiationService.stub(IPathService, new TestPathService()); - instantiationService.stub(ITerminalInstanceService, new MockTerminalInstanceService()); - instantiationService.stub(IConfigurationService, configurationService); - }); - - suite('preprocessPath', () => { - test('Windows', () => { - const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, { - os: OperatingSystem.Windows, - userHome: 'C:\\Users\\Me' - } as any); - linkHandler.processCwd = 'C:\\base'; - - assert.equal(linkHandler.preprocessPath('./src/file1'), 'C:\\base\\src\\file1'); - assert.equal(linkHandler.preprocessPath('src\\file2'), 'C:\\base\\src\\file2'); - assert.equal(linkHandler.preprocessPath('~/src/file3'), 'C:\\Users\\Me\\src\\file3'); - assert.equal(linkHandler.preprocessPath('~\\src\\file4'), 'C:\\Users\\Me\\src\\file4'); - assert.equal(linkHandler.preprocessPath('C:\\absolute\\path\\file5'), 'C:\\absolute\\path\\file5'); - assert.equal(linkHandler.preprocessPath('\\\\?\\C:\\absolute\\path\\extended\\file6'), 'C:\\absolute\\path\\extended\\file6'); - }); - test('Windows - spaces', () => { - const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, { - os: OperatingSystem.Windows, - userHome: 'C:\\Users\\M e' - } as any); - linkHandler.processCwd = 'C:\\base dir'; - - assert.equal(linkHandler.preprocessPath('./src/file1'), 'C:\\base dir\\src\\file1'); - assert.equal(linkHandler.preprocessPath('src\\file2'), 'C:\\base dir\\src\\file2'); - assert.equal(linkHandler.preprocessPath('~/src/file3'), 'C:\\Users\\M e\\src\\file3'); - assert.equal(linkHandler.preprocessPath('~\\src\\file4'), 'C:\\Users\\M e\\src\\file4'); - assert.equal(linkHandler.preprocessPath('C:\\abso lute\\path\\file5'), 'C:\\abso lute\\path\\file5'); - }); - - test('Linux', () => { - const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, { - os: OperatingSystem.Linux, - userHome: '/home/me' - } as any); - linkHandler.processCwd = '/base'; - - assert.equal(linkHandler.preprocessPath('./src/file1'), '/base/src/file1'); - assert.equal(linkHandler.preprocessPath('src/file2'), '/base/src/file2'); - assert.equal(linkHandler.preprocessPath('~/src/file3'), '/home/me/src/file3'); - assert.equal(linkHandler.preprocessPath('/absolute/path/file4'), '/absolute/path/file4'); - }); - - test('No Workspace', () => { - const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, { - os: OperatingSystem.Linux, - userHome: '/home/me' - } as any); - - assert.equal(linkHandler.preprocessPath('./src/file1'), null); - assert.equal(linkHandler.preprocessPath('src/file2'), null); - assert.equal(linkHandler.preprocessPath('~/src/file3'), '/home/me/src/file3'); - assert.equal(linkHandler.preprocessPath('/absolute/path/file4'), '/absolute/path/file4'); - }); - }); - - suite('wrapLinkHandler', () => { - const nullMouseEvent: any = Object.freeze({ preventDefault: () => { } }); - - test('should allow intercepting of links with onBeforeHandleLink', async () => { - const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, { - os: OperatingSystem.Linux, - userHome: '' - } as any); - linkHandler.onBeforeHandleLink(e => { - if (e.link === 'https://www.microsoft.com') { - intercepted = true; - e.resolve(true); - } - e.resolve(false); - }); - const wrappedHandler = linkHandler.wrapLinkHandler(() => defaultHandled = true); - - let defaultHandled = false; - let intercepted = false; - await wrappedHandler(nullMouseEvent, 'https://www.visualstudio.com'); - assert.equal(intercepted, false); - assert.equal(defaultHandled, true); - - defaultHandled = false; - intercepted = false; - await wrappedHandler(nullMouseEvent, 'https://www.microsoft.com'); - assert.equal(intercepted, true); - assert.equal(defaultHandled, false); - }); - }); -});