Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

output channel: new replaceAll API to improve output channel rendering #136402

Merged
merged 9 commits into from
Nov 8, 2021
15 changes: 15 additions & 0 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2833,4 +2833,19 @@ declare module 'vscode' {
}

//#endregion

//#region https://github.com/microsoft/vscode/issues/132183
export interface OutputChannel {

/*
* Replaces the existing contents of the channel with the given value.
*
* *Note*: this method should only be used by extensions with smaller output
* channel text sizes. Use of `append` methods is preferred.
*/
replaceAll(value: string): void;

}

//#endregion
}
8 changes: 8 additions & 0 deletions src/vs/workbench/api/browser/mainThreadOutputService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
return undefined;
}

public $replaceAll(channelId: string, till: number, value: string): Promise<void> | undefined {
const channel = this._getChannel(channelId);
smcenlly marked this conversation as resolved.
Show resolved Hide resolved
if (channel) {
channel.replaceAll(till, value);
}
return undefined;
}

public $reveal(channelId: string, preserveFocus: boolean): Promise<void> | undefined {
const channel = this._getChannel(channelId);
if (channel) {
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ export interface MainThreadOutputServiceShape extends IDisposable {
$append(channelId: string, value: string): Promise<void> | undefined;
$update(channelId: string): Promise<void> | undefined;
$clear(channelId: string, till: number): Promise<void> | undefined;
$replaceAll(channelId: string, till: number, value: string): Promise<void> | undefined;
$reveal(channelId: string, preserveFocus: boolean): Promise<void> | undefined;
$close(channelId: string): Promise<void> | undefined;
$dispose(channelId: string): Promise<void> | undefined;
Expand Down
27 changes: 22 additions & 5 deletions src/vs/workbench/api/common/extHostOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';

export abstract class AbstractExtHostOutputChannel extends Disposable implements vscode.OutputChannel {

Expand All @@ -20,18 +21,20 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements
protected readonly _proxy: MainThreadOutputServiceShape;
private _disposed: boolean;
private _offset: number;
private _extension: IExtensionDescription | undefined;

protected readonly _onDidAppend: Emitter<void> = this._register(new Emitter<void>());
readonly onDidAppend: Event<void> = this._onDidAppend.event;

constructor(name: string, log: boolean, file: URI | undefined, extensionId: string | undefined, proxy: MainThreadOutputServiceShape) {
constructor(name: string, log: boolean, file: URI | undefined, extension: IExtensionDescription | undefined, proxy: MainThreadOutputServiceShape) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the | undefined portion is for testing? For such cases there exists nullExtensionDescription which can than enable stricter typings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't - I am not that familiar with the codebase. Will update the type. Thanks for the feedback :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use nullExtensionDescription and changed type to be IExtensionDescription instead of IExtensionDescription | undefined.

super();

this._name = name;
this._proxy = proxy;
this._id = proxy.$register(this.name, log, file, extensionId);
this._id = proxy.$register(this.name, log, file, extension?.identifier.value);
this._disposed = false;
this._offset = 0;
this._extension = extension;
}

get name(): string {
Expand All @@ -58,6 +61,17 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements
this._id.then(id => this._proxy.$clear(id, till));
}

replaceAll(value: string): void {
if (this._extension) {
checkProposedApiEnabled(this._extension);
}

this.validate();
const till = this._offset;
this._offset += value ? VSBuffer.fromString(value).byteLength : 0;
this._id.then(id => this._proxy.$replaceAll(id, till, value));
}

show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
this.validate();
this._id.then(id => this._proxy.$reveal(id, !!(typeof columnOrPreserveFocus === 'boolean' ? columnOrPreserveFocus : preserveFocus)));
Expand Down Expand Up @@ -87,8 +101,8 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements

export class ExtHostPushOutputChannel extends AbstractExtHostOutputChannel {

constructor(name: string, extensionId: string, proxy: MainThreadOutputServiceShape) {
super(name, false, undefined, extensionId, proxy);
constructor(name: string, extension: IExtensionDescription, proxy: MainThreadOutputServiceShape) {
super(name, false, undefined, extension, proxy);
}

override append(value: string): void {
Expand Down Expand Up @@ -125,6 +139,9 @@ export class LazyOutputChannel implements vscode.OutputChannel {
clear(): void {
this._channel.then(channel => channel.clear());
}
replaceAll(value: string): void {
this._channel.then(channel => channel.replaceAll(value));
}
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
this._channel.then(channel => channel.show(columnOrPreserveFocus, preserveFocus));
}
Expand Down Expand Up @@ -154,7 +171,7 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
if (!name) {
throw new Error('illegal argument `name`. must not be falsy');
}
return new ExtHostPushOutputChannel(name, extension.identifier.value, this._proxy);
return new ExtHostPushOutputChannel(name, extension, this._proxy);
}

createOutputChannelFromLogFile(name: string, file: URI): vscode.OutputChannel {
Expand Down
14 changes: 10 additions & 4 deletions src/vs/workbench/api/node/extHostOutputService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChannel {

private _appender: OutputAppender;

constructor(name: string, appender: OutputAppender, extensionId: string, proxy: MainThreadOutputServiceShape) {
super(name, false, URI.file(appender.file), extensionId, proxy);
constructor(name: string, appender: OutputAppender, extension: IExtensionDescription, proxy: MainThreadOutputServiceShape) {
super(name, false, URI.file(appender.file), extension, proxy);
this._appender = appender;
}

Expand All @@ -55,6 +55,12 @@ class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChannel {
this._onDidAppend.fire();
}

override replaceAll(value: string): void {
this._appender.append(value);
this._appender.flush();
super.replaceAll(value);
}

override update(): void {
this._appender.flush();
super.update();
Expand Down Expand Up @@ -116,11 +122,11 @@ export class ExtHostOutputService2 extends ExtHostOutputService {
const fileName = `${this._namePool++}-${name.replace(/[\\/:\*\?"<>\|]/g, '')}`;
const file = URI.file(join(outputDirPath, `${fileName}.log`));
const appender = await OutputAppender.create(fileName, file.fsPath);
return new ExtHostOutputChannelBackedByFile(name, appender, extension.identifier.value, this._proxy);
return new ExtHostOutputChannelBackedByFile(name, appender, extension, this._proxy);
} catch (error) {
// Do not crash if logger cannot be created
this.logService.error(error);
return new ExtHostPushOutputChannel(name, extension.identifier.value, this._proxy);
return new ExtHostPushOutputChannel(name, extension, this._proxy);
}
}
}
4 changes: 4 additions & 0 deletions src/vs/workbench/contrib/output/browser/outputServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class OutputChannel extends Disposable implements IOutputChannel {
clear(till?: number): void {
this.model.clear(till);
}

replaceAll(till: number, value: string): void {
this.model.replaceAll(till, value);
}
}

export class OutputService extends Disposable implements IOutputService, ITextModelContentProvider {
Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/contrib/output/common/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ export interface IOutputChannel {
*/
clear(till?: number): void;

/**
* Replaces the output of the channel.
*/
replaceAll(till: number, value: string): void;

/**
* Disposes the output channel.
*/
Expand Down
Loading