提交 47f8f2d8 编写于 作者: S Sandeep Somavarapu

Fix #68351

上级 b9f82d07
......@@ -8,14 +8,68 @@ import { URI } from 'vs/base/common/uri';
import * as glob from 'vs/base/common/glob';
import { isLinux } from 'vs/base/common/platform';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { startsWithIgnoreCase } from 'vs/base/common/strings';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { isEqualOrParent, isEqual } from 'vs/base/common/resources';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { ThrottledDelayer } from 'vs/base/common/async';
export const IFileService = createDecorator<IFileService>('fileService');
export class FileListener extends Disposable {
private readonly _onDidContentChange = new Emitter<IFileStat>();
readonly onDidContentChange: Event<IFileStat> = this._onDidContentChange.event;
private watching: boolean = false;
private delayer: ThrottledDelayer<void>;
private etag: string | null;
constructor(
private readonly file: URI,
private readonly fileService: IFileService
) {
super();
this.delayer = new ThrottledDelayer<void>(500);
}
watch(eTag: string | null): void {
if (!this.watching) {
this.etag = eTag;
this.poll();
this.watching = true;
}
}
private poll(): void {
const loop = () => this.doWatch().then(() => this.poll());
this.delayer.trigger(loop);
}
private doWatch(): Promise<void> {
return this.fileService.resolveFile(this.file)
.then(stat => {
if (stat.etag !== this.etag) {
this.etag = stat.etag;
this._onDidContentChange.fire(stat);
}
});
}
unwatch(): void {
if (this.watching) {
this.delayer.cancel();
this.watching = false;
}
}
dispose(): void {
this.unwatch();
super.dispose();
}
}
export interface IResourceEncodings {
getWriteEncoding(resource: URI, preferredEncoding?: string): string;
}
......
......@@ -26,7 +26,7 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { RunOnceScheduler, ThrottledDelayer } from 'vs/base/common/async';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Position } from 'vs/editor/common/core/position';
import { IFileService } from 'vs/platform/files/common/files';
import { IFileService, FileListener } from 'vs/platform/files/common/files';
import { IPanel } from 'vs/workbench/common/panel';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
......@@ -278,65 +278,12 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out
}
}
class OutputFileListener extends Disposable {
private readonly _onDidContentChange = new Emitter<number>();
readonly onDidContentChange: Event<number> = this._onDidContentChange.event;
private watching: boolean = false;
private syncDelayer: ThrottledDelayer<void>;
private etag: string;
constructor(
private readonly file: URI,
private readonly fileService: IFileService
) {
super();
this.syncDelayer = new ThrottledDelayer<void>(500);
}
watch(eTag: string): void {
if (!this.watching) {
this.etag = eTag;
this.poll();
this.watching = true;
}
}
private poll(): void {
const loop = () => this.doWatch().then(() => this.poll());
this.syncDelayer.trigger(loop);
}
private doWatch(): Promise<void> {
return this.fileService.resolveFile(this.file)
.then(stat => {
if (stat.etag !== this.etag) {
this.etag = stat.etag;
this._onDidContentChange.fire(stat.size);
}
});
}
unwatch(): void {
if (this.watching) {
this.syncDelayer.cancel();
this.watching = false;
}
}
dispose(): void {
this.unwatch();
super.dispose();
}
}
/**
* An output channel driven by a file and does not support appending messages.
*/
class FileOutputChannel extends AbstractFileOutputChannel implements OutputChannel {
private readonly fileHandler: OutputFileListener;
private readonly fileHandler: FileListener;
private updateInProgress: boolean = false;
private etag: string = '';
......@@ -351,8 +298,8 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann
) {
super(outputChannelDescriptor, modelUri, fileService, modelService, modeService);
this.fileHandler = this._register(new OutputFileListener(this.file, this.fileService));
this._register(this.fileHandler.onDidContentChange(size => this.update(size)));
this.fileHandler = this._register(new FileListener(this.file, this.fileService));
this._register(this.fileHandler.onDidContentChange(({ size }) => this.update(size)));
this._register(toDisposable(() => this.fileHandler.unwatch()));
}
......
......@@ -10,9 +10,9 @@ import { Event, Emitter } from 'vs/base/common/event';
import * as pfs from 'vs/base/node/pfs';
import * as errors from 'vs/base/common/errors';
import * as collections from 'vs/base/common/collections';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { RunOnceScheduler, Delayer } from 'vs/base/common/async';
import { FileChangeType, FileChangesEvent, IContent, IFileService } from 'vs/platform/files/common/files';
import { FileChangeType, FileChangesEvent, IContent, IFileService, FileListener } from 'vs/platform/files/common/files';
import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels';
import { FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, FOLDER_SETTINGS_NAME, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
......@@ -211,16 +211,22 @@ class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfigurat
private workspaceConfig: URI | null = null;
private readonly reloadConfigurationScheduler: RunOnceScheduler;
private fileListener: FileListener;
private fileListenerDisposables: IDisposable[] = [];
constructor(private fileService: IFileService, from?: AbstractWorkspaceConfiguration) {
super(from);
this.workspaceConfig = from && from.workspaceIdentifier ? from.workspaceIdentifier.configPath : null;
this._register(fileService.onFileChanges(e => this.handleWorkspaceFileEvents(e)));
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50));
this.listenToWorkspaceConfigurationFile();
this._register(toDisposable(() => dispose(this.fileListenerDisposables)));
}
protected loadWorkspaceConfigurationContents(workspaceIdentifier: IWorkspaceIdentifier): Promise<string> {
if (!(this.workspaceConfig && resources.isEqual(this.workspaceConfig, workspaceIdentifier.configPath))) {
this.workspaceConfig = workspaceIdentifier.configPath;
this.listenToWorkspaceConfigurationFile();
}
return this.fileService.resolveContent(this.workspaceConfig)
.then(content => content.value, e => {
errors.onUnexpectedError(e);
......@@ -228,19 +234,16 @@ class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfigurat
});
}
private handleWorkspaceFileEvents(event: FileChangesEvent): void {
if (this.workspaceConfig) {
const events = event.changes;
let affectedByChanges = false;
// Find changes that affect workspace file
for (let i = 0, len = events.length; i < len && !affectedByChanges; i++) {
affectedByChanges = resources.isEqual(this.workspaceConfig, events[i].resource);
}
if (affectedByChanges) {
this.reloadConfigurationScheduler.schedule();
private listenToWorkspaceConfigurationFile(): void {
if (this.fileListener) {
this.fileListenerDisposables = dispose(this.fileListenerDisposables);
this.fileListener = null;
}
if (this.workspaceConfig) {
this.fileListener = new FileListener(this.workspaceConfig, this.fileService);
this.fileListenerDisposables.push(this.fileListener);
this.fileListener.watch(null);
this.fileListener.onDidContentChange(() => this.reloadConfigurationScheduler.schedule(), this, this.fileListenerDisposables);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册