Skip to content

Commit 3246d63

Browse files
authored
Merge pull request microsoft#203932 from microsoft/tyriar/203930
Don't recreate TerminalLinkManager after registered by ext
2 parents 7e2981e + 32ebbed commit 3246d63

File tree

3 files changed

+28
-26
lines changed

3 files changed

+28
-26
lines changed

src/vs/workbench/contrib/terminalContrib/links/browser/terminal.links.contribution.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,29 +55,24 @@ class TerminalLinkContribution extends DisposableStore implements ITerminalContr
5555

5656
// Set widget manager
5757
if (isTerminalProcessManager(this._processManager)) {
58-
const disposable = this.add(Event.once(this._processManager.onProcessReady)(() => {
58+
const disposable = linkManager.add(Event.once(this._processManager.onProcessReady)(() => {
5959
linkManager.setWidgetManager(this._widgetManager);
6060
this.delete(disposable);
6161
}));
6262
} else {
6363
linkManager.setWidgetManager(this._widgetManager);
6464
}
6565

66-
// Attach the link provider(s) to the instance and listen for changes
66+
// Attach the external link provider to the instance and listen for changes
6767
if (!isDetachedTerminalInstance(this._instance)) {
6868
for (const linkProvider of this._terminalLinkProviderService.linkProviders) {
69-
linkManager.registerExternalLinkProvider(linkProvider.provideLinks.bind(linkProvider, this._instance));
69+
linkManager.externalProvideLinksCb = linkProvider.provideLinks.bind(linkProvider, this._instance);
7070
}
7171
linkManager.add(this._terminalLinkProviderService.onDidAddLinkProvider(e => {
72-
linkManager.registerExternalLinkProvider(e.provideLinks.bind(e, this._instance as ITerminalInstance));
72+
linkManager.externalProvideLinksCb = e.provideLinks.bind(e, this._instance as ITerminalInstance);
7373
}));
7474
}
75-
76-
// TODO: Currently only a single link provider is supported; the one registered by the ext host
77-
linkManager.add(this._terminalLinkProviderService.onDidRemoveLinkProvider(e => {
78-
linkManager.dispose();
79-
this.xtermReady(xterm);
80-
}));
75+
linkManager.add(this._terminalLinkProviderService.onDidRemoveLinkProvider(() => linkManager.externalProvideLinksCb = undefined));
8176
}
8277

8378
async showLinkQuickpick(extended?: boolean): Promise<void> {

src/vs/workbench/contrib/terminalContrib/links/browser/terminalLinkManager.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export class TerminalLinkManager extends DisposableStore {
4545
private readonly _externalLinkProviders: IDisposable[] = [];
4646
private readonly _openers: Map<TerminalLinkType, ITerminalLinkOpener> = new Map();
4747

48+
externalProvideLinksCb?: OmitFirstArg<ITerminalExternalLinkProvider['provideLinks']>;
49+
4850
constructor(
4951
private readonly _xterm: Terminal,
5052
private readonly _processInfo: ITerminalProcessInfo,
@@ -349,25 +351,30 @@ export class TerminalLinkManager extends DisposableStore {
349351
}
350352

351353
private _registerStandardLinkProviders(): void {
354+
// Forward any external link provider requests to the registered provider if it exists. This
355+
// helps maintain the relative priority of the link providers as it's defined by the order
356+
// in which they're registered in xterm.js.
357+
//
358+
/**
359+
* There's a bit going on here but here's another view:
360+
* - {@link externalProvideLinksCb} The external callback that gives the links (eg. from
361+
* exthost)
362+
* - {@link proxyLinkProvider} A proxy that forwards the call over to
363+
* {@link externalProvideLinksCb}
364+
* - {@link wrappedLinkProvider} Wraps the above in an `TerminalLinkDetectorAdapter`
365+
*/
366+
const proxyLinkProvider: OmitFirstArg<ITerminalExternalLinkProvider['provideLinks']> = async (bufferLineNumber) => {
367+
return this.externalProvideLinksCb?.(bufferLineNumber);
368+
};
369+
const detectorId = `extension-${this._externalLinkProviders.length}`;
370+
const wrappedLinkProvider = this._setupLinkDetector(detectorId, new TerminalExternalLinkDetector(detectorId, this._xterm, proxyLinkProvider), true);
371+
this._linkProvidersDisposables.push(this._xterm.registerLinkProvider(wrappedLinkProvider));
372+
352373
for (const p of this._standardLinkProviders.values()) {
353374
this._linkProvidersDisposables.push(this._xterm.registerLinkProvider(p));
354375
}
355376
}
356377

357-
registerExternalLinkProvider(provideLinks: OmitFirstArg<ITerminalExternalLinkProvider['provideLinks']>): void {
358-
// Avoid any leaks in case this is already disposed
359-
if (this.isDisposed) {
360-
return;
361-
}
362-
// Clear and re-register the standard link providers so they are a lower priority than the new one
363-
this._clearLinkProviders();
364-
const detectorId = `extension-${this._externalLinkProviders.length}`;
365-
const wrappedLinkProvider = this._setupLinkDetector(detectorId, new TerminalExternalLinkDetector(detectorId, this._xterm, provideLinks), true);
366-
const newLinkProvider = this._xterm.registerLinkProvider(wrappedLinkProvider);
367-
this._externalLinkProviders.push(newLinkProvider);
368-
this._registerStandardLinkProviders();
369-
}
370-
371378
protected _isLinkActivationModifierDown(event: MouseEvent): boolean {
372379
const editorConf = this._configurationService.getValue<{ multiCursorModifier: 'ctrlCmd' | 'alt' }>('editor');
373380
if (editorConf.multiCursorModifier === 'ctrlCmd') {

src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalLinkManager.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ suite('TerminalLinkManager', () => {
101101

102102
suite('registerExternalLinkProvider', () => {
103103
test('should not leak disposables if the link manager is already disposed', () => {
104-
linkManager.registerExternalLinkProvider(async () => undefined);
104+
linkManager.externalProvideLinksCb = async () => undefined;
105105
linkManager.dispose();
106-
linkManager.registerExternalLinkProvider(async () => undefined);
106+
linkManager.externalProvideLinksCb = async () => undefined;
107107
});
108108
});
109109

0 commit comments

Comments
 (0)