diff --git a/src/vs/editor/browser/standalone/simpleServices.ts b/src/vs/editor/browser/standalone/simpleServices.ts index 523e2604b94bf3409d9949c9d32fd46a848969a3..d2023e1274381d0f4be4cfdf40cc4325f0046509 100644 --- a/src/vs/editor/browser/standalone/simpleServices.ts +++ b/src/vs/editor/browser/standalone/simpleServices.ts @@ -6,6 +6,7 @@ import { Schemas } from 'vs/base/common/network'; import Severity from 'vs/base/common/severity'; +import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, getConfigurationValue, IConfigurationKeys } from 'vs/platform/configuration/common/configuration'; import { IEditor, IEditorInput, IEditorOptions, IEditorService, IResourceInput, ITextEditorModel, Position } from 'vs/platform/editor/common/editor'; @@ -25,6 +26,8 @@ import { getDefaultValues as getDefaultConfiguration } from 'vs/platform/configu import { CommandService } from 'vs/platform/commands/common/commandService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress'; +import { ITextModelResolverService, IResolveOptions, ITextModelContentProvider } from 'vs/platform/textmodelResolver/common/textModelResolverService'; +import { IDisposable } from 'vs/base/common/lifecycle'; export class SimpleEditor implements IEditor { @@ -176,6 +179,46 @@ export class SimpleEditorService implements IEditorService { } } +export class SimpleEditorModelResolverService implements ITextModelResolverService { + public _serviceBrand: any; + + private editor: SimpleEditor; + + public setEditor(editor: editorCommon.IEditor): void { + this.editor = new SimpleEditor(editor); + } + + public resolve(resource: URI, options?: IResolveOptions): TPromise { + let model: editorCommon.IModel; + + model = this.editor.withTypedEditor( + (editor) => this.findModel(editor, resource), + (diffEditor) => this.findModel(diffEditor.getOriginalEditor(), resource) || this.findModel(diffEditor.getModifiedEditor(), resource) + ); + + if (!model) { + return TPromise.as(null); + } + + return TPromise.as(new SimpleModel(model)); + } + + public registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable { + return { + dispose: function () { /* no op */ } + }; + } + + private findModel(editor: editorCommon.ICommonCodeEditor, resource: URI): editorCommon.IModel { + let model = editor.getModel(); + if (model.uri.toString() !== resource.toString()) { + return null; + } + + return model; + } +} + export class SimpleProgressService implements IProgressService { _serviceBrand: any; diff --git a/src/vs/editor/browser/standalone/standaloneEditor.ts b/src/vs/editor/browser/standalone/standaloneEditor.ts index 4ee7a7879e867fdd8a55f2bcd0e925e575da58b7..e0149773923f86b29c2f282b14aedc6ab2805bbe 100644 --- a/src/vs/editor/browser/standalone/standaloneEditor.ts +++ b/src/vs/editor/browser/standalone/standaloneEditor.ts @@ -17,7 +17,7 @@ import { OpenerService } from 'vs/platform/opener/browser/openerService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IModel } from 'vs/editor/common/editorCommon'; import { Colorizer, IColorizerElementOptions, IColorizerOptions } from 'vs/editor/browser/standalone/colorizer'; -import { SimpleEditorService } from 'vs/editor/browser/standalone/simpleServices'; +import { SimpleEditorService, SimpleEditorModelResolverService } from 'vs/editor/browser/standalone/simpleServices'; import * as modes from 'vs/editor/common/modes'; import { IWebWorkerOptions, MonacoWebWorker, createWebWorker as actualCreateWebWorker } from 'vs/editor/common/services/webWorker'; import { IMarkerData } from 'vs/platform/markers/common/markers'; @@ -30,6 +30,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService'; import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; /** * @internal @@ -48,6 +49,12 @@ function withAllStandaloneServices(domElement: H services.set(IEditorService, simpleEditorService); } + let simpleEditorModelResolverService: SimpleEditorModelResolverService = null; + if (!services.has(ITextModelResolverService)) { + simpleEditorModelResolverService = new SimpleEditorModelResolverService(); + services.set(ITextModelResolverService, simpleEditorModelResolverService); + } + if (!services.has(IOpenerService)) { services.set(IOpenerService, new OpenerService(services.get(IEditorService), services.get(ICommandService))); } @@ -58,6 +65,10 @@ function withAllStandaloneServices(domElement: H simpleEditorService.setEditor(result); } + if (simpleEditorModelResolverService) { + simpleEditorModelResolverService.setEditor(result); + } + return result; } diff --git a/src/vs/platform/textmodelResolver/common/textModelResolverService.ts b/src/vs/platform/textmodelResolver/common/textModelResolverService.ts new file mode 100644 index 0000000000000000000000000000000000000000..55cc39f36cb55f58813c9f6ec9d0df8307caf52e --- /dev/null +++ b/src/vs/platform/textmodelResolver/common/textModelResolverService.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { TPromise } from 'vs/base/common/winjs.base'; +import URI from 'vs/base/common/uri'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IModel } from 'vs/editor/common/editorCommon'; +import { ITextEditorModel } from 'vs/platform/editor/common/editor'; +import { IDisposable } from 'vs/base/common/lifecycle'; + +export const ITextModelResolverService = createDecorator('textModelResolverService'); + +export interface IResolveOptions { + encoding?: string; +} + +export interface ITextModelResolverService { + _serviceBrand: any; + + resolve(resource: URI, options?: IResolveOptions): TPromise; + + registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable; +} + +export interface ITextModelContentProvider { + + provideTextContent(resource: URI): TPromise; +} \ No newline at end of file diff --git a/src/vs/test/utils/servicesTestUtils.ts b/src/vs/test/utils/servicesTestUtils.ts index 0323318f15ab2423865e71202306f8b4bb8f2c29..e5a59182b726666c87ae771036481c7b409df205 100644 --- a/src/vs/test/utils/servicesTestUtils.ts +++ b/src/vs/test/utils/servicesTestUtils.ts @@ -22,7 +22,8 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IQuickOpenService } from 'vs/workbench/services/quickopen/common/quickOpenService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { ITextModelResolverService, TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; import { IEditorInput, IEditorOptions, IEditorModel, Position, Direction, IEditor, IResourceInput, ITextEditorModel } from 'vs/platform/editor/common/editor'; import { IEventService } from 'vs/platform/event/common/event'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; diff --git a/src/vs/workbench/api/node/mainThreadDocuments.ts b/src/vs/workbench/api/node/mainThreadDocuments.ts index f245aedc6ce871f8894e4c2d7ab60cf2cdb4d3c3..38f3a1eae8a591bd3ed603061887f152d7419489 100644 --- a/src/vs/workbench/api/node/mainThreadDocuments.ts +++ b/src/vs/workbench/api/node/mainThreadDocuments.ts @@ -20,7 +20,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { ExtHostContext, MainThreadDocumentsShape, ExtHostDocumentsShape } from './extHost.protocol'; -import { ITextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; export class MainThreadDocuments extends MainThreadDocumentsShape { private _modelService: IModelService; diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index e6953eea5a0f4d4952334c80b3d208715e687b54..2a45200232c401d85b895a6f11dd6652cf7e8e8d 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -205,7 +205,7 @@ export abstract class EditorInput implements IEditorInput { * if the EditorModel should be refreshed before returning it. Depending on the implementation * this could mean to refresh the editor model contents with the version from disk. */ - public abstract resolve(refresh?: boolean): TPromise; + public abstract resolve(refresh?: boolean): TPromise; /** * An editor that is dirty will be asked to be saved once it closes. diff --git a/src/vs/workbench/common/editor/resourceEditorInput.ts b/src/vs/workbench/common/editor/resourceEditorInput.ts index ecd1834d6f7ed24c754e3d5668680844285d318f..578cb5dcf2710effac7eb62d4b0ea871e885050a 100644 --- a/src/vs/workbench/common/editor/resourceEditorInput.ts +++ b/src/vs/workbench/common/editor/resourceEditorInput.ts @@ -5,10 +5,10 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { EditorModel, EditorInput } from 'vs/workbench/common/editor'; -import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; +import { EditorInput, ITextEditorModel } from 'vs/workbench/common/editor'; import URI from 'vs/base/common/uri'; -import { ITextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; +import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; /** * A read-only text editor input whos contents are made of the provided resource that points to an existing @@ -63,15 +63,19 @@ export class ResourceEditorInput extends EditorInput { } } - public resolve(refresh?: boolean): TPromise { + public resolve(refresh?: boolean): TPromise { // Use Cached Model if (this.cachedModel) { - return TPromise.as(this.cachedModel); + return TPromise.as(this.cachedModel); } // Otherwise Create Model and handle dispose event - return this.textModelResolverService.resolve(this.resource).then((model: ResourceEditorModel) => { + return this.textModelResolverService.resolve(this.resource).then(model => { + if (!(model instanceof ResourceEditorModel)) { + return TPromise.wrapError(`Unexpected model for ResourceInput: ${this.resource}`); // TODO@Ben eventually also files should be supported, but we guard due to the dangerous dispose of the model in dispose() + } + this.cachedModel = model; const unbind = model.onDispose(() => { diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 1e468fdf986b9ba4c8d25d78b24ff1984ae405ef..379c7d1e7c0aa2d8453123961fd9d4b3cfe16631 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -67,7 +67,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { TextFileService } from 'vs/workbench/services/textfile/electron-browser/textFileService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { ITextModelResolverService, TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IMessageService } from 'vs/platform/message/common/message'; diff --git a/src/vs/workbench/parts/contentprovider/common/contentprovider.contribution.ts b/src/vs/workbench/parts/contentprovider/common/contentprovider.contribution.ts index 98c85648557141fb7eb2e522e7e45d3ee703e6ff..77e6a7ecd0eae5593b01514194b6e37c8ec32ee0 100644 --- a/src/vs/workbench/parts/contentprovider/common/contentprovider.contribution.ts +++ b/src/vs/workbench/parts/contentprovider/common/contentprovider.contribution.ts @@ -13,7 +13,7 @@ import JSONContributionRegistry = require('vs/platform/jsonschemas/common/jsonCo import { Registry } from 'vs/platform/platform'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { ITextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; let schemaRegistry = Registry.as(JSONContributionRegistry.Extensions.JSONContribution); diff --git a/src/vs/workbench/parts/files/browser/saveErrorHandler.ts b/src/vs/workbench/parts/files/browser/saveErrorHandler.ts index a518417f6a265b0735e6e244af0f9df4db3d9cc0..44f9079cfd1aeb6c38bdfd10965d1a04d35e141f 100644 --- a/src/vs/workbench/parts/files/browser/saveErrorHandler.ts +++ b/src/vs/workbench/parts/files/browser/saveErrorHandler.ts @@ -12,7 +12,7 @@ import paths = require('vs/base/common/paths'); import { Action } from 'vs/base/common/actions'; import URI from 'vs/base/common/uri'; import product from 'vs/platform/product'; -import { EditorModel } from 'vs/workbench/common/editor'; +import { ITextEditorModel } from 'vs/workbench/common/editor'; import { EditorInputAction } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -29,7 +29,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; -import { ITextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; // A handler for save error happening with conflict resolution actions export class SaveErrorHandler implements ISaveErrorHandler, IWorkbenchContribution { @@ -198,7 +198,7 @@ export class FileOnDiskEditorInput extends ResourceEditorInput { return this.lastModified; } - public resolve(refresh?: boolean): TPromise { + public resolve(refresh?: boolean): TPromise { // Make sure our file from disk is resolved up to date return this.textFileService.resolveTextContent(this.fileResource).then(content => { diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index d37d5888d5927bb060e6181f9320e89f43a119dc..b825af0fc2194a895c1fb40a098aff1af1ed75dd 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -6,28 +6,16 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; -import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IModel } from 'vs/editor/common/editorCommon'; import { ITextEditorModel } from 'vs/platform/editor/common/editor'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IModelService } from 'vs/editor/common/services/modelService'; import { sequence } from 'vs/base/common/async'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; - -export const ITextModelResolverService = createDecorator('textModelResolverService'); - -export interface ITextModelResolverService { - _serviceBrand: any; - - resolve(resource: URI): TPromise; - - registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable; -} - -export interface ITextModelContentProvider { - - provideTextContent(resource: URI): TPromise; -} +import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import network = require('vs/base/common/network'); +import { ITextModelResolverService, ITextModelContentProvider, IResolveOptions } from 'vs/platform/textmodelResolver/common/textModelResolverService'; export class TextModelResolverService implements ITextModelResolverService { @@ -37,12 +25,20 @@ export class TextModelResolverService implements ITextModelResolverService { private contentProviderRegistry: { [scheme: string]: ITextModelContentProvider[] } = Object.create(null); constructor( + @ITextFileService private textFileService: ITextFileService, @IInstantiationService private instantiationService: IInstantiationService, @IModelService private modelService: IModelService ) { } - public resolve(resource: URI): TPromise { + public resolve(resource: URI, options?: IResolveOptions): TPromise { + + // File Schema: use text file service + if (resource.scheme === network.Schemas.file) { + return this.textFileService.models.loadOrCreate(resource, options && options.encoding, false /* refresh */); + } + + // Any other resource: use registry return this.resolveTextModelContent(this.modelService, resource).then(() => this.instantiationService.createInstance(ResourceEditorModel, resource)); } diff --git a/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts b/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts index 330e837bb206468df7db317aa024df2907033d80..c52823d53dcfb1cfcc01736cb51103aa8a01e74c 100644 --- a/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts +++ b/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts @@ -13,7 +13,7 @@ import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorIn import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { workbenchInstantiationService } from 'vs/test/utils/servicesTestUtils'; -import { ITextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; +import { ITextModelResolverService } from 'vs/platform/textmodelResolver/common/textModelResolverService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService';