Skip to content

Commit 588d6e7

Browse files
committed
Cherrypick PR #2907
1 parent 1cda783 commit 588d6e7

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

src/client/common/terminal/activator/base.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,33 @@
44
'use strict';
55

66
import { Terminal, Uri } from 'vscode';
7-
import { sleep } from '../../../../utils/async';
7+
import { createDeferred, sleep } from '../../../../utils/async';
88
import { ITerminalActivator, ITerminalHelper, TerminalShellType } from '../types';
99

1010
export class BaseTerminalActivator implements ITerminalActivator {
11-
private readonly activatedTerminals: Set<Terminal> = new Set<Terminal>();
11+
private readonly activatedTerminals: Map<Terminal, Promise<boolean>> = new Map<Terminal, Promise<boolean>>();
1212
constructor(private readonly helper: ITerminalHelper) { }
1313
public async activateEnvironmentInTerminal(terminal: Terminal, resource: Uri | undefined, preserveFocus: boolean = true) {
1414
if (this.activatedTerminals.has(terminal)) {
15-
return false;
15+
return this.activatedTerminals.get(terminal)!;
1616
}
17-
this.activatedTerminals.add(terminal);
17+
const deferred = createDeferred<boolean>();
18+
this.activatedTerminals.set(terminal, deferred.promise);
1819
const shellPath = this.helper.getTerminalShellPath();
1920
const terminalShellType = !shellPath || shellPath.length === 0 ? TerminalShellType.other : this.helper.identifyTerminalShell(shellPath);
2021

2122
const activationCommamnds = await this.helper.getEnvironmentActivationCommands(terminalShellType, resource);
23+
let activated = false;
2224
if (activationCommamnds) {
2325
for (const command of activationCommamnds!) {
2426
terminal.show(preserveFocus);
2527
terminal.sendText(command);
2628
await this.waitForCommandToProcess(terminalShellType);
29+
activated = true;
2730
}
28-
return true;
29-
} else {
30-
return false;
3131
}
32+
deferred.resolve(activated);
33+
return activated;
3234
}
3335
protected async waitForCommandToProcess(shell: TerminalShellType) {
3436
// Give the command some time to complete.

src/test/common/terminals/activator/base.unit.test.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33

44
'use strict';
55

6+
import { expect } from 'chai';
67
import * as TypeMoq from 'typemoq';
78
import { Terminal } from 'vscode';
89
import { BaseTerminalActivator } from '../../../../client/common/terminal/activator/base';
910
import { ITerminalActivator, ITerminalHelper } from '../../../../client/common/terminal/types';
1011
import { noop } from '../../../../utils/misc';
1112

12-
// tslint:disable-next-line:max-func-body-length
13-
suite('Terminalx Base Activator', () => {
13+
// tslint:disable:max-func-body-length no-any
14+
suite('Terminal Base Activator', () => {
1415
let activator: ITerminalActivator;
1516
let helper: TypeMoq.IMock<ITerminalHelper>;
1617

1718
setup(() => {
1819
helper = TypeMoq.Mock.ofType<ITerminalHelper>();
1920
activator = new class extends BaseTerminalActivator {
2021
public waitForCommandToProcess() { noop(); return Promise.resolve(); }
21-
}(helper.object);
22+
}(helper.object) as any as ITerminalActivator;
2223
});
2324
[
2425
{ commandCount: 1, preserveFocus: false },
@@ -70,5 +71,30 @@ suite('Terminalx Base Activator', () => {
7071

7172
terminal.verifyAll();
7273
});
74+
test(`Terminal is activated only once ${titleSuffix} (even when not waiting)`, async () => {
75+
helper.setup(h => h.getTerminalShellPath()).returns(() => '');
76+
helper.setup(h => h.getEnvironmentActivationCommands(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve(activationCommands));
77+
const terminal = TypeMoq.Mock.ofType<Terminal>();
78+
79+
terminal
80+
.setup(t => t.show(TypeMoq.It.isValue(item.preserveFocus)))
81+
.returns(() => undefined)
82+
.verifiable(TypeMoq.Times.exactly(activationCommands.length));
83+
activationCommands.forEach(cmd => {
84+
terminal
85+
.setup(t => t.sendText(TypeMoq.It.isValue(cmd)))
86+
.returns(() => undefined)
87+
.verifiable(TypeMoq.Times.exactly(1));
88+
});
89+
90+
const activated = await Promise.all([
91+
activator.activateEnvironmentInTerminal(terminal.object, undefined, item.preserveFocus),
92+
activator.activateEnvironmentInTerminal(terminal.object, undefined, item.preserveFocus),
93+
activator.activateEnvironmentInTerminal(terminal.object, undefined, item.preserveFocus)
94+
]);
95+
96+
terminal.verifyAll();
97+
expect(activated).to.deep.equal([true, true, true], 'Invalid values');
98+
});
7399
});
74100
});

0 commit comments

Comments
 (0)