提交 979273be 编写于 作者: S Sandeep Somavarapu

Fix #69689

上级 6877b809
......@@ -86,8 +86,11 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
public $close(channelId: string): Promise<void> | undefined {
const panel = this._panelService.getActivePanel();
if (panel && panel.getId() === OUTPUT_PANEL_ID && channelId === this._outputService.getActiveChannel().id) {
this._partService.setPanelHidden(true);
if (panel && panel.getId() === OUTPUT_PANEL_ID) {
const activeChannel = this._outputService.getActiveChannel();
if (activeChannel && channelId === activeChannel.id) {
this._partService.setPanelHidden(true);
}
}
return undefined;
......@@ -101,7 +104,7 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
return undefined;
}
private _getChannel(channelId: string): IOutputChannel {
private _getChannel(channelId: string): IOutputChannel | null {
return this._outputService.getChannel(channelId);
}
}
......@@ -17,7 +17,7 @@ import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorIn
import { URI } from 'vs/base/common/uri';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { LOG_SCHEME, IOutputChannelDescriptor } from 'vs/workbench/contrib/output/common/output';
import { LOG_SCHEME, IFileOutputChannelDescriptor } from 'vs/workbench/contrib/output/common/output';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWindowService } from 'vs/platform/windows/common/windows';
......@@ -26,7 +26,7 @@ export class LogViewerInput extends ResourceEditorInput {
public static readonly ID = 'workbench.editorinputs.output';
constructor(private outputChannelDescriptor: IOutputChannelDescriptor,
constructor(private outputChannelDescriptor: IFileOutputChannelDescriptor,
@ITextModelService textModelResolverService: ITextModelService,
@IHashService hashService: IHashService
) {
......
......@@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { IAction, Action } from 'vs/base/common/actions';
import { IOutputService, OUTPUT_PANEL_ID, IOutputChannelRegistry, Extensions as OutputExt, IOutputChannelDescriptor } from 'vs/workbench/contrib/output/common/output';
import { IOutputService, OUTPUT_PANEL_ID, IOutputChannelRegistry, Extensions as OutputExt, IOutputChannelDescriptor, IFileOutputChannelDescriptor } from 'vs/workbench/contrib/output/common/output';
import { SelectActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
......@@ -50,9 +50,11 @@ export class ClearOutputAction extends Action {
}
public run(): Promise<boolean> {
this.outputService.getActiveChannel().clear();
aria.status(nls.localize('outputCleared', "Output was cleared"));
const activeChannel = this.outputService.getActiveChannel();
if (activeChannel) {
activeChannel.clear();
aria.status(nls.localize('outputCleared', "Output was cleared"));
}
return Promise.resolve(true);
}
}
......@@ -70,7 +72,12 @@ export class ToggleOrSetOutputScrollLockAction extends Action {
constructor(id: string, label: string,
@IOutputService private readonly outputService: IOutputService) {
super(id, label, 'output-action output-scroll-unlock');
this.toDispose.push(this.outputService.onActiveOutputChannel(channel => this.setClass(this.outputService.getActiveChannel().scrollLock)));
this.toDispose.push(this.outputService.onActiveOutputChannel(channel => {
const activeChannel = this.outputService.getActiveChannel();
if (activeChannel) {
this.setClass(activeChannel.scrollLock);
}
}));
}
public run(newLockState?: boolean): Promise<boolean> {
......@@ -113,7 +120,7 @@ export class SwitchOutputAction extends Action {
this.class = 'output-action switch-to-output';
}
public run(channelId?: string): Promise<any> {
public run(channelId: string): Promise<any> {
return this.outputService.showChannel(channelId);
}
}
......@@ -134,12 +141,12 @@ export class SwitchOutputActionItem extends SelectActionItem {
super(null, action, [], 0, contextViewService, { ariaLabel: nls.localize('outputChannels', 'Output Channels.') });
let outputChannelRegistry = Registry.as<IOutputChannelRegistry>(OutputExt.OutputChannels);
this.toDispose.push(outputChannelRegistry.onDidRegisterChannel(() => this.updateOtions(this.outputService.getActiveChannel().id)));
this.toDispose.push(outputChannelRegistry.onDidRemoveChannel(() => this.updateOtions(this.outputService.getActiveChannel().id)));
this.toDispose.push(this.outputService.onActiveOutputChannel(activeChannelId => this.updateOtions(activeChannelId)));
this.toDispose.push(outputChannelRegistry.onDidRegisterChannel(() => this.updateOtions()));
this.toDispose.push(outputChannelRegistry.onDidRemoveChannel(() => this.updateOtions()));
this.toDispose.push(this.outputService.onActiveOutputChannel(() => this.updateOtions()));
this.toDispose.push(attachSelectBoxStyler(this.selectBox, themeService));
this.updateOtions(this.outputService.getActiveChannel().id);
this.updateOtions();
}
protected getActionContext(option: string, index: number): string {
......@@ -147,30 +154,34 @@ export class SwitchOutputActionItem extends SelectActionItem {
return channel ? channel.id : option;
}
private updateOtions(selectedChannel: string): void {
const groups = groupBy(this.outputService.getChannelDescriptors(), (c1: IOutputChannelDescriptor, c2: IOutputChannelDescriptor) => {
if (!c1.log && c2.log) {
return -1;
}
if (c1.log && !c2.log) {
return 1;
}
return 0;
});
this.outputChannels = groups[0] || [];
this.logChannels = groups[1] || [];
const showSeparator = this.outputChannels.length && this.logChannels.length;
const separatorIndex = showSeparator ? this.outputChannels.length : -1;
const options: string[] = [...this.outputChannels.map(c => c.label), ...(showSeparator ? [SwitchOutputActionItem.SEPARATOR] : []), ...this.logChannels.map(c => nls.localize('logChannel', "Log ({0})", c.label))];
let selected = 0;
if (selectedChannel) {
selected = this.outputChannels.map(c => c.id).indexOf(selectedChannel);
if (selected === -1) {
const logChannelIndex = this.logChannels.map(c => c.id).indexOf(selectedChannel);
selected = logChannelIndex !== -1 ? separatorIndex + 1 + logChannelIndex : 0;
private updateOtions(): void {
const activeChannel = this.outputService.getActiveChannel();
if (activeChannel) {
const selectedChannel = activeChannel.id;
const groups = groupBy(this.outputService.getChannelDescriptors(), (c1: IOutputChannelDescriptor, c2: IOutputChannelDescriptor) => {
if (!c1.log && c2.log) {
return -1;
}
if (c1.log && !c2.log) {
return 1;
}
return 0;
});
this.outputChannels = groups[0] || [];
this.logChannels = groups[1] || [];
const showSeparator = this.outputChannels.length && this.logChannels.length;
const separatorIndex = showSeparator ? this.outputChannels.length : -1;
const options: string[] = [...this.outputChannels.map(c => c.label), ...(showSeparator ? [SwitchOutputActionItem.SEPARATOR] : []), ...this.logChannels.map(c => nls.localize('logChannel', "Log ({0})", c.label))];
let selected = 0;
if (selectedChannel) {
selected = this.outputChannels.map(c => c.id).indexOf(selectedChannel);
if (selected === -1) {
const logChannelIndex = this.logChannels.map(c => c.id).indexOf(selectedChannel);
selected = logChannelIndex !== -1 ? separatorIndex + 1 + logChannelIndex : 0;
}
}
this.setOptions(options.map((label, index) => <ISelectOptionItem>{ text: label, isDisabled: (index === separatorIndex ? true : undefined) }), Math.max(0, selected));
}
this.setOptions(options.map((label, index) => <ISelectOptionItem>{ text: label, isDisabled: (index === separatorIndex ? true : undefined) }), Math.max(0, selected));
}
}
......@@ -192,17 +203,23 @@ export class OpenLogOutputFile extends Action {
}
private update(): void {
const outputChannelDescriptor = this.getOutputChannelDescriptor();
this.enabled = !!(outputChannelDescriptor && outputChannelDescriptor.file && outputChannelDescriptor.log);
this.enabled = !!this.getLogFileOutputChannelDescriptor();
}
public run(): Promise<any> {
return this.enabled ? this.editorService.openEditor(this.instantiationService.createInstance(LogViewerInput, this.getOutputChannelDescriptor())).then(() => null) : Promise.resolve(null);
const logFileOutputChannelDescriptor = this.getLogFileOutputChannelDescriptor();
return logFileOutputChannelDescriptor ? this.editorService.openEditor(this.instantiationService.createInstance(LogViewerInput, logFileOutputChannelDescriptor)).then(() => null) : Promise.resolve(null);
}
private getOutputChannelDescriptor(): IOutputChannelDescriptor {
private getLogFileOutputChannelDescriptor(): IFileOutputChannelDescriptor | null {
const channel = this.outputService.getActiveChannel();
return channel ? this.outputService.getChannelDescriptors().filter(c => c.id === channel.id)[0] : null;
if (channel) {
const descriptor = this.outputService.getChannelDescriptors().filter(c => c.id === channel.id)[0];
if (descriptor && descriptor.file && descriptor.log) {
return <IFileOutputChannelDescriptor>descriptor;
}
}
return null;
}
}
......@@ -219,15 +236,15 @@ export class ShowLogsOutputChannelAction extends Action {
}
run(): Promise<void> {
const entries: IQuickPickItem[] = this.outputService.getChannelDescriptors().filter(c => c.file && c.log)
.map(({ id, label }) => (<IQuickPickItem>{ id, label }));
const entries: { id: string, label: string }[] = this.outputService.getChannelDescriptors().filter(c => c.file && c.log)
.map(({ id, label }) => ({ id, label }));
return this.quickInputService.pick(entries, { placeHolder: nls.localize('selectlog', "Select Log") })
.then(entry => {
if (entry) {
return this.outputService.showChannel(entry.id);
}
return null;
return undefined;
});
}
}
......@@ -257,9 +274,9 @@ export class OpenOutputLogFileAction extends Action {
return this.quickInputService.pick(entries, { placeHolder: nls.localize('selectlogFile', "Select Log file") })
.then(entry => {
if (entry) {
return this.editorService.openEditor(this.instantiationService.createInstance(LogViewerInput, entry.channel)).then(() => null);
return this.editorService.openEditor(this.instantiationService.createInstance(LogViewerInput, entry.channel)).then(() => undefined);
}
return null;
return undefined;
});
}
}
\ No newline at end of file
......@@ -75,7 +75,7 @@ export class OutputPanel extends AbstractTextResourceEditor {
return this.actions;
}
public getActionItem(action: Action): IActionItem {
public getActionItem(action: Action): IActionItem | null {
if (action.id === SwitchOutputAction.ID) {
return this.instantiationService.createInstance(SwitchOutputActionItem, action);
}
......@@ -154,11 +154,14 @@ export class OutputPanel extends AbstractTextResourceEditor {
return;
}
const newPositionLine = e.position.lineNumber;
const lastLine = codeEditor.getModel().getLineCount();
const newLockState = lastLine !== newPositionLine;
const lockAction = this.actions.filter((action) => action.id === ToggleOrSetOutputScrollLockAction.ID)[0];
lockAction.run(newLockState);
const model = codeEditor.getModel();
if (model) {
const newPositionLine = e.position.lineNumber;
const lastLine = model.getLineCount();
const newLockState = lastLine !== newPositionLine;
const lockAction = this.actions.filter((action) => action.id === ToggleOrSetOutputScrollLockAction.ID)[0];
lockAction.run(newLockState);
}
});
}
......
......@@ -68,7 +68,7 @@ export interface IOutputService {
* Given the channel id returns the output channel instance.
* Channel should be first registered via OutputChannelRegistry.
*/
getChannel(id: string): IOutputChannel;
getChannel(id: string): IOutputChannel | null;
/**
* Returns an array of all known output channels descriptors.
......@@ -79,7 +79,7 @@ export interface IOutputService {
* Returns the currently active channel.
* Only one channel can be active at a given moment.
*/
getActiveChannel(): IOutputChannel;
getActiveChannel(): IOutputChannel | null;
/**
* Show the channel with the passed id.
......@@ -137,6 +137,10 @@ export interface IOutputChannelDescriptor {
file?: URI;
}
export interface IFileOutputChannelDescriptor extends IOutputChannelDescriptor {
file: URI;
}
export interface IOutputChannelRegistry {
readonly onDidRegisterChannel: Event<string>;
......
......@@ -30,7 +30,6 @@ registerSingleton(IOutputService, OutputService);
ModesRegistry.registerLanguage({
id: OUTPUT_MODE_ID,
extensions: [],
aliases: [null],
mimetypes: [OUTPUT_MIME]
});
......@@ -38,7 +37,6 @@ ModesRegistry.registerLanguage({
ModesRegistry.registerLanguage({
id: LOG_MODE_ID,
extensions: [],
aliases: [null],
mimetypes: [LOG_MIME]
});
......@@ -99,7 +97,10 @@ registerAction({
when: CONTEXT_IN_OUTPUT
},
handler(accessor) {
accessor.get(IOutputService).getActiveChannel().clear();
const activeChannel = accessor.get(IOutputService).getActiveChannel();
if (activeChannel) {
activeChannel.clear();
}
}
});
......
......@@ -14,7 +14,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { Registry } from 'vs/platform/registry/common/platform';
import { EditorOptions } from 'vs/workbench/common/editor';
import { IOutputChannelDescriptor, IOutputChannel, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry, OUTPUT_SCHEME, OUTPUT_MIME, LOG_SCHEME, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT, MAX_OUTPUT_LENGTH } from 'vs/workbench/contrib/output/common/output';
import { IOutputChannelDescriptor, IOutputChannel, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry, OUTPUT_SCHEME, OUTPUT_MIME, LOG_SCHEME, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT, MAX_OUTPUT_LENGTH, IFileOutputChannelDescriptor } from 'vs/workbench/contrib/output/common/output';
import { OutputPanel } from 'vs/workbench/contrib/output/browser/outputPanel';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IModelService } from 'vs/editor/common/services/modelService';
......@@ -44,7 +44,7 @@ import { isNumber } from 'vs/base/common/types';
const OUTPUT_ACTIVE_CHANNEL_KEY = 'output.activechannel';
let watchingOutputDir = false;
let callbacks: ((eventType: string, fileName: string) => void)[] = [];
let callbacks: ((eventType: string, fileName?: string) => void)[] = [];
function watchOutputDirectory(outputDir: string, logService: ILogService, onChange: (eventType: string, fileName: string) => void): IDisposable {
callbacks.push(onChange);
if (!watchingOutputDir) {
......@@ -65,7 +65,7 @@ function watchOutputDirectory(outputDir: string, logService: ILogService, onChan
}
interface OutputChannel extends IOutputChannel {
readonly file: URI;
readonly file: URI | null;
readonly onDidAppendedContent: Event<void>;
readonly onDispose: Event<void>;
loadModel(): Promise<ITextModel>;
......@@ -83,14 +83,14 @@ abstract class AbstractFileOutputChannel extends Disposable implements OutputCha
private readonly mimeType: string;
protected modelUpdater: RunOnceScheduler;
protected model: ITextModel;
protected model: ITextModel | null;
readonly file: URI;
protected startOffset: number = 0;
protected endOffset: number = 0;
constructor(
readonly outputChannelDescriptor: IOutputChannelDescriptor,
readonly outputChannelDescriptor: IFileOutputChannelDescriptor,
private readonly modelUri: URI,
protected fileService: IFileService,
protected modelService: IModelService,
......@@ -154,7 +154,7 @@ abstract class AbstractFileOutputChannel extends Disposable implements OutputCha
abstract append(message: string);
protected onModelCreated(model: ITextModel) { }
protected onModelWillDispose(model: ITextModel) { }
protected onModelWillDispose(model: ITextModel | null) { }
protected onUpdateModelCancelled() { }
protected updateModel() { }
......@@ -176,15 +176,14 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out
private readonly rotatingFilePath: string;
constructor(
outputChannelDescriptor: IOutputChannelDescriptor,
outputDir: string,
outputChannelDescriptor: IFileOutputChannelDescriptor,
modelUri: URI,
@IFileService fileService: IFileService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@ILogService logService: ILogService
) {
super({ ...outputChannelDescriptor, file: URI.file(join(outputDir, `${outputChannelDescriptor.id}.log`)) }, modelUri, fileService, modelService, modeService);
super(outputChannelDescriptor, modelUri, fileService, modelService, modeService);
// Use one rotating file to check for main file reset
this.appender = new OutputAppender(this.id, this.file.fsPath);
......@@ -262,7 +261,7 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out
}
}
private onFileChangedInOutputDirector(eventType: string, fileName: string): void {
private onFileChangedInOutputDirector(eventType: string, fileName?: string): void {
// Check if rotating file has changed. It changes only when the main file exceeds its limit.
if (this.rotatingFilePath === fileName) {
this.resettingDelayer.trigger(() => this.resetModel());
......@@ -286,11 +285,11 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann
private readonly fileHandler: FileListener;
private updateInProgress: boolean = false;
private etag: string = '';
private loadModelPromise: Promise<ITextModel> = Promise.resolve(undefined);
private etag: string | undefined = '';
private loadModelPromise: Promise<ITextModel> | null = null;
constructor(
outputChannelDescriptor: IOutputChannelDescriptor,
outputChannelDescriptor: IFileOutputChannelDescriptor,
modelUri: URI,
@IFileService fileService: IFileService,
@IModelService modelService: IModelService,
......@@ -314,7 +313,8 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann
}
clear(till?: number): void {
this.loadModelPromise.then(() => {
const loadModelPromise: Promise<any> = this.loadModelPromise ? this.loadModelPromise : Promise.resolve();
loadModelPromise.then(() => {
super.clear(till);
this.update();
});
......@@ -344,7 +344,7 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann
this.fileHandler.watch(this.etag);
}
protected onModelWillDispose(model: ITextModel): void {
protected onModelWillDispose(model: ITextModel | null): void {
this.fileHandler.unwatch();
}
......@@ -353,13 +353,15 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann
}
update(size?: number): void {
if (!this.updateInProgress) {
this.updateInProgress = true;
if (isNumber(size) && this.endOffset > size) { // Reset - Content is removed
this.startOffset = this.endOffset = 0;
this.model.setValue('');
if (this.model) {
if (!this.updateInProgress) {
this.updateInProgress = true;
if (isNumber(size) && this.endOffset > size) { // Reset - Content is removed
this.startOffset = this.endOffset = 0;
this.model.setValue('');
}
this.modelUpdater.schedule();
}
this.modelUpdater.schedule();
}
}
}
......@@ -370,7 +372,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
private channels: Map<string, OutputChannel> = new Map<string, OutputChannel>();
private activeChannelIdInStorage: string;
private activeChannel: IOutputChannel;
private activeChannel: IOutputChannel | null;
private readonly outputDir: string;
private readonly _onActiveOutputChannel = new Emitter<string>();
......@@ -392,7 +394,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
super();
this.activeChannelIdInStorage = this.storageService.get(OUTPUT_ACTIVE_CHANNEL_KEY, StorageScope.WORKSPACE, null);
this.activeChannelIdInStorage = this.storageService.get(OUTPUT_ACTIVE_CHANNEL_KEY, StorageScope.WORKSPACE, '');
this.outputDir = join(environmentService.logsPath, `output_${windowService.getCurrentWindowId()}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
// Register as text model content provider for output
......@@ -419,7 +421,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
this._register(this.storageService.onWillSaveState(() => this.saveState()));
}
provideTextContent(resource: URI): Promise<ITextModel> {
provideTextContent(resource: URI): Promise<ITextModel> | null {
const channel = <OutputChannel>this.getChannel(resource.path);
if (channel) {
return channel.loadModel();
......@@ -447,15 +449,15 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
return promise.then(() => this._onActiveOutputChannel.fire(id));
}
getChannel(id: string): IOutputChannel {
return this.channels.get(id);
getChannel(id: string): IOutputChannel | null {
return this.channels.get(id) || null;
}
getChannelDescriptors(): IOutputChannelDescriptor[] {
return Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).getChannels();
}
getActiveChannel(): IOutputChannel {
getActiveChannel(): IOutputChannel | null {
return this.activeChannel;
}
......@@ -469,7 +471,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
}
}
private onDidPanelOpen(panel: IPanel, preserveFocus: boolean): Promise<void> {
private onDidPanelOpen(panel: IPanel | null, preserveFocus: boolean): Promise<void> {
if (panel && panel.getId() === OUTPUT_PANEL_ID) {
this._outputPanel = <OutputPanel>this.panelService.getActivePanel();
if (this.activeChannel) {
......@@ -506,7 +508,9 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
this.showChannel(channel.id, true);
} else {
this.activeChannel = channel;
this._onActiveOutputChannel.fire(channel ? channel.id : undefined);
if (this.activeChannel) {
this._onActiveOutputChannel.fire(this.activeChannel.id);
}
}
}
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).removeChannel(id);
......@@ -528,7 +532,8 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
return this.instantiationService.createInstance(FileOutputChannel, channelData, uri);
}
try {
return this.instantiationService.createInstance(OutputChannelBackedByFile, { id, label: channelData ? channelData.label : '' }, this.outputDir, uri);
const channelDescriptor: IFileOutputChannelDescriptor = { id, label: channelData ? channelData.label : '', log: false, file: URI.file(join(this.outputDir, `${id}.log`)) };
return this.instantiationService.createInstance(OutputChannelBackedByFile, channelDescriptor, uri);
} catch (e) {
// Do not crash if spdlog rotating logger cannot be loaded (workaround for https://github.com/Microsoft/vscode/issues/47883)
this.logService.error(e);
......@@ -584,7 +589,7 @@ export class LogContentProvider {
) {
}
provideTextContent(resource: URI): Promise<ITextModel> {
provideTextContent(resource: URI): Promise<ITextModel> | null {
if (resource.scheme === LOG_SCHEME) {
let channel = this.getChannel(resource);
if (channel) {
......@@ -594,7 +599,7 @@ export class LogContentProvider {
return null;
}
private getChannel(resource: URI): OutputChannel {
private getChannel(resource: URI): OutputChannel | undefined {
const channelId = resource.path;
let channel = this.channels.get(channelId);
if (!channel) {
......@@ -624,9 +629,9 @@ class BufferredOutputChannel extends Disposable implements OutputChannel {
readonly onDispose: Event<void> = this._onDispose.event;
private modelUpdater: RunOnceScheduler;
private model: ITextModel;
private model: ITextModel | null;
private readonly bufferredContent: BufferedContent;
private lastReadId: number = undefined;
private lastReadId: number | undefined = undefined;
constructor(
protected readonly outputChannelIdentifier: IOutputChannelDescriptor,
......@@ -731,7 +736,9 @@ class BufferedContent {
while (this.length > MAX_OUTPUT_LENGTH) {
this.dataIds.shift();
const removed = this.data.shift();
this.length -= removed.length;
if (removed) {
this.length -= removed.length;
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册