提交 5eaf9f05 编写于 作者: A Alex Dima

Adopt ModelBuilder in workbench

上级 a4ac000b
...@@ -20,7 +20,6 @@ import 'vs/base/common/uri'; ...@@ -20,7 +20,6 @@ import 'vs/base/common/uri';
// platform common // platform common
import 'vs/platform/platform'; import 'vs/platform/platform';
import 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import 'vs/platform/files/common/files';
import 'vs/platform/request/common/request'; import 'vs/platform/request/common/request';
import 'vs/platform/workspace/common/workspace'; import 'vs/platform/workspace/common/workspace';
import 'vs/platform/telemetry/common/telemetry'; import 'vs/platform/telemetry/common/telemetry';
......
...@@ -4,16 +4,12 @@ ...@@ -4,16 +4,12 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import {IDisposable} from 'vs/base/common/lifecycle'; import {IStringStream} from 'vs/platform/files/common/files';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import {DefaultEndOfLine, ITextModelCreationOptions, ITextModelResolvedOptions, IRawText} from 'vs/editor/common/editorCommon'; import {DefaultEndOfLine, ITextModelCreationOptions, ITextModelResolvedOptions, IRawText} from 'vs/editor/common/editorCommon';
import * as strings from 'vs/base/common/strings'; import * as strings from 'vs/base/common/strings';
import {guessIndentation} from 'vs/editor/common/model/indentationGuesser'; import {guessIndentation} from 'vs/editor/common/model/indentationGuesser';
import {TPromise} from 'vs/base/common/winjs.base';
export interface IStringStream {
onData(listener: (chunk:string)=>void): IDisposable;
onEnd(listener: ()=>void): IDisposable;
}
export class ModelBuilderResult { export class ModelBuilderResult {
rawText: IRawText; rawText: IRawText;
...@@ -111,6 +107,31 @@ export class ModelBuilder { ...@@ -111,6 +107,31 @@ export class ModelBuilder {
private lineBasedBuilder: ModelLineBasedBuilder; private lineBasedBuilder: ModelLineBasedBuilder;
private totalLength: number; private totalLength: number;
public static fromStringStream(stream:IStringStream, options:ITextModelCreationOptions): TPromise<ModelBuilderResult> {
return new TPromise<ModelBuilderResult>((c, e, p) => {
let done = false;
let builder = new ModelBuilder();
stream.on('data', (chunk) => {
builder.acceptChunk(chunk);
});
stream.on('error', (error) => {
if (!done) {
done = true;
e(error);
}
});
stream.on('end', () => {
if (!done) {
done = true;
c(builder.finish(options));
}
});
});
}
constructor() { constructor() {
this.leftoverPrevChunk = ''; this.leftoverPrevChunk = '';
this.leftoverEndsInCR = false; this.leftoverEndsInCR = false;
......
...@@ -41,6 +41,13 @@ export interface IFileService { ...@@ -41,6 +41,13 @@ export interface IFileService {
*/ */
resolveContent(resource: URI, options?: IResolveContentOptions): winjs.TPromise<IContent>; resolveContent(resource: URI, options?: IResolveContentOptions): winjs.TPromise<IContent>;
/**
* Resolve the contents of a file identified by the resource.
*
* The returned object contains properties of the file and the value as a readable stream.
*/
resolveStreamContent(resource: URI, options?: IResolveContentOptions): winjs.TPromise<IStreamContent>;
/** /**
* Returns the contents of all files by the given array of file resources. * Returns the contents of all files by the given array of file resources.
*/ */
...@@ -346,6 +353,32 @@ export interface IContent extends IBaseStat { ...@@ -346,6 +353,32 @@ export interface IContent extends IBaseStat {
encoding: string; encoding: string;
} }
/**
* A Stream emitting strings.
*/
export interface IStringStream {
on(event:'data', callback:(chunk:string)=>void): void;
on(event:'error', callback:(err:any)=>void): void;
on(event:'end', callback:()=>void): void;
on(event:string, callback:any): void;
}
/**
* Streamable content and meta information of a file.
*/
export interface IStreamContent extends IBaseStat {
/**
* The streamable content of a text file.
*/
value: IStringStream;
/**
* The encoding of the content if known.
*/
encoding: string;
}
export interface IResolveContentOptions { export interface IResolveContentOptions {
/** /**
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
'use strict'; 'use strict';
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import {EndOfLinePreference, IModel} from 'vs/editor/common/editorCommon'; import {EndOfLinePreference, IModel, IRawText} from 'vs/editor/common/editorCommon';
import {IMode} from 'vs/editor/common/modes'; import {IMode} from 'vs/editor/common/modes';
import {EditorModel} from 'vs/workbench/common/editor'; import {EditorModel} from 'vs/workbench/common/editor';
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
...@@ -55,28 +55,37 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd ...@@ -55,28 +55,37 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
/** /**
* Creates the text editor model with the provided value, mime (can be comma separated for multiple values) and optional resource URL. * Creates the text editor model with the provided value, mime (can be comma separated for multiple values) and optional resource URL.
*/ */
protected createTextEditorModel(value: string, resource?: URI, mime?: string): TPromise<EditorModel> { protected createTextEditorModel(value: string | IRawText, resource?: URI, mime?: string): TPromise<EditorModel> {
let firstLineText = this.getFirstLineText(value); let firstLineText = this.getFirstLineText(value);
let mode = this.getOrCreateMode(this.modeService, mime, firstLineText);
// To avoid flickering, give the mode at most 50ms to load. If the mode doesn't load in 50ms, proceed creating the model with a mode promise // To avoid flickering, give the mode at most 50ms to load. If the mode doesn't load in 50ms, proceed creating the model with a mode promise
return TPromise.any<any>([TPromise.timeout(50), this.getOrCreateMode(this.modeService, mime, firstLineText)]).then(() => { return TPromise.any<any>([TPromise.timeout(50), mode]).then(() => {
return this._createTextEditorModelNow(value, mode, resource);
});
}
private _createTextEditorModelNow(value: string | IRawText, mode: TPromise<IMode>, resource: URI): EditorModel {
let model = resource && this.modelService.getModel(resource); let model = resource && this.modelService.getModel(resource);
let mode = this.getOrCreateMode(this.modeService, mime, firstLineText);
if (!model) { if (!model) {
model = this.modelService.createModel(value, mode, resource); model = this.modelService.createModel(value, mode, resource);
this.createdEditorModel = true; this.createdEditorModel = true;
} else { } else {
if (typeof value === 'string') {
model.setValue(value); model.setValue(value);
} else {
model.setValueFromRawText(value);
}
model.setMode(mode); model.setMode(mode);
} }
this.textEditorModelHandle = model.uri; this.textEditorModelHandle = model.uri;
return this; return this;
});
} }
private getFirstLineText(value: string): string { private getFirstLineText(value: string | IRawText): string {
if (typeof value === 'string') {
let firstLineText = value.substr(0, 100); let firstLineText = value.substr(0, 100);
let crIndex = firstLineText.indexOf('\r'); let crIndex = firstLineText.indexOf('\r');
...@@ -89,9 +98,10 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd ...@@ -89,9 +98,10 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
lfIndex = firstLineText.length; lfIndex = firstLineText.length;
} }
firstLineText = firstLineText.substr(0, Math.min(crIndex, lfIndex)); return firstLineText.substr(0, Math.min(crIndex, lfIndex));
} else {
return firstLineText; return value.lines[0].substr(0, 100);
}
} }
/** /**
...@@ -106,12 +116,17 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd ...@@ -106,12 +116,17 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
/** /**
* Updates the text editor model with the provided value. If the value is the same as the model has, this is a no-op. * Updates the text editor model with the provided value. If the value is the same as the model has, this is a no-op.
*/ */
protected updateTextEditorModel(newValue: string): void { protected updateTextEditorModel(newValue: string | IRawText): void {
if (!this.textEditorModel) { if (!this.textEditorModel) {
return; return;
} }
let rawText = RawText.fromStringWithModelOptions(newValue, this.textEditorModel); let rawText: IRawText;
if (typeof newValue === 'string') {
rawText = RawText.fromStringWithModelOptions(newValue, this.textEditorModel);
} else {
rawText = newValue;
}
// Return early if the text is already set in that form // Return early if the text is already set in that form
if (this.textEditorModel.equals(rawText)) { if (this.textEditorModel.equals(rawText)) {
......
...@@ -22,7 +22,7 @@ import {IFileService, IFileOperationResult, FileOperationResult} from 'vs/platfo ...@@ -22,7 +22,7 @@ import {IFileService, IFileOperationResult, FileOperationResult} from 'vs/platfo
import {TextFileEditorModel, ISaveErrorHandler} from 'vs/workbench/parts/files/common/editors/textFileEditorModel'; import {TextFileEditorModel, ISaveErrorHandler} from 'vs/workbench/parts/files/common/editors/textFileEditorModel';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IEventService} from 'vs/platform/event/common/event'; import {IEventService} from 'vs/platform/event/common/event';
import {EventType as FileEventType, TextFileChangeEvent} from 'vs/workbench/parts/files/common/files'; import {EventType as FileEventType, TextFileChangeEvent, ITextFileService} from 'vs/workbench/parts/files/common/files';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IMessageService, IMessageWithAction, Severity, CancelAction} from 'vs/platform/message/common/message'; import {IMessageService, IMessageWithAction, Severity, CancelAction} from 'vs/platform/message/common/message';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
...@@ -167,7 +167,8 @@ export class FileOnDiskEditorInput extends ResourceEditorInput { ...@@ -167,7 +167,8 @@ export class FileOnDiskEditorInput extends ResourceEditorInput {
@IModelService modelService: IModelService, @IModelService modelService: IModelService,
@IModeService private modeService: IModeService, @IModeService private modeService: IModeService,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@IFileService private fileService: IFileService @IFileService private fileService: IFileService,
@ITextFileService private textFileService: ITextFileService
) { ) {
// We create a new resource URI here that is different from the file resource because we represent the state of // We create a new resource URI here that is different from the file resource because we represent the state of
// the file as it is on disk and not as it is (potentially cached) in Code. That allows us to have a different // the file as it is on disk and not as it is (potentially cached) in Code. That allows us to have a different
...@@ -185,7 +186,7 @@ export class FileOnDiskEditorInput extends ResourceEditorInput { ...@@ -185,7 +186,7 @@ export class FileOnDiskEditorInput extends ResourceEditorInput {
public resolve(refresh?: boolean): TPromise<EditorModel> { public resolve(refresh?: boolean): TPromise<EditorModel> {
// Make sure our file from disk is resolved up to date // Make sure our file from disk is resolved up to date
return this.fileService.resolveContent(this.fileResource).then(content => { return this.textFileService.resolveTextContent(this.fileResource).then(content => {
this.lastModified = content.mtime; this.lastModified = content.mtime;
const codeEditorModel = this.modelService.getModel(this.resource); const codeEditorModel = this.modelService.getModel(this.resource);
...@@ -193,7 +194,7 @@ export class FileOnDiskEditorInput extends ResourceEditorInput { ...@@ -193,7 +194,7 @@ export class FileOnDiskEditorInput extends ResourceEditorInput {
this.modelService.createModel(content.value, this.modeService.getOrCreateMode(this.mime), this.resource); this.modelService.createModel(content.value, this.modeService.getOrCreateMode(this.mime), this.resource);
this.createdEditorModel = true; this.createdEditorModel = true;
} else { } else {
codeEditorModel.setValue(content.value); codeEditorModel.setValueFromRawText(content.value);
} }
return super.resolve(refresh); return super.resolve(refresh);
......
...@@ -10,16 +10,17 @@ import errors = require('vs/base/common/errors'); ...@@ -10,16 +10,17 @@ import errors = require('vs/base/common/errors');
import Event, {Emitter} from 'vs/base/common/event'; import Event, {Emitter} from 'vs/base/common/event';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput'; import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {CACHE, TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel'; import {CACHE, TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel';
import {IResult, ITextFileOperationResult, ITextFileService, IAutoSaveConfiguration, AutoSaveMode} from 'vs/workbench/parts/files/common/files'; import {IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode} from 'vs/workbench/parts/files/common/files';
import {ConfirmResult} from 'vs/workbench/common/editor'; import {ConfirmResult} from 'vs/workbench/common/editor';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService'; import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IFilesConfiguration, IFileOperationResult, FileOperationResult, AutoSaveConfiguration} from 'vs/platform/files/common/files'; import {IStringStream, IFileService, IResolveContentOptions, IFilesConfiguration, IFileOperationResult, FileOperationResult, AutoSaveConfiguration} from 'vs/platform/files/common/files';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IEventService} from 'vs/platform/event/common/event'; import {IEventService} from 'vs/platform/event/common/event';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IRawText} from 'vs/editor/common/editorCommon';
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService'; import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
/** /**
...@@ -45,7 +46,8 @@ export abstract class TextFileService implements ITextFileService { ...@@ -45,7 +46,8 @@ export abstract class TextFileService implements ITextFileService {
@ITelemetryService private telemetryService: ITelemetryService, @ITelemetryService private telemetryService: ITelemetryService,
@IWorkbenchEditorService protected editorService: IWorkbenchEditorService, @IWorkbenchEditorService protected editorService: IWorkbenchEditorService,
@IEditorGroupService private editorGroupService: IEditorGroupService, @IEditorGroupService private editorGroupService: IEditorGroupService,
@IEventService private eventService: IEventService @IEventService private eventService: IEventService,
@IFileService protected fileService: IFileService
) { ) {
this.listenerToUnbind = []; this.listenerToUnbind = [];
this._onAutoSaveConfigurationChange = new Emitter<IAutoSaveConfiguration>(); this._onAutoSaveConfigurationChange = new Emitter<IAutoSaveConfiguration>();
...@@ -60,6 +62,26 @@ export abstract class TextFileService implements ITextFileService { ...@@ -60,6 +62,26 @@ export abstract class TextFileService implements ITextFileService {
this.telemetryService.publicLog('autoSave', this.getAutoSaveConfiguration()); this.telemetryService.publicLog('autoSave', this.getAutoSaveConfiguration());
} }
public resolveTextContent(resource: URI, options?: IResolveContentOptions): TPromise<IRawTextContent> {
return this.fileService.resolveStreamContent(resource, options).then((streamContent) => {
return this.stringStreamToRawText(streamContent.value).then((res) => {
let r:IRawTextContent = {
resource: streamContent.resource,
name: streamContent.name,
mtime: streamContent.mtime,
etag: streamContent.etag,
mime: streamContent.mime,
encoding: streamContent.encoding,
value: res.rawText,
valueLogicalHash: res.hash
};
return r;
});
});
}
protected abstract stringStreamToRawText(stream:IStringStream): TPromise<{rawText:IRawText; hash:string;}>;
public get onAutoSaveConfigurationChange(): Event<IAutoSaveConfiguration> { public get onAutoSaveConfigurationChange(): Event<IAutoSaveConfiguration> {
return this._onAutoSaveConfigurationChange.event; return this._onAutoSaveConfigurationChange.event;
} }
......
...@@ -18,7 +18,7 @@ import {EventType as WorkbenchEventType, ResourceEvent} from 'vs/workbench/commo ...@@ -18,7 +18,7 @@ import {EventType as WorkbenchEventType, ResourceEvent} from 'vs/workbench/commo
import {EventType as FileEventType, TextFileChangeEvent, ITextFileService, IAutoSaveConfiguration, ModelState} from 'vs/workbench/parts/files/common/files'; import {EventType as FileEventType, TextFileChangeEvent, ITextFileService, IAutoSaveConfiguration, ModelState} from 'vs/workbench/parts/files/common/files';
import {EncodingMode, EditorModel, IEncodingSupport} from 'vs/workbench/common/editor'; import {EncodingMode, EditorModel, IEncodingSupport} from 'vs/workbench/common/editor';
import {BaseTextEditorModel} from 'vs/workbench/common/editor/textEditorModel'; import {BaseTextEditorModel} from 'vs/workbench/common/editor/textEditorModel';
import {IFileService, IFileStat, IFileOperationResult, FileOperationResult, IContent} from 'vs/platform/files/common/files'; import {IFileService, IFileStat, IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files';
import {IEventService} from 'vs/platform/event/common/event'; import {IEventService} from 'vs/platform/event/common/event';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IMessageService, Severity} from 'vs/platform/message/common/message'; import {IMessageService, Severity} from 'vs/platform/message/common/message';
...@@ -208,7 +208,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin ...@@ -208,7 +208,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin
} }
// Resolve Content // Resolve Content
return this.fileService.resolveContent(this.resource, { acceptTextOnly: true, etag: etag, encoding: this.preferredEncoding }).then((content: IContent) => { return this.textFileService.resolveTextContent(this.resource, { acceptTextOnly: true, etag: etag, encoding: this.preferredEncoding }).then((content) => {
diag('load() - resolved content', this.resource, new Date()); diag('load() - resolved content', this.resource, new Date());
// Telemetry // Telemetry
......
...@@ -8,10 +8,10 @@ import {TPromise} from 'vs/base/common/winjs.base'; ...@@ -8,10 +8,10 @@ import {TPromise} from 'vs/base/common/winjs.base';
import {Event as BaseEvent, PropertyChangeEvent} from 'vs/base/common/events'; import {Event as BaseEvent, PropertyChangeEvent} from 'vs/base/common/events';
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import Event from 'vs/base/common/event'; import Event from 'vs/base/common/event';
import {IModel, IEditorOptions} from 'vs/editor/common/editorCommon'; import {IModel, IEditorOptions, IRawText} from 'vs/editor/common/editorCommon';
import {IDisposable} from 'vs/base/common/lifecycle'; import {IDisposable} from 'vs/base/common/lifecycle';
import {EncodingMode, EditorInput, IFileEditorInput, ConfirmResult, IWorkbenchEditorConfiguration} from 'vs/workbench/common/editor'; import {EncodingMode, EditorInput, IFileEditorInput, ConfirmResult, IWorkbenchEditorConfiguration} from 'vs/workbench/common/editor';
import {IFileStat, IFilesConfiguration} from 'vs/platform/files/common/files'; import {IFileStat, IFilesConfiguration, IBaseStat, IResolveContentOptions} from 'vs/platform/files/common/files';
import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation'; import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation';
import {FileStat} from 'vs/workbench/parts/files/common/explorerViewModel'; import {FileStat} from 'vs/workbench/parts/files/common/explorerViewModel';
...@@ -246,9 +246,31 @@ export enum AutoSaveMode { ...@@ -246,9 +246,31 @@ export enum AutoSaveMode {
export var ITextFileService = createDecorator<ITextFileService>(TEXT_FILE_SERVICE_ID); export var ITextFileService = createDecorator<ITextFileService>(TEXT_FILE_SERVICE_ID);
export interface IRawTextContent extends IBaseStat {
/**
* The line grouped content of a text file.
*/
value: IRawText;
/**
* The line grouped logical hash of a text file.
*/
valueLogicalHash: string;
/**
* The encoding of the content if known.
*/
encoding: string;
}
export interface ITextFileService extends IDisposable { export interface ITextFileService extends IDisposable {
serviceId: ServiceIdentifier<any>; serviceId: ServiceIdentifier<any>;
/**
* Resolve the contents of a file identified by the resource.
*/
resolveTextContent(resource: URI, options?: IResolveContentOptions): TPromise<IRawTextContent>;
/** /**
* A resource is dirty if it has unsaved changes or is an untitled file not yet saved. * A resource is dirty if it has unsaved changes or is an untitled file not yet saved.
* *
......
...@@ -18,7 +18,7 @@ import {TextFileService as AbstractTextFileService} from 'vs/workbench/parts/fil ...@@ -18,7 +18,7 @@ import {TextFileService as AbstractTextFileService} from 'vs/workbench/parts/fil
import {CACHE, TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel'; import {CACHE, TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel';
import {ITextFileOperationResult, AutoSaveMode} from 'vs/workbench/parts/files/common/files'; import {ITextFileOperationResult, AutoSaveMode} from 'vs/workbench/parts/files/common/files';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService'; import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {IFileService} from 'vs/platform/files/common/files'; import {IFileService, IStringStream} from 'vs/platform/files/common/files';
import {BinaryEditorModel} from 'vs/workbench/common/editor/binaryEditorModel'; import {BinaryEditorModel} from 'vs/workbench/common/editor/binaryEditorModel';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService'; import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
...@@ -29,13 +29,15 @@ import {IModeService} from 'vs/editor/common/services/modeService'; ...@@ -29,13 +29,15 @@ import {IModeService} from 'vs/editor/common/services/modeService';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService'; import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService';
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService'; import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
import {IModelService} from 'vs/editor/common/services/modelService';
import {ModelBuilder, ModelBuilderResult} from 'vs/editor/node/model/modelBuilder';
export class TextFileService extends AbstractTextFileService { export class TextFileService extends AbstractTextFileService {
constructor( constructor(
@IWorkspaceContextService contextService: IWorkspaceContextService, @IWorkspaceContextService contextService: IWorkspaceContextService,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@IFileService private fileService: IFileService, @IFileService fileService: IFileService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService, @IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@ILifecycleService private lifecycleService: ILifecycleService, @ILifecycleService private lifecycleService: ILifecycleService,
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
...@@ -44,9 +46,10 @@ export class TextFileService extends AbstractTextFileService { ...@@ -44,9 +46,10 @@ export class TextFileService extends AbstractTextFileService {
@IModeService private modeService: IModeService, @IModeService private modeService: IModeService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService, @IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IEditorGroupService editorGroupService: IEditorGroupService, @IEditorGroupService editorGroupService: IEditorGroupService,
@IWindowService private windowService: IWindowService @IWindowService private windowService: IWindowService,
@IModelService private modelService: IModelService
) { ) {
super(contextService, instantiationService, configurationService, telemetryService, editorService, editorGroupService, eventService); super(contextService, instantiationService, configurationService, telemetryService, editorService, editorGroupService, eventService, fileService);
this.init(); this.init();
} }
...@@ -111,6 +114,10 @@ export class TextFileService extends AbstractTextFileService { ...@@ -111,6 +114,10 @@ export class TextFileService extends AbstractTextFileService {
super.dispose(); super.dispose();
} }
protected stringStreamToRawText(stream:IStringStream): TPromise<ModelBuilderResult> {
return ModelBuilder.fromStringStream(stream, this.modelService.getCreationOptions());
}
public revertAll(resources?: URI[], force?: boolean): TPromise<ITextFileOperationResult> { public revertAll(resources?: URI[], force?: boolean): TPromise<ITextFileOperationResult> {
// Revert files // Revert files
......
...@@ -24,9 +24,8 @@ import {InstantiationService} from 'vs/platform/instantiation/common/instantiati ...@@ -24,9 +24,8 @@ import {InstantiationService} from 'vs/platform/instantiation/common/instantiati
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IPartService} from 'vs/workbench/services/part/common/partService'; import {IPartService} from 'vs/workbench/services/part/common/partService';
import {ITextFileService} from 'vs/workbench/parts/files/common/files'; import {ITextFileService} from 'vs/workbench/parts/files/common/files';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {FileTracker} from 'vs/workbench/parts/files/browser/fileTracker'; import {FileTracker} from 'vs/workbench/parts/files/browser/fileTracker';
import {TestEditorGroupService, TestHistoryService, TestFileService, TestEditorService, TestPartService, TestConfigurationService, TestEventService, TestContextService, TestQuickOpenService, TestStorageService} from 'vs/workbench/test/common/servicesTestUtils'; import {TestTextFileService, TestEditorGroupService, TestHistoryService, TestFileService, TestEditorService, TestPartService, TestConfigurationService, TestEventService, TestContextService, TestQuickOpenService, TestStorageService} from 'vs/workbench/test/common/servicesTestUtils';
import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils'; import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils';
import {IHistoryService} from 'vs/workbench/services/history/common/history'; import {IHistoryService} from 'vs/workbench/services/history/common/history';
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService'; import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
...@@ -58,7 +57,7 @@ suite('Files - FileEditorInput', () => { ...@@ -58,7 +57,7 @@ suite('Files - FileEditorInput', () => {
services.set(IEditorGroupService, new TestEditorGroupService()); services.set(IEditorGroupService, new TestEditorGroupService());
services.set(ILifecycleService, NullLifecycleService); services.set(ILifecycleService, NullLifecycleService);
services.set(IConfigurationService, new TestConfigurationService()); services.set(IConfigurationService, new TestConfigurationService());
services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TextFileService)); services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TestTextFileService));
let input = instantiationService.createInstance(FileEditorInput, toResource('/foo/bar/file.js'), 'text/javascript', void 0); let input = instantiationService.createInstance(FileEditorInput, toResource('/foo/bar/file.js'), 'text/javascript', void 0);
let otherInput = instantiationService.createInstance(FileEditorInput, toResource('foo/bar/otherfile.js'), 'text/javascript', void 0); let otherInput = instantiationService.createInstance(FileEditorInput, toResource('foo/bar/otherfile.js'), 'text/javascript', void 0);
...@@ -128,7 +127,7 @@ suite('Files - FileEditorInput', () => { ...@@ -128,7 +127,7 @@ suite('Files - FileEditorInput', () => {
services.set(IEventService, eventService); services.set(IEventService, eventService);
services.set(IWorkspaceContextService, contextService); services.set(IWorkspaceContextService, contextService);
services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TextFileService)); services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TestTextFileService));
let fileEditorInput = instantiationService.createInstance(FileEditorInput, toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0); let fileEditorInput = instantiationService.createInstance(FileEditorInput, toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0);
let contentEditorInput2 = instantiationService.createInstance(FileEditorInput, toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0); let contentEditorInput2 = instantiationService.createInstance(FileEditorInput, toResource('/foo/bar/updatefile.js'), 'text/javascript', void 0);
...@@ -162,7 +161,7 @@ suite('Files - FileEditorInput', () => { ...@@ -162,7 +161,7 @@ suite('Files - FileEditorInput', () => {
services.set(ITelemetryService, telemetryService); services.set(ITelemetryService, telemetryService);
services.set(ILifecycleService, NullLifecycleService); services.set(ILifecycleService, NullLifecycleService);
services.set(IConfigurationService, new TestConfigurationService()); services.set(IConfigurationService, new TestConfigurationService());
services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TextFileService)); services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TestTextFileService));
let tracker = instantiationService.createInstance(FileTracker); let tracker = instantiationService.createInstance(FileTracker);
...@@ -208,7 +207,7 @@ suite('Files - FileEditorInput', () => { ...@@ -208,7 +207,7 @@ suite('Files - FileEditorInput', () => {
services.set(ILifecycleService, NullLifecycleService); services.set(ILifecycleService, NullLifecycleService);
services.set(IConfigurationService, new TestConfigurationService()); services.set(IConfigurationService, new TestConfigurationService());
services.set(IHistoryService, new TestHistoryService()); services.set(IHistoryService, new TestHistoryService());
services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TextFileService)); services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TestTextFileService));
let tracker = instantiationService.createInstance(FileTracker); let tracker = instantiationService.createInstance(FileTracker);
......
...@@ -27,9 +27,8 @@ import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/unti ...@@ -27,9 +27,8 @@ import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/unti
import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import PartService = require('vs/workbench/services/part/common/partService'); import PartService = require('vs/workbench/services/part/common/partService');
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {ITextFileService, EventType} from 'vs/workbench/parts/files/common/files'; import {ITextFileService, EventType} from 'vs/workbench/parts/files/common/files';
import {TestFileService, TestPartService, TestEditorService, TestConfigurationService, TestUntitledEditorService, TestStorageService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/common/servicesTestUtils'; import {TestTextFileService, TestFileService, TestPartService, TestEditorService, TestConfigurationService, TestUntitledEditorService, TestStorageService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/common/servicesTestUtils';
import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils'; import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils';
function toResource(path) { function toResource(path) {
...@@ -39,7 +38,7 @@ function toResource(path) { ...@@ -39,7 +38,7 @@ function toResource(path) {
let baseInstantiationService: IInstantiationService; let baseInstantiationService: IInstantiationService;
let messageService: TestMessageService; let messageService: TestMessageService;
let eventService: TestEventService; let eventService: TestEventService;
let textFileService: TextFileService; let textFileService: TestTextFileService;
suite('Files - TextFileEditorModel', () => { suite('Files - TextFileEditorModel', () => {
...@@ -64,7 +63,7 @@ suite('Files - TextFileEditorModel', () => { ...@@ -64,7 +63,7 @@ suite('Files - TextFileEditorModel', () => {
services.set(IConfigurationService, new TestConfigurationService()); services.set(IConfigurationService, new TestConfigurationService());
baseInstantiationService = new InstantiationService(services); baseInstantiationService = new InstantiationService(services);
textFileService = <any>baseInstantiationService.createInstance(<any>TextFileService); textFileService = <any>baseInstantiationService.createInstance(<any>TestTextFileService);
services.set(ITextFileService, textFileService); services.set(ITextFileService, textFileService);
}); });
......
...@@ -13,13 +13,12 @@ import {Registry} from 'vs/platform/platform'; ...@@ -13,13 +13,12 @@ import {Registry} from 'vs/platform/platform';
import {SyncDescriptor} from 'vs/platform/instantiation/common/descriptors'; import {SyncDescriptor} from 'vs/platform/instantiation/common/descriptors';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput'; import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {Extensions} from 'vs/workbench/browser/parts/editor/baseEditor'; import {Extensions} from 'vs/workbench/browser/parts/editor/baseEditor';
import {TestEventService, TestContextService} from 'vs/workbench/test/common/servicesTestUtils'; import {TestTextFileService, TestEventService, TestContextService} from 'vs/workbench/test/common/servicesTestUtils';
import {IEventService} from 'vs/platform/event/common/event'; import {IEventService} from 'vs/platform/event/common/event';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection'; import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection';
import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {ITextFileService} from 'vs/workbench/parts/files/common/files'; import {ITextFileService} from 'vs/workbench/parts/files/common/files';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
const ExtensionId = Extensions.Editors; const ExtensionId = Extensions.Editors;
...@@ -52,7 +51,7 @@ suite('Files - TextFileEditor', () => { ...@@ -52,7 +51,7 @@ suite('Files - TextFileEditor', () => {
services.set(IEventService, eventService); services.set(IEventService, eventService);
services.set(IWorkspaceContextService, contextService); services.set(IWorkspaceContextService, contextService);
services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TextFileService)); services.set(ITextFileService, <ITextFileService> instantiationService.createInstance(<any> TestTextFileService));
strictEqual(Registry.as(ExtensionId).getEditor(instantiationService.createInstance(FileEditorInput, URI.file(join('C:\\', '/foo/bar/foobar.html')), 'test-text/html', void 0)), d1); strictEqual(Registry.as(ExtensionId).getEditor(instantiationService.createInstance(FileEditorInput, URI.file(join('C:\\', '/foo/bar/foobar.html')), 'test-text/html', void 0)), d1);
strictEqual(Registry.as(ExtensionId).getEditor(instantiationService.createInstance(FileEditorInput, URI.file(join('C:\\', '/foo/bar/foobar.js')), 'test-text/javascript', void 0)), d1); strictEqual(Registry.as(ExtensionId).getEditor(instantiationService.createInstance(FileEditorInput, URI.file(join('C:\\', '/foo/bar/foobar.js')), 'test-text/javascript', void 0)), d1);
......
...@@ -13,7 +13,7 @@ import errors = require('vs/base/common/errors'); ...@@ -13,7 +13,7 @@ import errors = require('vs/base/common/errors');
import strings = require('vs/base/common/strings'); import strings = require('vs/base/common/strings');
import uri from 'vs/base/common/uri'; import uri from 'vs/base/common/uri';
import timer = require('vs/base/common/timer'); import timer = require('vs/base/common/timer');
import {IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IContent, IImportResult, IResolveContentOptions, IUpdateContentOptions} from 'vs/platform/files/common/files'; import {IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions} from 'vs/platform/files/common/files';
import {FileService as NodeFileService, IFileServiceOptions, IEncodingOverride} from 'vs/workbench/services/files/node/fileService'; import {FileService as NodeFileService, IFileServiceOptions, IEncodingOverride} from 'vs/workbench/services/files/node/fileService';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {IEventService} from 'vs/platform/event/common/event'; import {IEventService} from 'vs/platform/event/common/event';
...@@ -128,6 +128,17 @@ export class FileService implements IFileService { ...@@ -128,6 +128,17 @@ export class FileService implements IFileService {
}); });
} }
public resolveStreamContent(resource: uri, options?: IResolveContentOptions): TPromise<IStreamContent> {
let contentId = resource.toString();
let timerEvent = timer.start(timer.Topic.WORKBENCH, strings.format('Load {0}', contentId));
return this.raw.resolveStreamContent(resource, options).then((result) => {
timerEvent.stop();
return result;
});
}
public resolveContents(resources: uri[]): TPromise<IContent[]> { public resolveContents(resources: uri[]): TPromise<IContent[]> {
return this.raw.resolveContents(resources); return this.raw.resolveContents(resources);
} }
......
...@@ -141,10 +141,18 @@ export class FileService implements files.IFileService { ...@@ -141,10 +141,18 @@ export class FileService implements files.IFileService {
} }
public resolveContent(resource: uri, options?: files.IResolveContentOptions): TPromise<files.IContent> { public resolveContent(resource: uri, options?: files.IResolveContentOptions): TPromise<files.IContent> {
return this._resolveContent(resource, options, (resource, etag, enc) => this.resolveFileContent(resource, etag, enc));
}
public resolveStreamContent(resource: uri, options?: files.IResolveContentOptions): TPromise<files.IStreamContent> {
return this._resolveContent(resource, options, (resource, etag, enc) => this.resolveFileStreamContent(resource, etag, enc));
}
private _resolveContent<T extends files.IBaseStat>(resource: uri, options: files.IResolveContentOptions, contentResolver:(resource: uri, etag?: string, enc?: string) => TPromise<T>): TPromise<T> {
let absolutePath = this.toAbsolutePath(resource); let absolutePath = this.toAbsolutePath(resource);
// 1.) detect mimes // 1.) detect mimes
return nfcall(mime.detectMimesFromFile, absolutePath).then((detected: mime.IMimeAndEncoding) => { return nfcall(mime.detectMimesFromFile, absolutePath).then((detected: mime.IMimeAndEncoding):TPromise<T> => {
let isText = detected.mimes.indexOf(baseMime.MIME_BINARY) === -1; let isText = detected.mimes.indexOf(baseMime.MIME_BINARY) === -1;
// Return error early if client only accepts text and this is not text // Return error early if client only accepts text and this is not text
...@@ -173,7 +181,7 @@ export class FileService implements files.IFileService { ...@@ -173,7 +181,7 @@ export class FileService implements files.IFileService {
} }
// 2.) get content // 2.) get content
return this.resolveFileContent(resource, options && options.etag, preferredEncoding).then((content) => { return contentResolver(resource, options && options.etag, preferredEncoding).then((content) => {
// set our knowledge about the mime on the content obj // set our knowledge about the mime on the content obj
content.mime = detected.mimes.join(', '); content.mime = detected.mimes.join(', ');
...@@ -421,11 +429,11 @@ export class FileService implements files.IFileService { ...@@ -421,11 +429,11 @@ export class FileService implements files.IFileService {
}); });
} }
private resolveFileContent(resource: uri, etag?: string, enc?: string): TPromise<files.IContent> { private resolveFileStreamContent(resource: uri, etag?: string, enc?: string): TPromise<files.IStreamContent> {
let absolutePath = this.toAbsolutePath(resource); let absolutePath = this.toAbsolutePath(resource);
// 1.) stat // 1.) stat
return this.resolve(resource).then((model) => { return this.resolve(resource).then((model): TPromise<files.IStreamContent> => {
// Return early if file not modified since // Return early if file not modified since
if (etag && etag === model.etag) { if (etag && etag === model.etag) {
...@@ -441,29 +449,38 @@ export class FileService implements files.IFileService { ...@@ -441,29 +449,38 @@ export class FileService implements files.IFileService {
}); });
} }
// 2.) read contents
return new TPromise<files.IContent>((c, e) => {
let done = false;
let chunks: NodeBuffer[] = [];
let fileEncoding = this.getEncoding(model.resource, enc); let fileEncoding = this.getEncoding(model.resource, enc);
const reader = fs.createReadStream(absolutePath).pipe(encoding.decodeStream(fileEncoding)); // decode takes care of stripping any BOMs from the file content const reader = fs.createReadStream(absolutePath).pipe(encoding.decodeStream(fileEncoding)); // decode takes care of stripping any BOMs from the file content
reader.on('data', (buf) => { let content: files.IStreamContent = <any>model;
content.value = reader;
content.encoding = fileEncoding; // make sure to store the encoding in the model to restore it later when writing
return TPromise.as(content);
});
}
private resolveFileContent(resource: uri, etag?: string, enc?: string): TPromise<files.IContent> {
return this.resolveFileStreamContent(resource, etag, enc).then((streamContent) => {
// 2.) read contents
return new TPromise<files.IContent>((c, e) => {
let done = false;
let chunks: string[] = [];
streamContent.value.on('data', (buf) => {
chunks.push(buf); chunks.push(buf);
}); });
reader.on('error', (error) => { streamContent.value.on('error', (error) => {
if (!done) { if (!done) {
done = true; done = true;
e(error); e(error);
} }
}); });
reader.on('end', () => { streamContent.value.on('end', () => {
let content: files.IContent = <any>model; let content: files.IContent = <any>streamContent;
content.value = chunks.join(''); content.value = chunks.join('');
content.encoding = fileEncoding; // make sure to store the encoding in the model to restore it later when writing
if (!done) { if (!done) {
done = true; done = true;
......
...@@ -28,8 +28,7 @@ import {StringEditorModel} from 'vs/workbench/common/editor/stringEditorModel'; ...@@ -28,8 +28,7 @@ import {StringEditorModel} from 'vs/workbench/common/editor/stringEditorModel';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput'; import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel'; import {TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel';
import {ITextFileService} from 'vs/workbench/parts/files/common/files'; import {ITextFileService} from 'vs/workbench/parts/files/common/files';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices'; import {TestTextFileService, TestEventService, TestPartService, TestStorageService, TestConfigurationService, TestRequestService, TestContextService, TestWorkspace, TestEditorService, MockRequestService} from 'vs/workbench/test/common/servicesTestUtils';
import {TestEventService, TestPartService, TestStorageService, TestConfigurationService, TestRequestService, TestContextService, TestWorkspace, TestEditorService, MockRequestService} from 'vs/workbench/test/common/servicesTestUtils';
import {Viewlet} from 'vs/workbench/browser/viewlet'; import {Viewlet} from 'vs/workbench/browser/viewlet';
import {EventType} from 'vs/workbench/common/events'; import {EventType} from 'vs/workbench/common/events';
import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry';
...@@ -218,6 +217,27 @@ suite('Workbench UI Services', () => { ...@@ -218,6 +217,27 @@ suite('Workbench UI Services', () => {
}); });
}, },
resolveStreamContent: function (resource) {
return TPromise.as({
resource: resource,
value: {
on: (event:string, callback:Function): void => {
if (event === 'data') {
callback('Hello Html');
}
if (event === 'end') {
callback();
}
}
},
etag: 'index.txt',
mime: 'text/plain',
encoding: 'utf8',
mtime: new Date().getTime(),
name: paths.basename(resource.fsPath)
});
},
updateContent: function (res) { updateContent: function (res) {
return TPromise.timeout(1).then(() => { return TPromise.timeout(1).then(() => {
return { return {
...@@ -267,7 +287,7 @@ suite('Workbench UI Services', () => { ...@@ -267,7 +287,7 @@ suite('Workbench UI Services', () => {
services.set(ILifecycleService, NullLifecycleService); services.set(ILifecycleService, NullLifecycleService);
services.set(IFileService, <any> TestFileService); services.set(IFileService, <any> TestFileService);
services.set(ITextFileService, <ITextFileService>inst.createInstance(<any>TextFileService)); services.set(ITextFileService, <ITextFileService>inst.createInstance(<any>TestTextFileService));
services['instantiationService'] = inst; services['instantiationService'] = inst;
let activeInput: EditorInput = inst.createInstance(FileEditorInput, toResource('/something.js'), 'text/javascript', void 0); let activeInput: EditorInput = inst.createInstance(FileEditorInput, toResource('/something.js'), 'text/javascript', void 0);
...@@ -349,7 +369,7 @@ suite('Workbench UI Services', () => { ...@@ -349,7 +369,7 @@ suite('Workbench UI Services', () => {
services.set(PartService.IPartService, new TestPartService()); services.set(PartService.IPartService, new TestPartService());
services.set(ILifecycleService, NullLifecycleService); services.set(ILifecycleService, NullLifecycleService);
services.set(IConfigurationService, new TestConfigurationService()); services.set(IConfigurationService, new TestConfigurationService());
services.set(ITextFileService, <ITextFileService> inst.createInstance(<any>TextFileService)); services.set(ITextFileService, <ITextFileService> inst.createInstance(<any>TestTextFileService));
let activeInput: EditorInput = inst.createInstance(FileEditorInput, toResource('/something.js'), 'text/javascript', void 0); let activeInput: EditorInput = inst.createInstance(FileEditorInput, toResource('/something.js'), 'text/javascript', void 0);
let testEditorPart = new TestEditorPart(); let testEditorPart = new TestEditorPart();
......
...@@ -9,7 +9,7 @@ import {Promise, TPromise} from 'vs/base/common/winjs.base'; ...@@ -9,7 +9,7 @@ import {Promise, TPromise} from 'vs/base/common/winjs.base';
import EventEmitter = require('vs/base/common/eventEmitter'); import EventEmitter = require('vs/base/common/eventEmitter');
import Paths = require('vs/base/common/paths'); import Paths = require('vs/base/common/paths');
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import {NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {NullTelemetryService, ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import Storage = require('vs/workbench/common/storage'); import Storage = require('vs/workbench/common/storage');
import {EditorInputEvent} from 'vs/workbench/common/editor'; import {EditorInputEvent} from 'vs/workbench/common/editor';
import Event, {Emitter} from 'vs/base/common/event'; import Event, {Emitter} from 'vs/base/common/event';
...@@ -34,6 +34,11 @@ import {EditorStacksModel} from 'vs/workbench/common/editor/editorStacksModel'; ...@@ -34,6 +34,11 @@ import {EditorStacksModel} from 'vs/workbench/common/editor/editorStacksModel';
import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection'; import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection';
import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {IEditorGroupService, GroupArrangement} from 'vs/workbench/services/group/common/groupService'; import {IEditorGroupService, GroupArrangement} from 'vs/workbench/services/group/common/groupService';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {ModelBuilder, ModelBuilderResult} from 'vs/editor/node/model/modelBuilder';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IStringStream, IFileService} from 'vs/platform/files/common/files';
import {IModelService} from 'vs/editor/common/services/modelService';
export const TestWorkspace: IWorkspace = { export const TestWorkspace: IWorkspace = {
resource: URI.file('C:\\testWorkspace'), resource: URI.file('C:\\testWorkspace'),
...@@ -125,6 +130,28 @@ export class TestContextService implements WorkspaceContextService.IWorkspaceCon ...@@ -125,6 +130,28 @@ export class TestContextService implements WorkspaceContextService.IWorkspaceCon
} }
} }
export abstract class TestTextFileService extends TextFileService {
constructor(
@WorkspaceContextService.IWorkspaceContextService contextService: WorkspaceContextService.IWorkspaceContextService,
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@ITelemetryService telemetryService: ITelemetryService,
@WorkbenchEditorService.IWorkbenchEditorService editorService: WorkbenchEditorService.IWorkbenchEditorService,
@IEditorGroupService editorGroupService: IEditorGroupService,
@IEventService eventService: IEventService,
@IFileService fileService: IFileService,
@IModelService private modelService: IModelService
) {
super(contextService, instantiationService, configurationService, telemetryService, editorService, editorGroupService, eventService, fileService);
}
protected stringStreamToRawText(stream:IStringStream): TPromise<ModelBuilderResult> {
return ModelBuilder.fromStringStream(stream, this.modelService.getCreationOptions());
}
}
export class TestMessageService implements IMessageService { export class TestMessageService implements IMessageService {
public serviceId = IMessageService; public serviceId = IMessageService;
...@@ -528,6 +555,27 @@ export const TestFileService = { ...@@ -528,6 +555,27 @@ export const TestFileService = {
}); });
}, },
resolveStreamContent: function (resource) {
return TPromise.as({
resource: resource,
value: {
on: (event:string, callback:Function): void => {
if (event === 'data') {
callback('Hello Html');
}
if (event === 'end') {
callback();
}
}
},
etag: 'index.txt',
mime: 'text/plain',
encoding: 'utf8',
mtime: new Date().getTime(),
name: Paths.basename(resource.fsPath)
});
},
updateContent: function (res) { updateContent: function (res) {
return TPromise.timeout(1).then(() => { return TPromise.timeout(1).then(() => {
return { return {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册