mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-26 03:29:00 +01:00
introduce the concept fo ContentProvider to the ResourceEditorInput
Instead of just letting the API layer know about content provider we must push it lower because only than we can handle uri's opaque.
This commit is contained in:
@@ -7,10 +7,21 @@
|
||||
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 {IModel} from 'vs/editor/common/editorCommon';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {EventType} from 'vs/base/common/events';
|
||||
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {IModelService} from 'vs/editor/common/services/modelService';
|
||||
import {IModeService} from 'vs/editor/common/services/modeService';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export interface IResourceEditorContentProvider {
|
||||
provideTextContent(resource: URI): TPromise<string>;
|
||||
// onDidChange
|
||||
}
|
||||
|
||||
/**
|
||||
* A read-only text editor input whos contents are made of the provided resource that points to an existing
|
||||
@@ -18,6 +29,57 @@ import {IModelService} from 'vs/editor/common/services/modelService';
|
||||
*/
|
||||
export class ResourceEditorInput extends EditorInput {
|
||||
|
||||
// --- registry logic
|
||||
// todo@joh,ben this should maybe be a service that is in charge of loading/resolving a uri from a scheme
|
||||
|
||||
private static loadingModels: { [uri: string]: TPromise<IModel> } = Object.create(null);
|
||||
private static registry: { [scheme: string]: IResourceEditorContentProvider } = Object.create(null);
|
||||
|
||||
public static registerResourceContentProvider(scheme: string, provider: IResourceEditorContentProvider): IDisposable {
|
||||
ResourceEditorInput.registry[scheme] = provider;
|
||||
return { dispose() { delete ResourceEditorInput.registry[scheme] } };
|
||||
}
|
||||
|
||||
private static getOrCreateModel(modelService: IModelService, modeService: IModeService, resource: URI): TPromise<IModel> {
|
||||
const model = modelService.getModel(resource);
|
||||
if (model) {
|
||||
return TPromise.as(model);
|
||||
}
|
||||
|
||||
let loadingModel = ResourceEditorInput.loadingModels[resource.toString()];
|
||||
if (!loadingModel) {
|
||||
|
||||
// make sure we have a provider this scheme
|
||||
// the resource uses
|
||||
const provider = ResourceEditorInput.registry[resource.scheme];
|
||||
if (!provider) {
|
||||
return TPromise.wrapError(`No model with uri '${resource}' nor a resolver for the scheme '${resource.scheme}'.`);
|
||||
}
|
||||
|
||||
// load the model-content from the provider and cache
|
||||
// the loading such that we don't create the same model
|
||||
// twice
|
||||
ResourceEditorInput.loadingModels[resource.toString()] = loadingModel = new TPromise<IModel>((resolve, reject) => {
|
||||
|
||||
provider.provideTextContent(resource).then(value => {
|
||||
const firstLineText = value.substr(0, 1 + value.search(/\r?\n/));
|
||||
const mode = modeService.getOrCreateModeByFilenameOrFirstLine(resource.fsPath, firstLineText);
|
||||
return modelService.createModel(value, mode, resource);
|
||||
}).then(resolve, reject);
|
||||
|
||||
}, function() {
|
||||
// no cancellation when caching promises
|
||||
});
|
||||
|
||||
// remove the cached promise 'cos the model is now
|
||||
// known to the model service (see above)
|
||||
loadingModel.then(() => delete ResourceEditorInput.loadingModels[resource.toString()], () => delete ResourceEditorInput.loadingModels[resource.toString()]);
|
||||
}
|
||||
|
||||
return loadingModel;
|
||||
}
|
||||
|
||||
|
||||
public static ID: string = 'workbench.editors.resourceEditorInput';
|
||||
|
||||
protected cachedModel: ResourceEditorModel;
|
||||
@@ -31,6 +93,7 @@ export class ResourceEditorInput extends EditorInput {
|
||||
description: string,
|
||||
resource: URI,
|
||||
@IModelService protected modelService: IModelService,
|
||||
@IModeService protected modeService: IModeService,
|
||||
@IInstantiationService protected instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
@@ -60,18 +123,20 @@ export class ResourceEditorInput extends EditorInput {
|
||||
}
|
||||
|
||||
// Otherwise Create Model and handle dispose event
|
||||
let model = this.instantiationService.createInstance(ResourceEditorModel, this.resource);
|
||||
const unbind = model.addListener(EventType.DISPOSE, () => {
|
||||
this.cachedModel = null; // make sure we do not dispose model again
|
||||
unbind();
|
||||
this.dispose();
|
||||
});
|
||||
return ResourceEditorInput.getOrCreateModel(this.modelService, this.modeService, this.resource).then(() => {
|
||||
let model = this.instantiationService.createInstance(ResourceEditorModel, this.resource);
|
||||
const unbind = model.addListener(EventType.DISPOSE, () => {
|
||||
this.cachedModel = null; // make sure we do not dispose model again
|
||||
unbind();
|
||||
this.dispose();
|
||||
});
|
||||
|
||||
// Load it
|
||||
return model.load().then((resolvedModel: ResourceEditorModel) => {
|
||||
this.cachedModel = resolvedModel;
|
||||
// Load it
|
||||
return model.load().then((resolvedModel: ResourceEditorModel) => {
|
||||
this.cachedModel = resolvedModel;
|
||||
|
||||
return this.cachedModel;
|
||||
return this.cachedModel;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user