Skip to content

Commit d4ac309

Browse files
author
Kartik Raj
authored
Moved Language Server logging to its own output channel (microsoft#6821)
* Created new output channel and added tests * News entry * Fix tests * Localize stuff
1 parent 261a134 commit d4ac309

14 files changed

Lines changed: 241 additions & 114 deletions

File tree

news/1 Enhancements/6559.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Moved Language Server logging to its own output channel

package.nls.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@
119119
"Logging.CurrentWorkingDirectory": "cwd:",
120120
"Common.doNotShowAgain": "Do not show again",
121121
"Common.reload": "Reload",
122+
"OutputChannelNames.languageServer": "Python Language Server",
123+
"OutputChannelNames.python": "Python",
124+
"OutputChannelNames.pythonTest": "Python Test Log",
122125
"ExtensionChannels.installingInsidersMessage": "Installing Insiders... ",
123126
"ExtensionChannels.installingStableMessage": "Installing Stable... ",
124127
"ExtensionChannels.installationCompleteMessage": "complete.",

src/client/activation/languageServer/analysisOptions.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
Disposable,
1212
Event,
1313
EventEmitter,
14-
OutputChannel,
1514
Position,
1615
TextDocument,
1716
Uri,
@@ -27,7 +26,7 @@ import {
2726
} from 'vscode-languageclient';
2827

2928
import { IWorkspaceService } from '../../common/application/types';
30-
import { HiddenFilePrefix, isTestExecution, PYTHON_LANGUAGE, STANDARD_OUTPUT_CHANNEL } from '../../common/constants';
29+
import { HiddenFilePrefix, isTestExecution, PYTHON_LANGUAGE } from '../../common/constants';
3130
import { traceDecorators, traceError } from '../../common/logger';
3231
import {
3332
BANNER_NAME_LS_SURVEY,
@@ -41,7 +40,7 @@ import {
4140
import { debounceSync } from '../../common/utils/decorators';
4241
import { IEnvironmentVariablesProvider } from '../../common/variables/types';
4342
import { IInterpreterService } from '../../interpreter/contracts';
44-
import { ILanguageServerAnalysisOptions, ILanguageServerFolderService } from '../types';
43+
import { ILanguageServerAnalysisOptions, ILanguageServerFolderService, ILanguageServerOutputChannel } from '../types';
4544

4645
@injectable()
4746
export class LanguageServerAnalysisOptions implements ILanguageServerAnalysisOptions {
@@ -51,17 +50,19 @@ export class LanguageServerAnalysisOptions implements ILanguageServerAnalysisOpt
5150
private disposables: Disposable[] = [];
5251
private languageServerFolder: string = '';
5352
private resource: Resource;
53+
private output: IOutputChannel;
5454
private readonly didChange = new EventEmitter<void>();
5555
constructor(@inject(IExtensionContext) private readonly context: IExtensionContext,
5656
@inject(IEnvironmentVariablesProvider) private readonly envVarsProvider: IEnvironmentVariablesProvider,
5757
@inject(IConfigurationService) private readonly configuration: IConfigurationService,
5858
@inject(IWorkspaceService) private readonly workspace: IWorkspaceService,
5959
@inject(IPythonExtensionBanner) @named(BANNER_NAME_LS_SURVEY) private readonly surveyBanner: IPythonExtensionBanner,
6060
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
61-
@inject(IOutputChannel) @named(STANDARD_OUTPUT_CHANNEL) private readonly output: OutputChannel,
61+
@inject(ILanguageServerOutputChannel) private readonly lsOutputChannel: ILanguageServerOutputChannel,
6262
@inject(IPathUtils) private readonly pathUtils: IPathUtils,
63-
@inject(ILanguageServerFolderService) private readonly languageServerFolderService: ILanguageServerFolderService) {
64-
63+
@inject(ILanguageServerFolderService) private readonly languageServerFolderService: ILanguageServerFolderService
64+
) {
65+
this.output = this.lsOutputChannel.channel;
6566
}
6667
public async initialize(resource: Resource) {
6768
this.resource = resource;

src/client/activation/languageServer/downloader.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33

44
'use strict';
55

6-
import { inject, injectable, named } from 'inversify';
6+
import { inject, injectable } from 'inversify';
77
import * as path from 'path';
88
import { ProgressLocation, window } from 'vscode';
99
import { IApplicationShell, IWorkspaceService } from '../../common/application/types';
10-
import { STANDARD_OUTPUT_CHANNEL } from '../../common/constants';
1110
import '../../common/extensions';
1211
import { IFileSystem } from '../../common/platform/types';
1312
import { IFileDownloader, IOutputChannel, Resource } from '../../common/types';
@@ -18,6 +17,7 @@ import { sendTelemetryEvent } from '../../telemetry';
1817
import { EventName } from '../../telemetry/constants';
1918
import {
2019
ILanguageServerDownloader, ILanguageServerFolderService,
20+
ILanguageServerOutputChannel,
2121
IPlatformData
2222
} from '../types';
2323

@@ -27,15 +27,17 @@ const downloadFileExtension = '.nupkg';
2727

2828
@injectable()
2929
export class LanguageServerDownloader implements ILanguageServerDownloader {
30+
private output: IOutputChannel;
3031
constructor(
3132
@inject(IPlatformData) private readonly platformData: IPlatformData,
32-
@inject(IOutputChannel) @named(STANDARD_OUTPUT_CHANNEL) private readonly output: IOutputChannel,
33+
@inject(ILanguageServerOutputChannel) private readonly lsOutputChannel: ILanguageServerOutputChannel,
3334
@inject(IFileDownloader) private readonly fileDownloader: IFileDownloader,
3435
@inject(ILanguageServerFolderService) private readonly lsFolderService: ILanguageServerFolderService,
3536
@inject(IApplicationShell) private readonly appShell: IApplicationShell,
3637
@inject(IFileSystem) private readonly fs: IFileSystem,
3738
@inject(IWorkspaceService) private readonly workspace: IWorkspaceService
3839
) {
40+
this.output = this.lsOutputChannel.channel;
3941
}
4042

4143
public async getDownloadInfo(resource: Resource) {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
import { inject, injectable } from 'inversify';
7+
import { IApplicationShell } from '../../common/application/types';
8+
import { IOutputChannel } from '../../common/types';
9+
import { OutputChannelNames } from '../../common/utils/localize';
10+
import { ILanguageServerOutputChannel } from '../types';
11+
12+
@injectable()
13+
export class LanguageServerOutputChannel implements ILanguageServerOutputChannel {
14+
public output: IOutputChannel | undefined;
15+
constructor(
16+
@inject(IApplicationShell) private readonly appShell: IApplicationShell
17+
) { }
18+
19+
public get channel() {
20+
if (!this.output) {
21+
this.output = this.appShell.createOutputChannel(OutputChannelNames.languageServer());
22+
}
23+
return this.output;
24+
}
25+
}

src/client/activation/serviceRegistry.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ import { LanguageServerFolderService } from './languageServer/languageServerFold
2525
import { BetaLanguageServerPackageRepository, DailyLanguageServerPackageRepository, LanguageServerDownloadChannel, StableLanguageServerPackageRepository } from './languageServer/languageServerPackageRepository';
2626
import { LanguageServerPackageService } from './languageServer/languageServerPackageService';
2727
import { LanguageServerManager } from './languageServer/manager';
28+
import { LanguageServerOutputChannel } from './languageServer/outputChannel';
2829
import { PlatformData } from './languageServer/platformData';
29-
import { IDownloadChannelRule, IExtensionActivationManager, IExtensionActivationService, ILanguageClientFactory, ILanguageServer, ILanguageServerActivator, ILanguageServerAnalysisOptions, ILanguageServerCompatibilityService as ILanagueServerCompatibilityService, ILanguageServerDownloader, ILanguageServerExtension, ILanguageServerFolderService, ILanguageServerManager, ILanguageServerPackageService, IPlatformData, LanguageClientFactory, LanguageServerActivator } from './types';
30+
import { IDownloadChannelRule, IExtensionActivationManager, IExtensionActivationService, ILanguageClientFactory, ILanguageServer, ILanguageServerActivator, ILanguageServerAnalysisOptions, ILanguageServerCompatibilityService as ILanagueServerCompatibilityService, ILanguageServerDownloader, ILanguageServerExtension, ILanguageServerFolderService, ILanguageServerManager, ILanguageServerOutputChannel, ILanguageServerPackageService, IPlatformData, LanguageClientFactory, LanguageServerActivator } from './types';
3031

3132
export function registerTypes(serviceManager: IServiceManager) {
3233
serviceManager.addSingleton<IExtensionActivationService>(IExtensionActivationService, LanguageServerExtensionActivationService);
@@ -55,4 +56,5 @@ export function registerTypes(serviceManager: IServiceManager) {
5556
serviceManager.add<ILanguageServerAnalysisOptions>(ILanguageServerAnalysisOptions, LanguageServerAnalysisOptions);
5657
serviceManager.addSingleton<ILanguageServer>(ILanguageServer, LanguageServer);
5758
serviceManager.add<ILanguageServerManager>(ILanguageServerManager, LanguageServerManager);
59+
serviceManager.addSingleton<ILanguageServerOutputChannel>(ILanguageServerOutputChannel, LanguageServerOutputChannel);
5860
}

src/client/activation/types.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { SemVer } from 'semver';
77
import { Event } from 'vscode';
88
import { LanguageClient, LanguageClientOptions } from 'vscode-languageclient';
99
import { NugetPackage } from '../common/nuget/types';
10-
import { IDisposable, LanguageServerDownloadChannels, Resource } from '../common/types';
10+
import { IDisposable, IOutputChannel, LanguageServerDownloadChannels, Resource } from '../common/types';
1111

1212
export const IExtensionActivationManager = Symbol('IExtensionActivationManager');
1313
export interface IExtensionActivationManager extends IDisposable {
@@ -123,3 +123,14 @@ export interface IPlatformData {
123123
readonly engineDllName: string;
124124
readonly engineExecutableName: string;
125125
}
126+
127+
export const ILanguageServerOutputChannel = Symbol('ILanguageServerOutputChannel');
128+
export interface ILanguageServerOutputChannel {
129+
/**
130+
* Creates output channel if necessary and returns it
131+
*
132+
* @type {IOutputChannel}
133+
* @memberof ILanguageServerOutputChannel
134+
*/
135+
readonly channel: IOutputChannel;
136+
}
Lines changed: 85 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,85 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
2-
// Licensed under the MIT License.
3-
'use strict';
4-
5-
// tslint:disable:no-var-requires no-any unified-signatures
6-
7-
import { injectable } from 'inversify';
8-
import { CancellationToken, Disposable, env, InputBox, InputBoxOptions, MessageItem, MessageOptions, OpenDialogOptions, Progress, ProgressOptions, QuickPick, QuickPickItem, QuickPickOptions, SaveDialogOptions, StatusBarAlignment, StatusBarItem, TreeView, TreeViewOptions, Uri, window, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
9-
import { IApplicationShell } from './types';
10-
11-
@injectable()
12-
export class ApplicationShell implements IApplicationShell {
13-
public showInformationMessage(message: string, ...items: string[]): Thenable<string>;
14-
public showInformationMessage(message: string, options: MessageOptions, ...items: string[]): Thenable<string>;
15-
public showInformationMessage<T extends MessageItem>(message: string, ...items: T[]): Thenable<T>;
16-
public showInformationMessage<T extends MessageItem>(message: string, options: MessageOptions, ...items: T[]): Thenable<T>;
17-
public showInformationMessage(message: string, options?: any, ...items: any[]): Thenable<any> {
18-
return window.showInformationMessage(message, options, ...items);
19-
}
20-
21-
public showWarningMessage(message: string, ...items: string[]): Thenable<string>;
22-
public showWarningMessage(message: string, options: MessageOptions, ...items: string[]): Thenable<string>;
23-
public showWarningMessage<T extends MessageItem>(message: string, ...items: T[]): Thenable<T>;
24-
public showWarningMessage<T extends MessageItem>(message: string, options: MessageOptions, ...items: T[]): Thenable<T>;
25-
public showWarningMessage(message: any, options?: any, ...items: any[]) {
26-
return window.showWarningMessage(message, options, ...items);
27-
}
28-
29-
public showErrorMessage(message: string, ...items: string[]): Thenable<string>;
30-
public showErrorMessage(message: string, options: MessageOptions, ...items: string[]): Thenable<string>;
31-
public showErrorMessage<T extends MessageItem>(message: string, ...items: T[]): Thenable<T>;
32-
public showErrorMessage<T extends MessageItem>(message: string, options: MessageOptions, ...items: T[]): Thenable<T>;
33-
public showErrorMessage(message: any, options?: any, ...items: any[]) {
34-
return window.showErrorMessage(message, options, ...items);
35-
}
36-
37-
public showQuickPick(items: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string>;
38-
public showQuickPick<T extends QuickPickItem>(items: T[] | Thenable<T[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<T>;
39-
public showQuickPick(items: any, options?: any, token?: any): Thenable<any> {
40-
return window.showQuickPick(items, options, token);
41-
}
42-
43-
public showOpenDialog(options: OpenDialogOptions): Thenable<Uri[] | undefined> {
44-
return window.showOpenDialog(options);
45-
}
46-
public showSaveDialog(options: SaveDialogOptions): Thenable<Uri | undefined> {
47-
return window.showSaveDialog(options);
48-
}
49-
public showInputBox(options?: InputBoxOptions, token?: CancellationToken): Thenable<string | undefined> {
50-
return window.showInputBox(options, token);
51-
}
52-
public openUrl(url: string): void {
53-
env.openExternal(Uri.parse(url));
54-
}
55-
56-
public setStatusBarMessage(text: string, hideAfterTimeout: number): Disposable;
57-
public setStatusBarMessage(text: string, hideWhenDone: Thenable<any>): Disposable;
58-
public setStatusBarMessage(text: string): Disposable;
59-
public setStatusBarMessage(text: string, arg?: any): Disposable {
60-
return window.setStatusBarMessage(text, arg);
61-
}
62-
63-
public createStatusBarItem(alignment?: StatusBarAlignment, priority?: number): StatusBarItem {
64-
return window.createStatusBarItem(alignment, priority);
65-
}
66-
public showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions): Thenable<WorkspaceFolder | undefined> {
67-
return window.showWorkspaceFolderPick(options);
68-
}
69-
public withProgress<R>(options: ProgressOptions, task: (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => Thenable<R>): Thenable<R> {
70-
return window.withProgress<R>(options, task);
71-
}
72-
public createQuickPick<T extends QuickPickItem>(): QuickPick<T> {
73-
return window.createQuickPick<T>();
74-
}
75-
public createInputBox(): InputBox {
76-
return window.createInputBox();
77-
}
78-
public createTreeView<T>(viewId: string, options: TreeViewOptions<T>): TreeView<T> {
79-
return window.createTreeView<T>(viewId, options);
80-
}
81-
82-
}
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
'use strict';
4+
5+
// tslint:disable:no-var-requires no-any unified-signatures
6+
7+
import { injectable } from 'inversify';
8+
import { CancellationToken, Disposable, env, InputBox, InputBoxOptions, MessageItem, MessageOptions, OpenDialogOptions, OutputChannel, Progress, ProgressOptions, QuickPick, QuickPickItem, QuickPickOptions, SaveDialogOptions, StatusBarAlignment, StatusBarItem, TreeView, TreeViewOptions, Uri, window, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
9+
import { IApplicationShell } from './types';
10+
11+
@injectable()
12+
export class ApplicationShell implements IApplicationShell {
13+
public showInformationMessage(message: string, ...items: string[]): Thenable<string>;
14+
public showInformationMessage(message: string, options: MessageOptions, ...items: string[]): Thenable<string>;
15+
public showInformationMessage<T extends MessageItem>(message: string, ...items: T[]): Thenable<T>;
16+
public showInformationMessage<T extends MessageItem>(message: string, options: MessageOptions, ...items: T[]): Thenable<T>;
17+
public showInformationMessage(message: string, options?: any, ...items: any[]): Thenable<any> {
18+
return window.showInformationMessage(message, options, ...items);
19+
}
20+
21+
public showWarningMessage(message: string, ...items: string[]): Thenable<string>;
22+
public showWarningMessage(message: string, options: MessageOptions, ...items: string[]): Thenable<string>;
23+
public showWarningMessage<T extends MessageItem>(message: string, ...items: T[]): Thenable<T>;
24+
public showWarningMessage<T extends MessageItem>(message: string, options: MessageOptions, ...items: T[]): Thenable<T>;
25+
public showWarningMessage(message: any, options?: any, ...items: any[]) {
26+
return window.showWarningMessage(message, options, ...items);
27+
}
28+
29+
public showErrorMessage(message: string, ...items: string[]): Thenable<string>;
30+
public showErrorMessage(message: string, options: MessageOptions, ...items: string[]): Thenable<string>;
31+
public showErrorMessage<T extends MessageItem>(message: string, ...items: T[]): Thenable<T>;
32+
public showErrorMessage<T extends MessageItem>(message: string, options: MessageOptions, ...items: T[]): Thenable<T>;
33+
public showErrorMessage(message: any, options?: any, ...items: any[]) {
34+
return window.showErrorMessage(message, options, ...items);
35+
}
36+
37+
public showQuickPick(items: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string>;
38+
public showQuickPick<T extends QuickPickItem>(items: T[] | Thenable<T[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<T>;
39+
public showQuickPick(items: any, options?: any, token?: any): Thenable<any> {
40+
return window.showQuickPick(items, options, token);
41+
}
42+
43+
public showOpenDialog(options: OpenDialogOptions): Thenable<Uri[] | undefined> {
44+
return window.showOpenDialog(options);
45+
}
46+
public showSaveDialog(options: SaveDialogOptions): Thenable<Uri | undefined> {
47+
return window.showSaveDialog(options);
48+
}
49+
public showInputBox(options?: InputBoxOptions, token?: CancellationToken): Thenable<string | undefined> {
50+
return window.showInputBox(options, token);
51+
}
52+
public openUrl(url: string): void {
53+
env.openExternal(Uri.parse(url));
54+
}
55+
56+
public setStatusBarMessage(text: string, hideAfterTimeout: number): Disposable;
57+
public setStatusBarMessage(text: string, hideWhenDone: Thenable<any>): Disposable;
58+
public setStatusBarMessage(text: string): Disposable;
59+
public setStatusBarMessage(text: string, arg?: any): Disposable {
60+
return window.setStatusBarMessage(text, arg);
61+
}
62+
63+
public createStatusBarItem(alignment?: StatusBarAlignment, priority?: number): StatusBarItem {
64+
return window.createStatusBarItem(alignment, priority);
65+
}
66+
public showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions): Thenable<WorkspaceFolder | undefined> {
67+
return window.showWorkspaceFolderPick(options);
68+
}
69+
public withProgress<R>(options: ProgressOptions, task: (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => Thenable<R>): Thenable<R> {
70+
return window.withProgress<R>(options, task);
71+
}
72+
public createQuickPick<T extends QuickPickItem>(): QuickPick<T> {
73+
return window.createQuickPick<T>();
74+
}
75+
public createInputBox(): InputBox {
76+
return window.createInputBox();
77+
}
78+
public createTreeView<T>(viewId: string, options: TreeViewOptions<T>): TreeView<T> {
79+
return window.createTreeView<T>(viewId, options);
80+
}
81+
public createOutputChannel(name: string): OutputChannel {
82+
return window.createOutputChannel(name);
83+
}
84+
85+
}

src/client/common/application/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ import {
5151
WorkspaceEdit,
5252
WorkspaceFolder,
5353
WorkspaceFolderPickOptions,
54-
WorkspaceFoldersChangeEvent
54+
WorkspaceFoldersChangeEvent,
55+
OutputChannel
5556
} from 'vscode';
5657
import * as vsls from 'vsls/vscode';
5758

@@ -347,6 +348,13 @@ export interface IApplicationShell {
347348
* @returns a [TreeView](#TreeView).
348349
*/
349350
createTreeView<T>(viewId: string, options: TreeViewOptions<T>): TreeView<T>;
351+
352+
/**
353+
* Creates a new [output channel](#OutputChannel) with the given name.
354+
*
355+
* @param name Human-readable string which will be used to represent the channel in the UI.
356+
*/
357+
createOutputChannel(name: string): OutputChannel;
350358
}
351359

352360
export const ICommandManager = Symbol('ICommandManager');

0 commit comments

Comments
 (0)