Skip to content

Commit 4a6ddd8

Browse files
committed
change output channel to handle dispose.
1 parent 8e8357a commit 4a6ddd8

File tree

3 files changed

+121
-120
lines changed

3 files changed

+121
-120
lines changed

src/client/activation/common/outputChannel.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,30 @@
66
import { inject, injectable } from 'inversify';
77
import { IApplicationShell, ICommandManager } from '../../common/application/types';
88
import '../../common/extensions';
9-
import { IDisposableRegistry, ILogOutputChannel } from '../../common/types';
9+
import { IDisposable, ILogOutputChannel } from '../../common/types';
1010
import { OutputChannelNames } from '../../common/utils/localize';
1111
import { ILanguageServerOutputChannel } from '../types';
1212

1313
@injectable()
1414
export class LanguageServerOutputChannel implements ILanguageServerOutputChannel {
1515
public output: ILogOutputChannel | undefined;
16-
16+
private disposables: IDisposable[] = [];
1717
private registered = false;
1818

1919
constructor(
2020
@inject(IApplicationShell) private readonly appShell: IApplicationShell,
2121
@inject(ICommandManager) private readonly commandManager: ICommandManager,
22-
@inject(IDisposableRegistry) private readonly disposable: IDisposableRegistry,
2322
) {}
2423

24+
public dispose(): void {
25+
this.disposables.forEach((d) => d && d.dispose());
26+
this.disposables = [];
27+
}
28+
2529
public get channel(): ILogOutputChannel {
2630
if (!this.output) {
2731
this.output = this.appShell.createOutputChannel(OutputChannelNames.JediLanguageServer);
28-
this.disposable.push(this.output);
32+
this.disposables.push(this.output);
2933
this.registerCommand().ignoreErrors();
3034
}
3135
return this.output;
@@ -39,10 +43,10 @@ export class LanguageServerOutputChannel implements ILanguageServerOutputChannel
3943
// This controls the visibility of the command used to display the LS Output panel.
4044
// We don't want to display it when Jedi is used instead of LS.
4145
await this.commandManager.executeCommand('setContext', 'python.hasLanguageServerOutputChannel', true);
42-
this.disposable.push(
46+
this.disposables.push(
4347
this.commandManager.registerCommand('python.viewLanguageServerOutput', () => this.output?.show(true)),
4448
);
45-
this.disposable.push({
49+
this.disposables.push({
4650
dispose: () => {
4751
this.registered = false;
4852
},

src/client/languageServer/jediLSExtensionManager.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
IConfigurationService,
1414
Resource,
1515
IDisposable,
16-
IDisposableRegistry,
1716
} from '../common/types';
1817
import { IEnvironmentVariablesProvider } from '../common/variables/types';
1918
import { IInterpreterService } from '../interpreter/contracts';
@@ -43,9 +42,7 @@ export class JediLSExtensionManager implements IDisposable, ILanguageServerExten
4342
commandManager: ICommandManager,
4443
) {
4544
const appShell = serviceContainer.get<IApplicationShell>(IApplicationShell);
46-
const disposableRegistry = serviceContainer.get<IDisposableRegistry>(IDisposableRegistry);
47-
48-
this.outputChannel = new LanguageServerOutputChannel(appShell, commandManager, disposableRegistry);
45+
this.outputChannel = new LanguageServerOutputChannel(appShell, commandManager);
4946
this.analysisOptions = new JediLanguageServerAnalysisOptions(
5047
environmentService,
5148
this.outputChannel,
Lines changed: 110 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,123 @@
1-
// // Copyright (c) Microsoft Corporation. All rights reserved.
2-
// // Licensed under the MIT License.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
33

4-
// 'use strict';
4+
'use strict';
55

6-
// import { expect } from 'chai';
7-
// import * as TypeMoq from 'typemoq';
8-
// import { LanguageServerOutputChannel } from '../../client/activation/common/outputChannel';
9-
// import { IApplicationShell, ICommandManager } from '../../client/common/application/types';
10-
// import { ILogOutputChannel } from '../../client/common/types';
11-
// import { sleep } from '../../client/common/utils/async';
12-
// import { OutputChannelNames } from '../../client/common/utils/localize';
6+
import { expect } from 'chai';
7+
import * as TypeMoq from 'typemoq';
8+
import { LanguageServerOutputChannel } from '../../client/activation/common/outputChannel';
9+
import { IApplicationShell, ICommandManager } from '../../client/common/application/types';
10+
import { ILogOutputChannel } from '../../client/common/types';
11+
import { sleep } from '../../client/common/utils/async';
12+
import { OutputChannelNames } from '../../client/common/utils/localize';
1313

14-
// suite('Language Server Output Channel', () => {
15-
// let appShell: TypeMoq.IMock<IApplicationShell>;
16-
// let languageServerOutputChannel: LanguageServerOutputChannel;
17-
// let commandManager: TypeMoq.IMock<ICommandManager>;
18-
// let output: TypeMoq.IMock<ILogOutputChannel>;
19-
// setup(() => {
20-
// appShell = TypeMoq.Mock.ofType<IApplicationShell>();
21-
// output = TypeMoq.Mock.ofType<ILogOutputChannel>();
22-
// commandManager = TypeMoq.Mock.ofType<ICommandManager>();
23-
// languageServerOutputChannel = new LanguageServerOutputChannel(output, commandManager.object, []);
24-
// });
14+
suite('Language Server Output Channel', () => {
15+
let appShell: TypeMoq.IMock<IApplicationShell>;
16+
let languageServerOutputChannel: LanguageServerOutputChannel;
17+
let commandManager: TypeMoq.IMock<ICommandManager>;
18+
let output: TypeMoq.IMock<ILogOutputChannel>;
19+
setup(() => {
20+
appShell = TypeMoq.Mock.ofType<IApplicationShell>();
21+
output = TypeMoq.Mock.ofType<ILogOutputChannel>();
22+
commandManager = TypeMoq.Mock.ofType<ICommandManager>();
23+
languageServerOutputChannel = new LanguageServerOutputChannel(appShell.object, commandManager.object);
24+
});
2525

26-
// test('Create output channel if one does not exist before and return it', async () => {
27-
// appShell
28-
// .setup((a) => a.createOutputChannel(OutputChannelNames.languageServer))
29-
// .returns(() => output.object)
30-
// .verifiable(TypeMoq.Times.once());
31-
// const { channel } = languageServerOutputChannel;
32-
// appShell.verifyAll();
33-
// expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
34-
// });
26+
test('Create output channel if one does not exist before and return it', async () => {
27+
appShell
28+
.setup((a) => a.createOutputChannel(OutputChannelNames.JediLanguageServer))
29+
.returns(() => output.object)
30+
.verifiable(TypeMoq.Times.once());
31+
const { channel } = languageServerOutputChannel;
32+
appShell.verifyAll();
33+
expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
34+
});
3535

36-
// test('Do not create output channel if one already exists', async () => {
37-
// languageServerOutputChannel.output = output.object;
38-
// appShell
39-
// .setup((a) => a.createOutputChannel(TypeMoq.It.isAny()))
40-
// .returns(() => output.object)
41-
// .verifiable(TypeMoq.Times.never());
42-
// const { channel } = languageServerOutputChannel;
43-
// appShell.verifyAll();
44-
// expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
45-
// });
46-
// test('Register Command to display output panel', async () => {
47-
// appShell
48-
// .setup((a) => a.createOutputChannel(TypeMoq.It.isAny()))
49-
// .returns(() => output.object)
50-
// .verifiable(TypeMoq.Times.once());
51-
// commandManager
52-
// .setup((c) =>
53-
// c.executeCommand(
54-
// TypeMoq.It.isValue('setContext'),
55-
// TypeMoq.It.isValue('python.hasLanguageServerOutputChannel'),
56-
// TypeMoq.It.isValue(true),
57-
// ),
58-
// )
59-
// .returns(() => Promise.resolve())
60-
// .verifiable(TypeMoq.Times.once());
61-
// commandManager
62-
// .setup((c) => c.registerCommand(TypeMoq.It.isValue('python.viewLanguageServerOutput'), TypeMoq.It.isAny()))
63-
// .verifiable(TypeMoq.Times.once());
36+
test('Do not create output channel if one already exists', async () => {
37+
languageServerOutputChannel.output = output.object;
38+
appShell
39+
.setup((a) => a.createOutputChannel(TypeMoq.It.isAny()))
40+
.returns(() => output.object)
41+
.verifiable(TypeMoq.Times.never());
42+
const { channel } = languageServerOutputChannel;
43+
appShell.verifyAll();
44+
expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
45+
});
46+
test('Register Command to display output panel', async () => {
47+
appShell
48+
.setup((a) => a.createOutputChannel(TypeMoq.It.isAny()))
49+
.returns(() => output.object)
50+
.verifiable(TypeMoq.Times.once());
51+
commandManager
52+
.setup((c) =>
53+
c.executeCommand(
54+
TypeMoq.It.isValue('setContext'),
55+
TypeMoq.It.isValue('python.hasLanguageServerOutputChannel'),
56+
TypeMoq.It.isValue(true),
57+
),
58+
)
59+
.returns(() => Promise.resolve())
60+
.verifiable(TypeMoq.Times.once());
61+
commandManager
62+
.setup((c) => c.registerCommand(TypeMoq.It.isValue('python.viewLanguageServerOutput'), TypeMoq.It.isAny()))
63+
.verifiable(TypeMoq.Times.once());
6464

65-
// // Doesn't matter how many times we access channel property.
66-
// let { channel } = languageServerOutputChannel;
67-
// channel = languageServerOutputChannel.channel;
68-
// channel = languageServerOutputChannel.channel;
65+
// Doesn't matter how many times we access channel property.
66+
let { channel } = languageServerOutputChannel;
67+
channel = languageServerOutputChannel.channel;
68+
channel = languageServerOutputChannel.channel;
6969

70-
// await sleep(1);
70+
await sleep(1);
7171

72-
// appShell.verifyAll();
73-
// commandManager.verifyAll();
74-
// expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
75-
// });
76-
// test('Display panel when invoking command python.viewLanguageServerOutput', async () => {
77-
// let cmdCallback: () => unknown | undefined = () => {
78-
// /* no-op */
79-
// };
80-
// appShell
81-
// .setup((a) => a.createOutputChannel(TypeMoq.It.isAny()))
82-
// .returns(() => output.object)
83-
// .verifiable(TypeMoq.Times.once());
84-
// commandManager
85-
// .setup((c) =>
86-
// c.executeCommand(
87-
// TypeMoq.It.isValue('setContext'),
88-
// TypeMoq.It.isValue('python.hasLanguageServerOutputChannel'),
89-
// TypeMoq.It.isValue(true),
90-
// ),
91-
// )
92-
// .returns(() => Promise.resolve())
93-
// .verifiable(TypeMoq.Times.once());
94-
// commandManager
95-
// .setup((c) => c.registerCommand(TypeMoq.It.isValue('python.viewLanguageServerOutput'), TypeMoq.It.isAny()))
96-
// .callback((_: string, callback: () => unknown) => {
97-
// cmdCallback = callback;
98-
// })
99-
// .verifiable(TypeMoq.Times.once());
100-
// output.setup((o) => o.show(true)).verifiable(TypeMoq.Times.never());
101-
// // Doesn't matter how many times we access channel property.
102-
// let { channel } = languageServerOutputChannel;
103-
// channel = languageServerOutputChannel.channel;
104-
// channel = languageServerOutputChannel.channel;
72+
appShell.verifyAll();
73+
commandManager.verifyAll();
74+
expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
75+
});
76+
test('Display panel when invoking command python.viewLanguageServerOutput', async () => {
77+
let cmdCallback: () => unknown | undefined = () => {
78+
/* no-op */
79+
};
80+
appShell
81+
.setup((a) => a.createOutputChannel(TypeMoq.It.isAny()))
82+
.returns(() => output.object)
83+
.verifiable(TypeMoq.Times.once());
84+
commandManager
85+
.setup((c) =>
86+
c.executeCommand(
87+
TypeMoq.It.isValue('setContext'),
88+
TypeMoq.It.isValue('python.hasLanguageServerOutputChannel'),
89+
TypeMoq.It.isValue(true),
90+
),
91+
)
92+
.returns(() => Promise.resolve())
93+
.verifiable(TypeMoq.Times.once());
94+
commandManager
95+
.setup((c) => c.registerCommand(TypeMoq.It.isValue('python.viewLanguageServerOutput'), TypeMoq.It.isAny()))
96+
.callback((_: string, callback: () => unknown) => {
97+
cmdCallback = callback;
98+
})
99+
.verifiable(TypeMoq.Times.once());
100+
output.setup((o) => o.show(true)).verifiable(TypeMoq.Times.never());
101+
// Doesn't matter how many times we access channel property.
102+
let { channel } = languageServerOutputChannel;
103+
channel = languageServerOutputChannel.channel;
104+
channel = languageServerOutputChannel.channel;
105105

106-
// await sleep(1);
106+
await sleep(1);
107107

108-
// appShell.verifyAll();
109-
// commandManager.verifyAll();
110-
// output.verifyAll();
111-
// expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
112-
// expect(cmdCallback).to.not.equal(undefined, 'Command handler should not be undefined');
108+
appShell.verifyAll();
109+
commandManager.verifyAll();
110+
output.verifyAll();
111+
expect(channel).to.not.equal(undefined, 'Channel should not be undefined');
112+
expect(cmdCallback).to.not.equal(undefined, 'Command handler should not be undefined');
113113

114-
// // Confirm panel is displayed when command handler is invoked.
115-
// output.reset();
116-
// output.setup((o) => o.show(true)).verifiable(TypeMoq.Times.once());
114+
// Confirm panel is displayed when command handler is invoked.
115+
output.reset();
116+
output.setup((o) => o.show(true)).verifiable(TypeMoq.Times.once());
117117

118-
// // Invoke callback.
119-
// cmdCallback!();
118+
// Invoke callback.
119+
cmdCallback!();
120120

121-
// output.verifyAll();
122-
// });
123-
// });
121+
output.verifyAll();
122+
});
123+
});

0 commit comments

Comments
 (0)