提交 66c081aa 编写于 作者: B Benjamin Pasero

first cut introduce new setting to control auto save delay

上级 0444705b
......@@ -417,5 +417,6 @@ export interface IFilesConfiguration {
exclude: glob.IExpression;
encoding: string;
trimTrailingWhitespace: boolean;
autoSaveAfterDelay: number;
};
}
\ No newline at end of file
......@@ -19,7 +19,7 @@ import {IEditorRegistry, Extensions, EditorDescriptor} from 'vs/workbench/browse
import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel';
import {IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files';
import {FileEditorDescriptor} from 'vs/workbench/parts/files/browser/files';
import {BINARY_FILE_EDITOR_ID, FILE_EDITOR_INPUT_ID, FileEditorInput as CommonFileEditorInput} from 'vs/workbench/parts/files/common/files';
import {ITextFileService, BINARY_FILE_EDITOR_ID, FILE_EDITOR_INPUT_ID, FileEditorInput as CommonFileEditorInput} from 'vs/workbench/parts/files/common/files';
import {CACHE, TextFileEditorModel, State} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
......@@ -63,7 +63,8 @@ export class FileEditorInput extends CommonFileEditorInput {
mime: string,
preferredEncoding: string,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@ITextFileService private textFileService: ITextFileService
) {
super();
......@@ -157,11 +158,11 @@ export class FileEditorInput extends CommonFileEditorInput {
}
case State.DIRTY: {
return { state: 'dirty', decoration: !this.contextService.isAutoSaveEnabled() ? '\u25cf' : '', displayText: FileEditorInput.nlsDirtyDisplay, description: FileEditorInput.nlsDirtyMeta };
return { state: 'dirty', decoration: !this.textFileService.isAutoSaveEnabled() ? '\u25cf' : '', displayText: FileEditorInput.nlsDirtyDisplay, description: FileEditorInput.nlsDirtyMeta };
}
case State.PENDING_SAVE:
return { state: 'saving', decoration: !this.contextService.isAutoSaveEnabled() ? '\u25cf' : '', displayText: FileEditorInput.nlsPendingSaveDisplay, description: FileEditorInput.nlsPendingSaveMeta };
return { state: 'saving', decoration: !this.textFileService.isAutoSaveEnabled() ? '\u25cf' : '', displayText: FileEditorInput.nlsPendingSaveDisplay, description: FileEditorInput.nlsPendingSaveMeta };
case State.ERROR:
return { state: 'error', decoration: '\u25cf', displayText: FileEditorInput.nlsErrorDisplay, description: FileEditorInput.nlsErrorMeta };
......
......@@ -14,10 +14,9 @@ import types = require('vs/base/common/types');
import {IModelContentChangedEvent, EventType as EditorEventType} from 'vs/editor/common/editorCommon';
import {IMode} from 'vs/editor/common/modes';
import {EventType as WorkbenchEventType, ResourceEvent} from 'vs/workbench/common/events';
import {LocalFileChangeEvent, EventType as FileEventType, TextFileChangeEvent} from 'vs/workbench/parts/files/common/files';
import {LocalFileChangeEvent, EventType as FileEventType, TextFileChangeEvent, ITextFileService, IAutoSaveConfiguration} from 'vs/workbench/parts/files/common/files';
import {EncodingMode, EditorModel, IEncodingSupport} from 'vs/workbench/common/editor';
import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorModel';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IFileService, IFileStat, IFileOperationResult, FileOperationResult, IContent} from 'vs/platform/files/common/files';
import {IEventService} from 'vs/platform/event/common/event';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
......@@ -96,7 +95,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin
private bufferSavedVersionId: number;
private versionOnDiskStat: IFileStat;
private blockModelContentChange: boolean;
private autoSaveDelay: number;
private autoSaveAfterMillies: number;
private autoSaveEnabled: boolean;
private autoSavePromises: TPromise<void>[];
private mapPendingSaveToVersionId: { [versionId: string]: TPromise<void> };
......@@ -113,10 +112,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin
@IModeService modeService: IModeService,
@IModelService modelService: IModelService,
@IEventService private eventService: IEventService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IFileService private fileService: IFileService,
@IInstantiationService private instantiationService: IInstantiationService,
@ITelemetryService private telemetryService: ITelemetryService
@ITelemetryService private telemetryService: ITelemetryService,
@ITextFileService private textFileService: ITextFileService
) {
super(modelService, modeService);
......@@ -133,20 +132,17 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin
this.lastDirtyTime = 0;
this.mapPendingSaveToVersionId = {};
this.updateOptions();
this.updateAutoSaveConfiguration(textFileService.getAutoSaveConfiguration());
}
public updateOptions(): void {
// Check for Autosave Delay Configuration
let options = this.contextService.getOptions();
if (options && types.isNumber(options.autoSaveDelay)) {
this.autoSaveDelay = options.autoSaveDelay;
public updateAutoSaveConfiguration(config: IAutoSaveConfiguration): void {
if (typeof config.autoSaveAfterDelay === 'number' && config.autoSaveAfterDelay > 0) {
this.autoSaveAfterMillies = config.autoSaveAfterDelay * 1000;
this.autoSaveEnabled = true;
} else {
this.autoSaveDelay = TextFileEditorModel.DEFAULT_AUTO_SAVE_DELAY;
this.autoSaveAfterMillies = void 0;
this.autoSaveEnabled = false;
}
this.autoSaveEnabled = (this.autoSaveDelay !== -1);
}
/**
......@@ -385,13 +381,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin
// Cancel any currently running auto saves to make this the one that succeeds
this.cancelAutoSavePromises();
// Support to save without delay if configured as such
if (this.autoSaveDelay === 0) {
return this.doSave(versionId, true);
}
// Otherwise create new save promise and keep it
let promise: TPromise<void> = Promise.timeout(this.autoSaveDelay).then(() => {
// Create new save promise and keep it
let promise: TPromise<void> = Promise.timeout(this.autoSaveAfterMillies).then(() => {
// Only trigger save if the version id has not changed meanwhile
if (versionId === this.versionId) {
......@@ -449,8 +440,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin
if (this.isBusySaving()) {
diag('doSave(' + versionId + ') - exit - because busy saving', this.resource, new Date());
// Avoid endless loop here and guard if autoSaveDelay is 0 (used by tests only)
if (this.autoSaveDelay > 0) {
// Avoid endless loop here and guard if auto save is disabled
if (this.autoSaveEnabled) {
return this.doAutoSave(versionId);
}
}
......
......@@ -25,7 +25,6 @@ import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/unti
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IQuickOpenService} from 'vs/workbench/services/quickopen/common/quickOpenService';
import {IActivityService, NumberBadge} from 'vs/workbench/services/activity/common/activityService';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IEditorInput} from 'vs/platform/editor/common/editor';
import {IEventService} from 'vs/platform/event/common/event';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
......@@ -43,7 +42,6 @@ export class FileTracker implements IWorkbenchContribution {
private toUnbind: { (): void; }[];
constructor(
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IEventService private eventService: IEventService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
......@@ -86,7 +84,7 @@ export class FileTracker implements IWorkbenchContribution {
private onTextFileDirty(e: LocalFileChangeEvent): void {
this.emitInputStateChangeEvent(e.getAfter().resource);
if (!this.contextService.isAutoSaveEnabled()) {
if (!this.textFileService.isAutoSaveEnabled()) {
this.updateActivityBadge(); // no indication needed when auto save is turned off and we didn't show dirty
}
}
......
......@@ -218,6 +218,11 @@ configurationRegistry.registerConfiguration({
'type': 'boolean',
'default': false,
'description': nls.localize('trimTrailingWhitespace', "When enabled, will trim trailing whitespace when you save a file.")
},
'files.autoSaveAfterDelay': {
'type': 'number',
'default': 0,
'description': nls.localize('autoSaveAfterDelay', "When set to a positive number, will automatically save dirty files after configured seconds.")
}
}
});
......
......@@ -6,16 +6,18 @@
import {TPromise, Promise} from 'vs/base/common/winjs.base';
import URI from 'vs/base/common/uri';
import errors = require('vs/base/common/errors');
import {ListenerUnbind} from 'vs/base/common/eventEmitter';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {CACHE, TextFileEditorModel} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel';
import {IResult, ITextFileOperationResult, ConfirmResult, ITextFileService} from 'vs/workbench/parts/files/common/files';
import {IResult, ITextFileOperationResult, ConfirmResult, ITextFileService, IAutoSaveConfiguration} from 'vs/workbench/parts/files/common/files';
import {EventType} from 'vs/workbench/common/events';
import {WorkingFilesModel} from 'vs/workbench/parts/files/browser/workingFilesModel';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files';
import {IEventService} from 'vs/platform/event/common/event';
import {IFilesConfiguration, IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle';
import {IConfigurationService, IConfigurationServiceEvent, ConfigurationServiceEventTypes} from 'vs/platform/configuration/common/configuration';
/**
* The workbench file service implementation implements the raw file service spec and adds additional methods on top.
......@@ -25,30 +27,49 @@ import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle';
export abstract class TextFileService implements ITextFileService {
public serviceId = ITextFileService;
private listenerToUnbind: () => void;
private workingFilesModel: WorkingFilesModel;
private listenerToUnbind: ListenerUnbind[];
private _workingFilesModel: WorkingFilesModel;
private configuredAutoSaveDelay: number;
constructor(
@IEventService private eventService: IEventService,
@IWorkspaceContextService protected contextService: IWorkspaceContextService,
@IInstantiationService instantiationService: IInstantiationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IConfigurationService private configurationService: IConfigurationService,
@ILifecycleService private lifecycleService: ILifecycleService
) {
this.workingFilesModel = instantiationService.createInstance(WorkingFilesModel);
this.listenerToUnbind = [];
this.registerListeners();
this.loadConfiguration();
}
private get workingFilesModel(): WorkingFilesModel {
if (!this._workingFilesModel) {
this._workingFilesModel = this.instantiationService.createInstance(WorkingFilesModel);
}
return this._workingFilesModel;
}
private registerListeners(): void {
this.listenerToUnbind = this.eventService.addListener(EventType.WORKBENCH_OPTIONS_CHANGED, () => this.onOptionsChanged());
if (this.lifecycleService) {
this.lifecycleService.addBeforeShutdownParticipant(this);
this.lifecycleService.onShutdown(this.dispose, this);
this.listenerToUnbind.push(this.configurationService.addListener(ConfigurationServiceEventTypes.UPDATED, (e: IConfigurationServiceEvent) => this.onConfigurationChange(e.config)));
}
private loadConfiguration(): void {
this.configurationService.loadConfiguration().done((configuration: IFilesConfiguration) => {
this.onConfigurationChange(configuration);
}, errors.onUnexpectedError);
}
protected onOptionsChanged(): void {
CACHE.getAll().forEach((model) => model.updateOptions());
private onConfigurationChange(configuration: IFilesConfiguration): void {
this.configuredAutoSaveDelay = configuration && configuration.files && configuration.files.autoSaveAfterDelay;
const autoSaveConfig = this.getAutoSaveConfiguration();
CACHE.getAll().forEach((model) => model.updateAutoSaveConfiguration(autoSaveConfig));
}
public getDirty(resource?: URI): URI[] {
......@@ -172,8 +193,20 @@ export abstract class TextFileService implements ITextFileService {
return this.workingFilesModel;
}
public isAutoSaveEnabled(): boolean {
return this.configuredAutoSaveDelay && this.configuredAutoSaveDelay > 0;
}
public getAutoSaveConfiguration(): IAutoSaveConfiguration {
return {
autoSaveAfterDelay: this.configuredAutoSaveDelay && this.configuredAutoSaveDelay > 0 ? this.configuredAutoSaveDelay : void 0
}
}
public dispose(): void {
this.listenerToUnbind();
while (this.listenerToUnbind.length) {
this.listenerToUnbind.pop()();
}
this.workingFilesModel.dispose();
......
......@@ -22,7 +22,6 @@ import {CloseWorkingFileAction, SaveAllAction} from 'vs/workbench/parts/files/br
import {WorkingFileEntry} from 'vs/workbench/parts/files/browser/workingFilesModel';
import {WorkingFilesDragAndDrop, WorkingFilesSorter, WorkingFilesController, WorkingFilesDataSource, WorkingFilesRenderer, WorkingFilesActionProvider} from 'vs/workbench/parts/files/browser/views/workingFilesViewer';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IConfigurationService, IConfigurationServiceEvent, ConfigurationServiceEventTypes} from 'vs/platform/configuration/common/configuration';
import {IEditorInput} from 'vs/platform/editor/common/editor';
import {IEventService} from 'vs/platform/event/common/event';
......@@ -37,8 +36,6 @@ export class WorkingFilesView extends AdaptiveCollapsibleViewletView {
private static DEFAULT_MAX_VISIBLE_FILES = 9;
private static DEFAULT_DYNAMIC_HEIGHT = true;
private textFileService: ITextFileService;
private settings: any;
private maxVisibleWorkingFiles: number;
private dynamicHeight: boolean;
......@@ -51,18 +48,15 @@ export class WorkingFilesView extends AdaptiveCollapsibleViewletView {
constructor(actionRunner: IActionRunner, settings: any,
@IEventService private eventService: IEventService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IInstantiationService private instantiationService: IInstantiationService,
@IMessageService messageService: IMessageService,
@IContextMenuService contextMenuService: IContextMenuService,
@ITextFileService textFileService: ITextFileService,
@ITextFileService private textFileService: ITextFileService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IConfigurationService private configurationService: IConfigurationService
) {
super(actionRunner, WorkingFilesView.computeExpandedBodySize(textFileService.getWorkingFilesModel()), !!settings[WorkingFilesView.MEMENTO_COLLAPSED], 'workingFilesView', messageService, contextMenuService);
this.textFileService = textFileService;
this.settings = settings;
this.model = this.textFileService.getWorkingFilesModel();
this.lastDirtyCount = 0;
......@@ -154,7 +148,7 @@ export class WorkingFilesView extends AdaptiveCollapsibleViewletView {
}
private onTextFileDirty(e: LocalFileChangeEvent): void {
if (!this.contextService.isAutoSaveEnabled()) {
if (!this.textFileService.isAutoSaveEnabled()) {
this.updateDirtyIndicator(); // no indication needed when auto save is turned off and we didn't show dirty
}
}
......
......@@ -22,7 +22,7 @@ import actions = require('vs/base/common/actions');
import {ActionsRenderer} from 'vs/base/parts/tree/browser/actionsRenderer';
import {ContributableActionProvider} from 'vs/workbench/browser/actionBarRegistry';
import {keybindingForAction, CloseWorkingFileAction, SelectResourceForCompareAction, CompareResourcesAction, SaveFileAsAction, SaveFileAction, RevertFileAction, OpenToSideAction} from 'vs/workbench/parts/files/browser/fileActions';
import {asFileResource} from 'vs/workbench/parts/files/common/files';
import {asFileResource, ITextFileService} from 'vs/workbench/parts/files/common/files';
import {WorkingFileEntry, WorkingFilesModel} from 'vs/workbench/parts/files/browser/workingFilesModel';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
......@@ -119,8 +119,8 @@ export class WorkingFilesActionProvider extends ContributableActionProvider {
constructor(model: WorkingFilesModel,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@ITextFileService private textFileService: ITextFileService
) {
super();
......@@ -155,7 +155,7 @@ export class WorkingFilesActionProvider extends ContributableActionProvider {
actions.unshift(openToSideAction); // be on top
// Files: Save / Revert
let autoSaveEnabled = this.contextService.isAutoSaveEnabled();
let autoSaveEnabled = this.textFileService.isAutoSaveEnabled();
if ((!autoSaveEnabled || element.dirty) && element.isFile) {
actions.push(new Separator());
......
......@@ -11,7 +11,7 @@ import paths = require('vs/base/common/paths');
import errors = require('vs/base/common/errors');
import labels = require('vs/base/common/labels');
import {disposeAll, IDisposable} from 'vs/base/common/lifecycle';
import filesCommon = require('vs/workbench/parts/files/common/files');
import {ITextFileService, IWorkingFilesModel, IWorkingFileModelChangeEvent, IWorkingFileEntry, EventType, LocalFileChangeEvent, WORKING_FILES_MODEL_ENTRY_CLASS_ID} from 'vs/workbench/parts/files/common/files';
import {IFileStat, FileChangeType, FileChangesEvent, EventType as FileEventType} from 'vs/platform/files/common/files';
import {UntitledEditorEvent, EventType as WorkbenchEventType, EditorEvent} from 'vs/workbench/common/events';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
......@@ -22,14 +22,14 @@ import {asFileEditorInput} from 'vs/workbench/common/editor';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {IEventService} from 'vs/platform/event/common/event';
export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
export class WorkingFilesModel implements IWorkingFilesModel {
private static STORAGE_KEY = 'workingFiles.model.entries';
private entries: WorkingFileEntry[];
private pathLabelProvider: labels.PathLabelProvider;
private mapEntryToResource: { [resource: string]: WorkingFileEntry; };
private _onModelChange: Emitter<filesCommon.IWorkingFileModelChangeEvent>;
private _onModelChange: Emitter<IWorkingFileModelChangeEvent>;
private _onWorkingFileChange: Emitter<WorkingFileEntry>;
private toDispose: IDisposable[];
......@@ -39,13 +39,14 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
@IPartService private partService: IPartService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@ITextFileService private textFileService: ITextFileService
) {
this.pathLabelProvider = new labels.PathLabelProvider(this.contextService);
this.entries = [];
this.toDispose = [];
this.mapEntryToResource = Object.create(null);
this._onModelChange = new Emitter<filesCommon.IWorkingFileModelChangeEvent>();
this._onModelChange = new Emitter<IWorkingFileModelChangeEvent>();
this._onWorkingFileChange = new Emitter<WorkingFileEntry>();
this.load();
......@@ -55,7 +56,7 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
private registerListeners(): void {
// listen to global file changes to clean up model
this.toDispose.push(this.eventService.addListener2('files.internal:fileChanged', (e: filesCommon.LocalFileChangeEvent) => this.onLocalFileChange(e)));
this.toDispose.push(this.eventService.addListener2('files.internal:fileChanged', (e: LocalFileChangeEvent) => this.onLocalFileChange(e)));
this.toDispose.push(this.eventService.addListener2(FileEventType.FILE_CHANGES, (e) => this.onFileChanges(e)));
// listen to untitled
......@@ -63,10 +64,10 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
this.toDispose.push(this.eventService.addListener2(WorkbenchEventType.UNTITLED_FILE_DELETED, (e) => this.onUntitledFileDeleted(e)));
// listen to files being changed locally
this.toDispose.push(this.eventService.addListener2(filesCommon.EventType.FILE_DIRTY, (e: filesCommon.LocalFileChangeEvent) => this.onTextFileDirty(e)));
this.toDispose.push(this.eventService.addListener2(filesCommon.EventType.FILE_SAVE_ERROR, (e: filesCommon.LocalFileChangeEvent) => this.onTextFileSaveError(e)));
this.toDispose.push(this.eventService.addListener2(filesCommon.EventType.FILE_SAVED, (e: filesCommon.LocalFileChangeEvent) => this.onTextFileSaved(e)));
this.toDispose.push(this.eventService.addListener2(filesCommon.EventType.FILE_REVERTED, (e: filesCommon.LocalFileChangeEvent) => this.onTextFileReverted(e)));
this.toDispose.push(this.eventService.addListener2(EventType.FILE_DIRTY, (e: LocalFileChangeEvent) => this.onTextFileDirty(e)));
this.toDispose.push(this.eventService.addListener2(EventType.FILE_SAVE_ERROR, (e: LocalFileChangeEvent) => this.onTextFileSaveError(e)));
this.toDispose.push(this.eventService.addListener2(EventType.FILE_SAVED, (e: LocalFileChangeEvent) => this.onTextFileSaved(e)));
this.toDispose.push(this.eventService.addListener2(EventType.FILE_REVERTED, (e: LocalFileChangeEvent) => this.onTextFileReverted(e)));
// clean up model on set input error
this.toDispose.push(this.eventService.addListener2(WorkbenchEventType.EDITOR_SET_INPUT_ERROR, (e: EditorEvent) => this.onEditorInputSetError(e)));
......@@ -83,23 +84,23 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
}
}
private onTextFileDirty(e: filesCommon.LocalFileChangeEvent): void {
if (!this.contextService.isAutoSaveEnabled()) {
private onTextFileDirty(e: LocalFileChangeEvent): void {
if (!this.textFileService.isAutoSaveEnabled()) {
this.updateDirtyState(e.getAfter().resource, true); // no indication needed when auto save is turned off and we didn't show dirty
} else {
this.addEntry(e.getAfter().resource);
}
}
private onTextFileSaveError(e: filesCommon.LocalFileChangeEvent): void {
private onTextFileSaveError(e: LocalFileChangeEvent): void {
this.updateDirtyState(e.getAfter().resource, true);
}
private onTextFileSaved(e: filesCommon.LocalFileChangeEvent): void {
private onTextFileSaved(e: LocalFileChangeEvent): void {
this.updateDirtyState(e.getAfter().resource, false);
}
private onTextFileReverted(e: filesCommon.LocalFileChangeEvent): void {
private onTextFileReverted(e: LocalFileChangeEvent): void {
if (this.hasEntry(e.getAfter().resource)) {
this.updateDirtyState(e.getAfter().resource, false);
}
......@@ -119,7 +120,7 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
}
}
private onLocalFileChange(e: filesCommon.LocalFileChangeEvent): void {
private onLocalFileChange(e: LocalFileChangeEvent): void {
if (e.gotMoved()) {
this.moveEntry(e.getBefore().resource, e.getAfter().resource);
}
......@@ -144,7 +145,7 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
}
}
public get onModelChange(): Event<filesCommon.IWorkingFileModelChangeEvent> {
public get onModelChange(): Event<IWorkingFileModelChangeEvent> {
return this._onModelChange.event;
}
......@@ -395,7 +396,7 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel {
this.toDispose = disposeAll(this.toDispose);
}
private fireModelChange(event: filesCommon.IWorkingFileModelChangeEvent): void {
private fireModelChange(event: IWorkingFileModelChangeEvent): void {
this._onModelChange.fire(event);
}
......@@ -413,7 +414,7 @@ interface ISerializedWorkingFileEntry {
index: number;
}
export class WorkingFileEntry implements filesCommon.IWorkingFileEntry {
export class WorkingFileEntry implements IWorkingFileEntry {
private _resource: uri;
private _index: number;
private _dirty: boolean;
......@@ -445,7 +446,7 @@ export class WorkingFileEntry implements filesCommon.IWorkingFileEntry {
}
public get CLASS_ID(): string {
return filesCommon.WORKING_FILES_MODEL_ENTRY_CLASS_ID;
return WORKING_FILES_MODEL_ENTRY_CLASS_ID;
}
public get isFile(): boolean {
......
......@@ -288,6 +288,10 @@ export interface IResult {
success?: boolean;
}
export interface IAutoSaveConfiguration {
autoSaveAfterDelay: number;
}
export var ITextFileService = createDecorator<ITextFileService>(TEXT_FILE_SERVICE_ID);
export interface ITextFileService extends IDisposable {
......@@ -360,4 +364,14 @@ export interface ITextFileService extends IDisposable {
* Provides access to the list of working files.
*/
getWorkingFilesModel(): IWorkingFilesModel;
/**
* Checks if the user configured auto save to be enabled or not
*/
isAutoSaveEnabled(): boolean;
/**
* Convinient fast access to the configured auto save settings.
*/
getAutoSaveConfiguration(): IAutoSaveConfiguration;
}
\ No newline at end of file
......@@ -160,7 +160,7 @@ export class FileTracker implements IWorkbenchContribution {
}
private onTextFileDirty(e: LocalFileChangeEvent): void {
if (!this.contextService.isAutoSaveEnabled() && !this.isDocumentedEdited) {
if (!this.textFileService.isAutoSaveEnabled() && !this.isDocumentedEdited) {
this.updateDocumentEdited(); // no indication needed when auto save is turned off and we didn't show dirty
}
}
......
......@@ -23,9 +23,9 @@ import {SyncActionDescriptor} from 'vs/platform/actions/common/actions';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {IFileService} from 'vs/platform/files/common/files';
import {IInstantiationService, INullService} from 'vs/platform/instantiation/common/instantiation';
import {IEventService} from 'vs/platform/event/common/event';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle';
import {IConfigurationService, IConfigurationServiceEvent, ConfigurationServiceEventTypes} from 'vs/platform/configuration/common/configuration';
import remote = require('remote');
import ipc = require('ipc');
......@@ -35,20 +35,14 @@ const Dialog = remote.require('dialog');
export class TextFileService extends BrowserTextFileService {
constructor(
@IEventService eventService: IEventService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IInstantiationService private instantiationService: IInstantiationService,
@IInstantiationService instantiationService: IInstantiationService,
@IFileService private fileService: IFileService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@ILifecycleService lifecycleService: ILifecycleService
@ILifecycleService lifecycleService: ILifecycleService,
@IConfigurationService configurationService: IConfigurationService
) {
super(eventService, contextService, instantiationService, lifecycleService);
this.registerAutoSaveActions();
}
protected onOptionsChanged(): void {
super.onOptionsChanged();
super(contextService, instantiationService, configurationService, lifecycleService);
this.registerAutoSaveActions();
}
......
......@@ -14,7 +14,7 @@ import {create} from 'vs/platform/instantiation/common/instantiationService';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {MainTelemetryService} from 'vs/platform/telemetry/browser/mainTelemetryService';
import {FileTracker} from 'vs/workbench/parts/files/browser/fileTracker';
import {TestFileService, TestEditorService, TestPartService, MockRequestService, TestEventService, TestContextService, TestStorageService, TestWorkspace} from 'vs/workbench/test/browser/servicesTestUtils';
import {TestFileService, TestLifecycleService, TestEditorService, TestPartService, MockRequestService, TestConfigurationService, TestEventService, TestContextService, TestStorageService, TestWorkspace} from 'vs/workbench/test/browser/servicesTestUtils';
import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils';
function toResource(path) {
......@@ -44,7 +44,9 @@ suite('Files - FileEditorInput', () => {
partService: new TestPartService(),
modeService: createMockModeService(),
modelService: createMockModelService(),
telemetryService: telemetryService
telemetryService: telemetryService,
lifecycleService: new TestLifecycleService(),
configurationService: new TestConfigurationService()
});
let textFileServices = instantiationService.createInstance(<any>TextFileService);
......@@ -109,8 +111,8 @@ suite('Files - FileEditorInput', () => {
});
test('Input.matches() - FileEditorInput', function() {
let fileEditorInput = new FileEditorInput(toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0, void 0, void 0);
let contentEditorInput2 = new FileEditorInput(toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0, void 0, void 0);
let fileEditorInput = new FileEditorInput(toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0, void 0, void 0, void 0);
let contentEditorInput2 = new FileEditorInput(toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0, void 0, void 0, void 0);
assert.strictEqual(fileEditorInput.matches(null), false);
assert.strictEqual(fileEditorInput.matches(fileEditorInput), true);
......@@ -133,7 +135,9 @@ suite('Files - FileEditorInput', () => {
partService: new TestPartService(),
modeService: createMockModeService(),
modelService: createMockModelService(),
telemetryService: telemetryService
telemetryService: telemetryService,
lifecycleService: new TestLifecycleService(),
configurationService: new TestConfigurationService()
});
let textFileServices = instantiationService.createInstance(<any>TextFileService);
......@@ -175,7 +179,9 @@ suite('Files - FileEditorInput', () => {
partService: new TestPartService(),
modeService: createMockModeService(),
modelService: createMockModelService(),
telemetryService: telemetryService
telemetryService: telemetryService,
lifecycleService: new TestLifecycleService(),
configurationService: new TestConfigurationService()
});
let textFileServices = instantiationService.createInstance(<any>TextFileService);
......
......@@ -15,7 +15,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat
import {create} from 'vs/platform/instantiation/common/instantiationService';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {EventType, LocalFileChangeEvent} from 'vs/workbench/parts/files/common/files';
import {TestFileService, TestPartService, TestEditorService, TestUntitledEditorService, TestStorageService, TestTelemetryService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/browser/servicesTestUtils';
import {TestFileService, TestLifecycleService, TestPartService, TestEditorService, TestConfigurationService, TestUntitledEditorService, TestStorageService, TestTelemetryService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/browser/servicesTestUtils';
import Severity = require('vs/base/common/severity');
import {IEventService} from 'vs/platform/event/common/event';
import {IMessageService, IConfirmation} from 'vs/platform/message/common/message';
......@@ -48,10 +48,14 @@ suite('Files - TextFileEditorModel', () => {
editorService: new TestEditorService(),
partService: new TestPartService(),
modeService: createMockModeService(),
modelService: createMockModelService()
modelService: createMockModelService(),
lifecycleService: new TestLifecycleService(),
configurationService: new TestConfigurationService()
});
textFileService = <TextFileService>baseInstantiationService.createInstance(<any>TextFileService);
baseInstantiationService.registerService('textFileService', textFileService);
});
teardown(() => {
......
......@@ -37,9 +37,9 @@ suite('Files - TextFileEditor', () => {
equal(Registry.as(ExtensionId).getEditors().length, oldEditorCnt + 2);
equal(Registry.as(ExtensionId).getEditorInputs().length, oldInputCnt + 2);
strictEqual(Registry.as(ExtensionId).getEditor(new FileEditorInput(URI.file(join('C:\\', "/foo/bar/foobar.html")), "test-text/html", void 0, void 0, void 0)), d1);
strictEqual(Registry.as(ExtensionId).getEditor(new FileEditorInput(URI.file(join('C:\\', "/foo/bar/foobar.js")), "test-text/javascript", void 0, void 0, void 0)), d1);
strictEqual(Registry.as(ExtensionId).getEditor(new FileEditorInput(URI.file(join('C:\\', "/foo/bar/foobar.css")), "test-text/css", void 0, void 0, void 0)), d2);
strictEqual(Registry.as(ExtensionId).getEditor(new FileEditorInput(URI.file(join('C:\\', "/foo/bar/foobar.html")), "test-text/html", void 0, void 0, void 0, void 0)), d1);
strictEqual(Registry.as(ExtensionId).getEditor(new FileEditorInput(URI.file(join('C:\\', "/foo/bar/foobar.js")), "test-text/javascript", void 0, void 0, void 0, void 0)), d1);
strictEqual(Registry.as(ExtensionId).getEditor(new FileEditorInput(URI.file(join('C:\\', "/foo/bar/foobar.css")), "test-text/css", void 0, void 0, void 0, void 0)), d2);
Registry.as(ExtensionId).setEditors(oldEditors);
});
......
......@@ -17,7 +17,7 @@ import {StringEditorModel} from 'vs/workbench/browser/parts/editor/stringEditorM
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {TextFileEditorModel} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {TestEventService, TestPartService, TestStorageService, TestRequestService, TestContextService, TestWorkspace, TestEditorService, MockRequestService} from 'vs/workbench/test/browser/servicesTestUtils';
import {TestEventService, TestLifecycleService, TestPartService, TestStorageService, TestConfigurationService, TestRequestService, TestContextService, TestWorkspace, TestEditorService, MockRequestService} from 'vs/workbench/test/browser/servicesTestUtils';
import {Viewlet} from 'vs/workbench/browser/viewlet';
import {EventType} from 'vs/workbench/common/events';
import {MainTelemetryService} from 'vs/platform/telemetry/browser/mainTelemetryService';
......@@ -243,16 +243,20 @@ suite('Workbench UI Services', () => {
contextService: contextService,
requestService: requestService,
telemetryService: telemetryService,
configurationService: new TestConfigurationService(),
untitledEditorService: new UntitledEditorService(),
storageService: new TestStorageService(),
editorService: editorService,
partService: new TestPartService(),
modeService: createMockModeService(),
modelService: createMockModelService(),
lifecycleService: new TestLifecycleService(),
fileService: TestFileService
};
let inst = create(services);
let textFileService = inst.createInstance(<any>TextFileService);
inst.registerService('textFileService', textFileService);
services['instantiationService'] = inst;
let activeInput: EditorInput = inst.createInstance(FileEditorInput, toResource('/something.js'), 'text/javascript', void 0);
......@@ -347,14 +351,15 @@ suite('Workbench UI Services', () => {
untitledEditorService: new UntitledEditorService(),
editorService: editorService,
partService: new TestPartService(),
modelService: createMockModelService()
lifecycleService: new TestLifecycleService(),
modelService: createMockModelService(),
configurationService: new TestConfigurationService()
};
let inst = create(services);
let textFileService = inst.createInstance(<any>TextFileService);
services['textFileService'] = textFileService;
services['instantiationService'] = inst;
inst.registerService('textFileService', textFileService);
services['instantiationService'] = inst;
let activeInput: EditorInput = inst.createInstance(FileEditorInput, toResource('/something.js'), 'text/javascript', void 0);
let testEditorPart = new TestEditorPart();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册