提交 620e8b7f 编写于 作者: J Johannes Rieken

Merge pull request #5443 from Microsoft/joh/inst

InstantiationService debt
...@@ -13,6 +13,7 @@ import * as objects from 'vs/base/common/objects'; ...@@ -13,6 +13,7 @@ import * as objects from 'vs/base/common/objects';
import * as timer from 'vs/base/common/timer'; import * as timer from 'vs/base/common/timer';
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {IKeybindingContextKey, IKeybindingScopeLocation, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IKeybindingContextKey, IKeybindingScopeLocation, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {CommonEditorConfiguration} from 'vs/editor/common/config/commonEditorConfig'; import {CommonEditorConfiguration} from 'vs/editor/common/config/commonEditorConfig';
...@@ -114,9 +115,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr ...@@ -114,9 +115,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr
this.forcedWidgetFocusCount = 0; this.forcedWidgetFocusCount = 0;
this._telemetryService = telemetryService; this._telemetryService = telemetryService;
this._instantiationService = instantiationService.createChild({ this._instantiationService = instantiationService.createChild(new ServiceCollection([IKeybindingService, this._keybindingService]));
keybindingService: this._keybindingService
});
this._attachModel(null); this._attachModel(null);
......
...@@ -12,18 +12,27 @@ import Severity from 'vs/base/common/severity'; ...@@ -12,18 +12,27 @@ import Severity from 'vs/base/common/severity';
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import {WorkerServer} from 'vs/base/common/worker/workerServer'; import {WorkerServer} from 'vs/base/common/worker/workerServer';
import {EventService} from 'vs/platform/event/common/eventService'; import {EventService} from 'vs/platform/event/common/eventService';
import {IEventService} from 'vs/platform/event/common/event';
import {AbstractExtensionService, ActivatedExtension} from 'vs/platform/extensions/common/abstractExtensionService'; import {AbstractExtensionService, ActivatedExtension} from 'vs/platform/extensions/common/abstractExtensionService';
import {IExtensionDescription} from 'vs/platform/extensions/common/extensions'; import {IExtensionDescription, IExtensionService} from 'vs/platform/extensions/common/extensions';
import {createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {SecondaryMarkerService} from 'vs/platform/markers/common/markerService'; import {SecondaryMarkerService} from 'vs/platform/markers/common/markerService';
import {IMarkerService} from 'vs/platform/markers/common/markers';
import {BaseRequestService} from 'vs/platform/request/common/baseRequestService'; import {BaseRequestService} from 'vs/platform/request/common/baseRequestService';
import {IRequestService} from 'vs/platform/request/common/request';
import {RemoteTelemetryService} from 'vs/platform/telemetry/common/remoteTelemetryService'; import {RemoteTelemetryService} from 'vs/platform/telemetry/common/remoteTelemetryService';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {WorkerThreadService} from 'vs/platform/thread/common/workerThreadService'; import {WorkerThreadService} from 'vs/platform/thread/common/workerThreadService';
import {IThreadService} from 'vs/platform/thread/common/thread';
import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService'; import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService';
import {IWorkspace} from 'vs/platform/workspace/common/workspace'; import {IWorkspaceContextService, IWorkspace} from 'vs/platform/workspace/common/workspace';
import {ModeServiceImpl, ModeServiceWorkerHelper} from 'vs/editor/common/services/modeServiceImpl'; import {ModeServiceImpl, ModeServiceWorkerHelper} from 'vs/editor/common/services/modeServiceImpl';
import {IModeService} from 'vs/editor/common/services/modeService';
import {ModelServiceWorkerHelper} from 'vs/editor/common/services/modelServiceImpl'; import {ModelServiceWorkerHelper} from 'vs/editor/common/services/modelServiceImpl';
import {ResourceService} from 'vs/editor/common/services/resourceServiceImpl'; import {ResourceService} from 'vs/editor/common/services/resourceServiceImpl';
import {IResourceService} from 'vs/editor/common/services/resourceService';
export interface IInitData { export interface IInitData {
contextService: { contextService: {
...@@ -86,35 +95,29 @@ export class EditorWorkerServer { ...@@ -86,35 +95,29 @@ export class EditorWorkerServer {
public initialize(mainThread:WorkerServer, complete:ICallback, error:ICallback, progress:ICallback, initData:IInitData):void { public initialize(mainThread:WorkerServer, complete:ICallback, error:ICallback, progress:ICallback, initData:IInitData):void {
var extensionService = new WorkerExtensionService(); const services = new ServiceCollection();
var contextService = new BaseWorkspaceContextService(initData.contextService.workspace, initData.contextService.configuration, initData.contextService.options);
const extensionService = new WorkerExtensionService();
const contextService = new BaseWorkspaceContextService(initData.contextService.workspace, initData.contextService.configuration, initData.contextService.options);
this.threadService = new WorkerThreadService(mainThread.getRemoteCom()); this.threadService = new WorkerThreadService(mainThread.getRemoteCom());
this.threadService.setInstantiationService(createInstantiationService({ threadService: this.threadService })); this.threadService.setInstantiationService(new InstantiationService(new ServiceCollection([IThreadService, this.threadService])));
const telemetryServiceInstance = new RemoteTelemetryService('workerTelemetry', this.threadService);
var telemetryServiceInstance = new RemoteTelemetryService('workerTelemetry', this.threadService); const resourceService = new ResourceService();
const markerService = new SecondaryMarkerService(this.threadService);
var resourceService = new ResourceService(); const modeService = new ModeServiceImpl(this.threadService, extensionService);
var markerService = new SecondaryMarkerService(this.threadService); const requestService = new BaseRequestService(contextService, telemetryServiceInstance);
var modeService = new ModeServiceImpl(this.threadService, extensionService); services.set(IExtensionService, extensionService);
services.set(IThreadService, this.threadService);
var requestService = new BaseRequestService(contextService, telemetryServiceInstance); services.set(IModeService, modeService);
services.set(IWorkspaceContextService, contextService);
var _services : any = { services.set(IEventService, new EventService());
threadService: this.threadService, services.set(IResourceService, resourceService);
extensionService: extensionService, services.set(IMarkerService, markerService);
modeService: modeService, services.set(ITelemetryService, telemetryServiceInstance);
contextService: contextService, services.set(IRequestService, requestService);
eventService: new EventService(),
resourceService: resourceService, const instantiationService = new InstantiationService(services);
markerService: markerService,
telemetryService: telemetryServiceInstance,
requestService: requestService
};
var instantiationService = createInstantiationService(_services);
this.threadService.setInstantiationService(instantiationService); this.threadService.setInstantiationService(instantiationService);
// Instantiate thread actors // Instantiate thread actors
......
...@@ -26,6 +26,7 @@ import {DefaultController, LegacyRenderer} from 'vs/base/parts/tree/browser/tree ...@@ -26,6 +26,7 @@ import {DefaultController, LegacyRenderer} from 'vs/base/parts/tree/browser/tree
import {Tree} from 'vs/base/parts/tree/browser/treeImpl'; import {Tree} from 'vs/base/parts/tree/browser/treeImpl';
import {IEditorService} from 'vs/platform/editor/common/editor'; import {IEditorService} from 'vs/platform/editor/common/editor';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {DefaultConfig} from 'vs/editor/common/config/defaultConfig'; import {DefaultConfig} from 'vs/editor/common/config/defaultConfig';
...@@ -34,7 +35,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; ...@@ -34,7 +35,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import {Model} from 'vs/editor/common/model/model'; import {Model} from 'vs/editor/common/model/model';
import {ICodeEditor, IMouseTarget} from 'vs/editor/browser/editorBrowser'; import {ICodeEditor, IMouseTarget} from 'vs/editor/browser/editorBrowser';
import {EmbeddedCodeEditorWidget} from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; import {EmbeddedCodeEditorWidget} from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
import {PeekViewWidget} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; import {PeekViewWidget, IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget';
import {EventType, FileReferences, OneReference, ReferencesModel} from './referenceSearchModel'; import {EventType, FileReferences, OneReference, ReferencesModel} from './referenceSearchModel';
class DecorationsManager implements IDisposable { class DecorationsManager implements IDisposable {
...@@ -398,7 +399,7 @@ export class ReferenceWidget extends PeekViewWidget { ...@@ -398,7 +399,7 @@ export class ReferenceWidget extends PeekViewWidget {
super(editor, keybindingService, ReferenceWidget.INNER_EDITOR_CONTEXT_KEY, { frameColor: '#007ACC', showFrame: false, showArrow: true }); super(editor, keybindingService, ReferenceWidget.INNER_EDITOR_CONTEXT_KEY, { frameColor: '#007ACC', showFrame: false, showArrow: true });
this.editorService = editorService; this.editorService = editorService;
this.contextService = contextService; this.contextService = contextService;
this.instantiationService = instantiationService.createChild({ peekViewService: this }); this.instantiationService = instantiationService.createChild(new ServiceCollection([IPeekViewService, this]));
this.callOnModel = []; this.callOnModel = [];
......
...@@ -5,27 +5,22 @@ ...@@ -5,27 +5,22 @@
'use strict'; 'use strict';
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import ServiceCollection from './serviceCollection';
import * as descriptors from './descriptors'; import * as descriptors from './descriptors';
// ----------------------- internal util ----------------------- // ------ internal util
export namespace _util { export namespace _util {
export const DI_TARGET = '$di$target'; export const DI_TARGET = '$di$target';
export const DI_DEPENDENCIES = '$di$dependencies'; export const DI_DEPENDENCIES = '$di$dependencies';
export const DI_PROVIDES = '$di$provides_service';
export function getServiceId(id: ServiceIdentifier<any>): string { export function getServiceDependencies(ctor: any): { id: ServiceIdentifier<any>, index: number }[] {
return id[DI_PROVIDES]; return ctor[DI_DEPENDENCIES] || [];
}
export function getServiceDependencies(ctor: any): { serviceId: string, index: number }[] {
return ctor[DI_DEPENDENCIES];
} }
} }
// ----------------------- interfaces ----------------------- // --- interfaces ------
export interface IConstructorSignature0<T> { export interface IConstructorSignature0<T> {
new (...services: { serviceId: ServiceIdentifier<any>; }[]): T; new (...services: { serviceId: ServiceIdentifier<any>; }[]): T;
...@@ -103,7 +98,6 @@ export interface IFunctionSignature8<A1, A2, A3, A4, A5, A6, A7, A8, R> { ...@@ -103,7 +98,6 @@ export interface IFunctionSignature8<A1, A2, A3, A4, A5, A6, A7, A8, R> {
(accessor: ServicesAccessor, first: A1, second: A2, third: A3, forth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8): R; (accessor: ServicesAccessor, first: A1, second: A2, third: A3, forth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8): R;
} }
export var IInstantiationService = createDecorator<IInstantiationService>('instantiationService'); export var IInstantiationService = createDecorator<IInstantiationService>('instantiationService');
export interface IInstantiationService { export interface IInstantiationService {
...@@ -175,12 +169,7 @@ export interface IInstantiationService { ...@@ -175,12 +169,7 @@ export interface IInstantiationService {
* Creates a child of this service which inherts all current services * Creates a child of this service which inherts all current services
* and adds/overwrites the given services * and adds/overwrites the given services
*/ */
createChild(services: any): IInstantiationService; createChild(services: ServiceCollection): IInstantiationService;
/**
* Registers a new service to this instantation service.
*/
registerService(name: string, service: any): void;
/** /**
* Adds a service or a descriptor to the collection of services and * Adds a service or a descriptor to the collection of services and
...@@ -204,29 +193,21 @@ export interface ServiceIdentifier<T> { ...@@ -204,29 +193,21 @@ export interface ServiceIdentifier<T> {
*/ */
export function createDecorator<T>(serviceId: string): { (...args: any[]): void; type: T; } { export function createDecorator<T>(serviceId: string): { (...args: any[]): void; type: T; } {
let ret = function(target: any, key: string, index: number): any { let id = function(target: any, key: string, index: number): any {
if (arguments.length !== 3) { if (arguments.length !== 3) {
throw new Error('@IServiceName-decorator can only be used to decorate a parameter'); throw new Error('@IServiceName-decorator can only be used to decorate a parameter');
} }
if (target[_util.DI_TARGET] === target) { if (target[_util.DI_TARGET] === target) {
target[_util.DI_DEPENDENCIES].push({ serviceId, index }); target[_util.DI_DEPENDENCIES].push({ id, index });
} else { } else {
target[_util.DI_DEPENDENCIES] = [{ serviceId, index }]; target[_util.DI_DEPENDENCIES] = [{ id, index }];
target[_util.DI_TARGET] = target; target[_util.DI_TARGET] = target;
} }
}; };
ret[_util.DI_PROVIDES] = serviceId; id.toString = () => serviceId;
// ret['type'] = undefined;
return <any>ret;
}
/** return <any>id;
* A service context which can be used to retrieve services
* given a valid service identifer is being presented
*/
export interface Context {
get<T>(id: ServiceIdentifier<T>): T;
} }
...@@ -4,181 +4,152 @@ ...@@ -4,181 +4,152 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as winjs from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import * as errors from 'vs/base/common/errors'; import {illegalArgument, illegalState, canceled} from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings'; import {create} from 'vs/base/common/types';
import * as types from 'vs/base/common/types'; import * as assert from 'vs/base/common/assert';
import * as collections from 'vs/base/common/collections'; import {forEach} from 'vs/base/common/collections';
import * as descriptors from './descriptors';
import {Graph} from 'vs/base/common/graph'; import {Graph} from 'vs/base/common/graph';
import * as instantiation from './instantiation'; import {SyncDescriptor, AsyncDescriptor} from 'vs/platform/instantiation/common/descriptors';
import {ServiceIdentifier, IInstantiationService, ServicesAccessor, _util, createDecorator} from 'vs/platform/instantiation/common/instantiation';
import IInstantiationService = instantiation.IInstantiationService; import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import ServiceIdentifier = instantiation.ServiceIdentifier;
/** /**
* Creates a new instance of an instantiation service. * Creates a new instance of an instantiation service.
*/ */
export function createInstantiationService(services: any = Object.create(null)): IInstantiationService { export function createInstantiationService(param: ServiceCollection | { [legacyId: string]: any } = new ServiceCollection()): IInstantiationService {
let result = new InstantiationService(services, new AccessLock());
return result;
}
class AccessLock {
private _value: number = 0;
public get locked() { if (param instanceof ServiceCollection) {
return this._value === 0; return new InstantiationService(param);
} }
public runUnlocked<R>(r: () => R): R { // legacy
this._value++; let services = new ServiceCollection();
try { forEach(param, entry => {
return r(); services.set(createDecorator(entry.key), entry.value);
} finally { });
this._value--; return new InstantiationService(services);
}
}
} }
class ServicesMap { export class InstantiationService implements IInstantiationService {
serviceId: any;
private _services: ServiceCollection;
constructor(services: ServiceCollection) {
this._services = services;
constructor(private _services: any, private _lock: AccessLock) { this._services.set(IInstantiationService, this);
collections.forEach(this._services, (entry) => { }
// add a accessor to myselves createChild(services: ServiceCollection): IInstantiationService {
this.registerService(entry.key, entry.value); this._services.forEach((id, thing) => {
if (!services.has(id)) {
services.set(id, thing);
}
}); });
return new InstantiationService(services);
} }
public registerService(name: string, service: any): void { addSingleton<T>(id: ServiceIdentifier<T>, instanceOrDescriptor: T | SyncDescriptor<T>): void {
// add a accessor to myselves if (this._services.has(id)) {
Object.defineProperty(this, name, { throw new Error('duplicate service');
get: () => {
if (this._lock.locked) {
throw errors.illegalState('the services map can only be used during construction');
} }
if (!service) { this._services.set(id, instanceOrDescriptor);
throw errors.illegalArgument(strings.format('service with \'{0}\' not found', name));
} }
if (service instanceof descriptors.SyncDescriptor) {
let cached = this._services[name]; getInstance<T>(id: ServiceIdentifier<T>): T {
if (cached instanceof descriptors.SyncDescriptor) { let thing = this._services.get(id);
this._ensureInstances(name, service); if (thing instanceof SyncDescriptor) {
service = this._services[name]; return this._createAndCacheServiceInstance(id, thing);
} else { } else {
service = cached; return thing;
} }
} }
return service;
},
set: (value: any) => {
throw errors.illegalState('services cannot be changed');
},
configurable: false,
enumerable: false
});
// add to services map
this._services[name] = service;
}
public get lock(): AccessLock { invokeFunction<R>(signature: (accessor: ServicesAccessor, ...more: any[]) => R, ...args: any[]): R {
return this._lock; let accessor: ServicesAccessor;
try {
accessor = {
get: <T>(id: ServiceIdentifier<T>) => {
return this.getInstance(id);
} }
};
public get services(): any { return signature.apply(undefined, [accessor].concat(args));
return this._services; } finally {
accessor.get = function () {
throw illegalState('service accessor is only valid during the invocation of its target method');
};
} }
private _ensureInstances(serviceId: string, desc: descriptors.SyncDescriptor<any>): void {
let seen: { [n: string]: boolean } = Object.create(null);
let graph = new Graph<{ serviceId: string, desc: descriptors.SyncDescriptor<any> }>(i => i.serviceId);
function throwCycleError() {
const err = new Error('[createInstance cyclic dependency between services]');
err.message = graph.toString();
throw err;
} }
let stack = [{ serviceId, desc }]; createInstance<T>(param: any, ...rest:any[]): any {
while (stack.length) {
let item = stack.pop();
graph.lookupOrInsertNode(item);
// check for cycles between the descriptors if (param instanceof AsyncDescriptor) {
if (seen[item.serviceId]) { // async
throwCycleError(); return this._createInstanceAsync(param, rest);
}
seen[item.serviceId] = true;
// check all dependencies for existence and if the need to be created first } else if (param instanceof SyncDescriptor) {
let dependencies = instantiation._util.getServiceDependencies(item.desc.ctor); // sync
if (Array.isArray(dependencies)) { return this._createInstance(param, rest);
for (let dependency of dependencies) {
let instanceOrDesc = this.services[dependency.serviceId];
if (!instanceOrDesc) {
// throw new Error(`[createInstance] ${serviceId} depends on ${dependency.serviceId} which is NOT registered.`);
console.warn(`[createInstance] ${serviceId} depends on ${dependency.serviceId} which is NOT registered.`);
}
if (instanceOrDesc instanceof descriptors.SyncDescriptor) { } else {
const d = { serviceId: dependency.serviceId, desc: instanceOrDesc }; // sync, just ctor
stack.push(d); return this._createInstance(new SyncDescriptor(param), rest);
graph.insertEdge(item, d);
}
}
} }
} }
while (true) { private _createInstanceAsync<T>(descriptor: AsyncDescriptor<T>, args: any[]): TPromise<T> {
let roots = graph.roots();
// if there is no more roots but still let canceledError: Error;
// nodes in the graph we have a cycle
if (roots.length === 0) {
if (graph.length !== 0) {
throwCycleError();
}
break;
}
for (let root of roots) { return new TPromise((c, e, p) => {
let instance = this.createInstance(root.data.desc, []); require([descriptor.moduleName], (_module?: any) => {
this._services[root.data.serviceId] = instance; if (canceledError) {
graph.removeNode(root.data); e(canceledError);
}
}
} }
public invokeFunction<R>(fn: Function, args: any[]): R { if (!_module) {
return e(illegalArgument('module not found: ' + descriptor.moduleName));
}
return this._lock.runUnlocked(() => { let ctor: Function;
if (!descriptor.ctorName) {
ctor = _module;
} else {
ctor = _module[descriptor.ctorName];
}
let accessor: instantiation.ServicesAccessor = { if (typeof ctor !== 'function') {
get: <T>(id: instantiation.ServiceIdentifier<T>) => { return e(illegalArgument('not a function: ' + descriptor.ctorName || descriptor.moduleName));
let value = instantiation._util.getServiceId(id);
return <T>this[value];
} }
};
return fn.apply(undefined, [accessor].concat(args)); try {
args.unshift.apply(args, descriptor.staticArguments()); // instead of spread in ctor call
c(this._createInstance(new SyncDescriptor<T>(ctor), args));
} catch (error) {
return e(error);
}
}, e);
}, () => {
canceledError = canceled();
}); });
} }
public createInstance<T>(descriptor: descriptors.SyncDescriptor<T>, args: any[]): T { private _createInstance<T>(desc: SyncDescriptor<T>, args: any[]): T {
let allArguments: any[] = []; let allArguments: any[] = [];
let serviceInjections = instantiation._util.getServiceDependencies(descriptor.ctor) || []; let serviceInjections = _util.getServiceDependencies(desc.ctor);
let fixedArguments = descriptor.staticArguments().concat(args); let fixedArguments = desc.staticArguments().concat(args);
let expectedFirstServiceIndex = fixedArguments.length; let expectedFirstServiceIndex = fixedArguments.length;
let actualFirstServiceIndex = Number.MAX_VALUE; let actualFirstServiceIndex = Number.MAX_VALUE;
serviceInjections.forEach(si => { serviceInjections.forEach(serviceInjection => {
// @IServiceName // @IServiceName
let {serviceId, index} = si; let {id, index} = serviceInjection;
let service = this._lock.runUnlocked(() => this[serviceId]); // let service = this._lock.runUnlocked(() => this[serviceId]);
allArguments[index] = service; allArguments[index] = this.getInstance(id);
actualFirstServiceIndex = Math.min(actualFirstServiceIndex, si.index); actualFirstServiceIndex = Math.min(actualFirstServiceIndex, index);
}); });
// insert the fixed arguments into the array of all ctor // insert the fixed arguments into the array of all ctor
...@@ -193,7 +164,7 @@ class ServicesMap { ...@@ -193,7 +164,7 @@ class ServicesMap {
i += 1; i += 1;
} }
allArguments.unshift(descriptor.ctor); // ctor is first arg allArguments.unshift(desc.ctor); // ctor is first arg
// services are the last arguments of ctor-calls. We check if static ctor arguments // services are the last arguments of ctor-calls. We check if static ctor arguments
// (like those from a [sync|async] desriptor) or args that are passed by createInstance // (like those from a [sync|async] desriptor) or args that are passed by createInstance
...@@ -201,7 +172,7 @@ class ServicesMap { ...@@ -201,7 +172,7 @@ class ServicesMap {
if (actualFirstServiceIndex !== Number.MAX_VALUE if (actualFirstServiceIndex !== Number.MAX_VALUE
&& actualFirstServiceIndex !== expectedFirstServiceIndex) { && actualFirstServiceIndex !== expectedFirstServiceIndex) {
let msg = `[createInstance] constructor '${descriptor.ctor.name}' has first` + let msg = `[createInstance] constructor '${desc.ctor.name}' has first` +
` service dependency at position ${actualFirstServiceIndex + 1} but is called with` + ` service dependency at position ${actualFirstServiceIndex + 1} but is called with` +
` ${expectedFirstServiceIndex - 1} static arguments that are expected to come first`; ` ${expectedFirstServiceIndex - 1} static arguments that are expected to come first`;
...@@ -209,148 +180,73 @@ class ServicesMap { ...@@ -209,148 +180,73 @@ class ServicesMap {
console.warn(msg); console.warn(msg);
} }
return this._lock.runUnlocked(() => { // return this._lock.runUnlocked(() => {
const instance = types.create.apply(null, allArguments); const instance = create.apply(null, allArguments);
descriptor._validate(instance); desc._validate(instance);
return <T>instance; return <T>instance;
}); // });
} }
}
class InstantiationService implements IInstantiationService { private _createAndCacheServiceInstance<T>(id: ServiceIdentifier<T>, desc: SyncDescriptor<T>): T {
public serviceId = IInstantiationService; assert.ok(this._services.get(id) instanceof SyncDescriptor);
private _servicesMap: ServicesMap; const graph = new Graph<{ id: ServiceIdentifier<any>, desc: SyncDescriptor<any> }>(data => data.id.toString());
constructor(services: any, lock: AccessLock) { function throwCycleError() {
services['instantiationService'] = this; const err = new Error('[createInstance] cyclic dependency between services');
this._servicesMap = new ServicesMap(services, lock); err.message = graph.toString();
throw err;
} }
createChild(services: any): IInstantiationService { let count = 0;
const childServices = {}; const stack = [{ id, desc }];
// copy existing services while (stack.length) {
collections.forEach(this._servicesMap.services, (entry) => { const item = stack.pop();
childServices[entry.key] = entry.value; graph.lookupOrInsertNode(item);
});
// insert new services (might overwrite)
collections.forEach(services, (entry) => {
childServices[entry.key] = entry.value;
});
return new InstantiationService(childServices, this._servicesMap.lock);
}
registerService(name: string, service: any): void { // TODO@joh use the graph to find a cycle
this._servicesMap.registerService(name, service); // a weak heuristic for cycle checks
if (count++ > 100) {
throwCycleError();
} }
addSingleton<T>(id: ServiceIdentifier<T>, instanceOrDescriptor: T | descriptors.SyncDescriptor<T>): void { // check all dependencies for existence and if the need to be created first
let name = instantiation._util.getServiceId(id); let dependencies = _util.getServiceDependencies(item.desc.ctor);
this._servicesMap.registerService(name, instanceOrDescriptor); for (let dependency of dependencies) {
let instanceOrDesc = this._services.get(dependency.id);
if (!instanceOrDesc) {
console.warn(`[createInstance] ${id} depends on ${dependency.id} which is NOT registered.`);
} }
getInstance<T>(id: ServiceIdentifier<T>): T { if (instanceOrDesc instanceof SyncDescriptor) {
let name = instantiation._util.getServiceId(id); const d = { id: dependency.id, desc: instanceOrDesc };
let result = this._servicesMap.lock.runUnlocked(() => this._servicesMap[name]); graph.insertEdge(item, d);
return result; stack.push(d);
}
createInstance<T>(ctor: instantiation.IConstructorSignature0<T>, ...rest: any[]): T;
createInstance<A1, T>(ctor: instantiation.IConstructorSignature1<A1, T>, ...rest: any[]): T;
createInstance<A1, A2, T>(ctor: instantiation.IConstructorSignature2<A1, A2, T>, ...rest: any[]): T;
createInstance<A1, A2, A3, T>(ctor: instantiation.IConstructorSignature3<A1, A2, A3, T>, ...rest: any[]): T;
createInstance<A1, A2, A3, A4, T>(ctor: instantiation.IConstructorSignature4<A1, A2, A3, A4, T>, first: A1, second: A2, third: A3, fourth: A4): T;
createInstance<A1, A2, A3, A4, A5, T>(ctor: instantiation.IConstructorSignature5<A1, A2, A3, A4, A5, T>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5): T;
createInstance<A1, A2, A3, A4, A5, A6, T>(ctor: instantiation.IConstructorSignature6<A1, A2, A3, A4, A5, A6, T>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6): T;
createInstance<A1, A2, A3, A4, A5, A6, A7, T>(ctor: instantiation.IConstructorSignature7<A1, A2, A3, A4, A5, A6, A7, T>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7): T;
createInstance<A1, A2, A3, A4, A5, A6, A7, A8, T>(ctor: instantiation.IConstructorSignature8<A1, A2, A3, A4, A5, A6, A7, A8, T>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8): T;
createInstance<T>(descriptor: descriptors.SyncDescriptor0<T>): T;
createInstance<A1, T>(descriptor: descriptors.SyncDescriptor1<A1, T>, a1: A1): T;
createInstance<A1, A2, T>(descriptor: descriptors.SyncDescriptor2<A1, A2, T>, a1: A1, a2: A2): T;
createInstance<A1, A2, A3, T>(descriptor: descriptors.SyncDescriptor3<A1, A2, A3, T>, a1: A1, a2: A2, a3: A3): T;
createInstance<A1, A2, A3, A4, T>(descriptor: descriptors.SyncDescriptor4<A1, A2, A3, A4, T>, a1: A1, a2: A2, a3: A3, a4: A4): T;
createInstance<A1, A2, A3, A4, A5, T>(descriptor: descriptors.SyncDescriptor5<A1, A2, A3, A4, A5, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): T;
createInstance<A1, A2, A3, A4, A5, A6, T>(descriptor: descriptors.SyncDescriptor6<A1, A2, A3, A4, A5, A6, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6): T;
createInstance<A1, A2, A3, A4, A5, A6, A7, T>(descriptor: descriptors.SyncDescriptor7<A1, A2, A3, A4, A5, A6, A7, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7): T;
createInstance<A1, A2, A3, A4, A5, A6, A7, A8, T>(descriptor: descriptors.SyncDescriptor8<A1, A2, A3, A4, A5, A6, A7, A8, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8): T;
createInstance<T>(descriptor: descriptors.AsyncDescriptor0<T>): winjs.TPromise<T>;
createInstance<A1, T>(descriptor: descriptors.AsyncDescriptor1<A1, T>, a1: A1): winjs.TPromise<T>;
createInstance<A1, A2, T>(descriptor: descriptors.AsyncDescriptor2<A1, A2, T>, a1: A1, a2: A2): winjs.TPromise<T>;
createInstance<A1, A2, A3, T>(descriptor: descriptors.AsyncDescriptor3<A1, A2, A3, T>, a1: A1, a2: A2, a3: A3): winjs.TPromise<T>;
createInstance<A1, A2, A3, A4, T>(descriptor: descriptors.AsyncDescriptor4<A1, A2, A3, A4, T>, a1: A1, a2: A2, a3: A3, a4: A4): winjs.TPromise<T>;
createInstance<A1, A2, A3, A4, A5, T>(descriptor: descriptors.AsyncDescriptor5<A1, A2, A3, A4, A5, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): winjs.TPromise<T>;
createInstance<A1, A2, A3, A4, A5, A6, T>(descriptor: descriptors.AsyncDescriptor6<A1, A2, A3, A4, A5, A6, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6): winjs.TPromise<T>;
createInstance<A1, A2, A3, A4, A5, A6, A7, T>(descriptor: descriptors.AsyncDescriptor7<A1, A2, A3, A4, A5, A6, A7, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7): winjs.TPromise<T>;
createInstance<A1, A2, A3, A4, A5, A6, A7, A8, T>(descriptor: descriptors.AsyncDescriptor8<A1, A2, A3, A4, A5, A6, A7, A8, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8): winjs.TPromise<T>;
createInstance<T>(descriptor: descriptors.SyncDescriptor<T>, ...args: any[]): T;
createInstance<T>(descriptor: descriptors.AsyncDescriptor<T>, ...args: any[]): winjs.TPromise<T>;
createInstance<T>(param: any): any {
let rest = new Array<any>(arguments.length - 1);
for (let i = 1, len = arguments.length; i < len; i++) {
rest[i - 1] = arguments[i];
}
if (param instanceof descriptors.SyncDescriptor) {
return this._servicesMap.createInstance(<descriptors.SyncDescriptor<T>>param, rest);
} else if (param instanceof descriptors.AsyncDescriptor) {
return this._createInstanceAsync(<descriptors.AsyncDescriptor<T>>param, rest);
} else {
return this._servicesMap.createInstance(new descriptors.SyncDescriptor(<instantiation.IConstructorSignature0<T>>param), rest);
} }
} }
_createInstanceAsync<T>(descriptor: descriptors.AsyncDescriptor<T>, args: any[]): winjs.TPromise<T> {
let canceled: Error;
return new winjs.TPromise((c, e, p) => {
require([descriptor.moduleName], (_module?: any) => {
if (canceled) {
e(canceled);
} }
if (!_module) { while (true) {
return e(errors.illegalArgument('module not found: ' + descriptor.moduleName)); let roots = graph.roots();
}
let ctor: Function; // if there is no more roots but still
if (!descriptor.ctorName) { // nodes in the graph we have a cycle
ctor = _module; if (roots.length === 0) {
} else { if (graph.length !== 0) {
ctor = _module[descriptor.ctorName]; throwCycleError();
} }
break;
if (typeof ctor !== 'function') {
return e(errors.illegalArgument('not a function: ' + descriptor.ctorName || descriptor.moduleName));
} }
try { for (let root of roots) {
args.unshift.apply(args, descriptor.staticArguments()); // instead of spread in ctor call // create instance and overwrite the service collections
c(this._servicesMap.createInstance(new descriptors.SyncDescriptor<T>(ctor), args)); const instance = this._createInstance(root.data.desc, []);
} catch (error) { this._services.set(id, instance);
return e(error); graph.removeNode(root.data);
} }
}, e);
}, () => {
canceled = errors.canceled();
});
} }
invokeFunction<R>(ctor: instantiation.IFunctionSignature0<R>): R; return <T> this._services.get(id);
invokeFunction<A1, R>(ctor: instantiation.IFunctionSignature1<A1, R>, first: A1): R;
invokeFunction<A1, A2, R>(ctor: instantiation.IFunctionSignature2<A1, A2, R>, first: A1, second: A2): R;
invokeFunction<A1, A2, A3, R>(ctor: instantiation.IFunctionSignature3<A1, A2, A3, R>, first: A1, second: A2, third: A3): R;
invokeFunction<A1, A2, A3, A4, R>(ctor: instantiation.IFunctionSignature4<A1, A2, A3, A4, R>, first: A1, second: A2, third: A3, fourth: A4): R;
invokeFunction<A1, A2, A3, A4, A5, R>(ctor: instantiation.IFunctionSignature5<A1, A2, A3, A4, A5, R>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5): R;
invokeFunction<A1, A2, A3, A4, A5, A6, R>(ctor: instantiation.IFunctionSignature6<A1, A2, A3, A4, A5, A6, R>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6): R;
invokeFunction<A1, A2, A3, A4, A5, A6, A7, R>(ctor: instantiation.IFunctionSignature7<A1, A2, A3, A4, A5, A6, A7, R>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7): R;
invokeFunction<A1, A2, A3, A4, A5, A6, A7, A8, R>(ctor: instantiation.IFunctionSignature8<A1, A2, A3, A4, A5, A6, A7, A8, R>, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8): R;
invokeFunction<R>(signature: any, ...args: any[]): R {
return this._servicesMap.invokeFunction<R>(signature, args);
} }
} }
/*---------------------------------------------------------------------------------------------
* 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 {binarySearch} from 'vs/base/common/arrays';
import {ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation';
import {SyncDescriptor} from './descriptors';
type Entry = [ServiceIdentifier<any>, any];
export default class ServiceCollection {
private _entries: Entry[] = [];
constructor(...entries:[ServiceIdentifier<any>, any][]) {
for (let entry of entries) {
this.set(entry[0], entry[1]);
}
}
set<T>(id: ServiceIdentifier<T>, instanceOrDescriptor: T | SyncDescriptor<T>): T | SyncDescriptor<T> {
const entry: Entry = [id, instanceOrDescriptor];
const idx = binarySearch(this._entries, entry, ServiceCollection._entryCompare);
if (idx < 0) {
// new element
this._entries.splice(~idx, 0, entry);
} else {
const old = this._entries[idx];
this._entries[idx] = entry;
return old[1];
}
}
forEach(callback: (id: ServiceIdentifier<any>, instanceOrDescriptor: any) => any): void {
for (let entry of this._entries) {
let [id, instanceOrDescriptor] = entry;
callback(id, instanceOrDescriptor);
}
}
has(id: ServiceIdentifier<any>): boolean {
return binarySearch(this._entries, ServiceCollection._searchEntry(id), ServiceCollection._entryCompare) >= 0;
}
get<T>(id: ServiceIdentifier<T>): T | SyncDescriptor<T> {
const idx = binarySearch(this._entries, ServiceCollection._searchEntry(id), ServiceCollection._entryCompare);
if (idx >= 0) {
return this._entries[idx][1];
}
}
private static _dummy: Entry = [undefined, undefined];
private static _searchEntry(id: ServiceIdentifier<any>): Entry {
ServiceCollection._dummy[0] = id;
return ServiceCollection._dummy;
}
private static _entryCompare(a: Entry, b: Entry): number {
const _a = a[0].toString();
const _b = b[0].toString();
if (_a < _b) {
return -1;
} else if (_a > _b) {
return 1;
} else {
return 0;
}
}
}
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
import assert = require('assert'); import assert = require('assert');
import instantiation = require('vs/platform/instantiation/common/instantiation'); import instantiation = require('vs/platform/instantiation/common/instantiation');
import instantiationService = require('vs/platform/instantiation/common/instantiationService'); import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {SyncDescriptor} from 'vs/platform/instantiation/common/descriptors'; import {SyncDescriptor} from 'vs/platform/instantiation/common/descriptors';
let IService1 = instantiation.createDecorator<IService1>('service1'); let IService1 = instantiation.createDecorator<IService1>('service1');
...@@ -63,7 +63,7 @@ class DependentService implements IDependentService { ...@@ -63,7 +63,7 @@ class DependentService implements IDependentService {
name = 'farboo'; name = 'farboo';
} }
class ParameterTarget { class Target1Dep {
constructor( @IService1 service1: IService1) { constructor( @IService1 service1: IService1) {
assert.ok(service1); assert.ok(service1);
...@@ -71,7 +71,15 @@ class ParameterTarget { ...@@ -71,7 +71,15 @@ class ParameterTarget {
} }
} }
class ParameterTarget2 { class Target2Dep {
constructor( @IService1 service1: IService1, @IService2 service2) {
assert.ok(service1 instanceof Service1);
assert.ok(service2 instanceof Service2);
}
}
class TargetWithStaticParam {
constructor(v: boolean, @IService1 service1: IService1) { constructor(v: boolean, @IService1 service1: IService1) {
assert.ok(v); assert.ok(v);
assert.ok(service1); assert.ok(service1);
...@@ -123,27 +131,80 @@ class ServiceLoop2 implements IService2 { ...@@ -123,27 +131,80 @@ class ServiceLoop2 implements IService2 {
} }
suite('Instantiation Service', () => { suite('Instantiation Service', () => {
test('@Param - simple clase', function() {
let service = instantiationService.createInstantiationService(Object.create(null));
service.addSingleton(IService1, new Service1());
service.addSingleton(IService2, new Service2());
service.addSingleton(IService3, new Service3());
service.createInstance(ParameterTarget); test('service collection, cannot overwrite', function () {
let collection = new ServiceCollection();
let result = collection.set(IService1, null);
assert.equal(result, undefined);
result = collection.set(IService1, new Service1());
assert.equal(result, null);
});
test('service collection, add/has', function () {
let collection = new ServiceCollection();
collection.set(IService1, null);
assert.ok(collection.has(IService1));
collection.set(IService2, null);
assert.ok(collection.has(IService1));
assert.ok(collection.has(IService2));
});
test('addSingleton - cannot overwrite service', function () {
let collection = new ServiceCollection();
let service = new InstantiationService(collection);
collection.set(IService1, new Service1());
assert.throws(() => service.addSingleton(IService1, new Service1()));
});
test('@Param - simple clase', function () {
let collection = new ServiceCollection();
let service = new InstantiationService(collection);
collection.set(IService1, new Service1());
collection.set(IService2, new Service2());
collection.set(IService3, new Service3());
service.createInstance(Target1Dep);
});
test('@Param - fixed args', function () {
let collection = new ServiceCollection();
let service = new InstantiationService(collection);
collection.set(IService1, new Service1());
collection.set(IService2, new Service2());
collection.set(IService3, new Service3());
service.createInstance(TargetWithStaticParam, true);
}); });
test('@Param - fixed args', function() { test('service collection is live', function () {
let service = instantiationService.createInstantiationService(Object.create(null));
service.addSingleton(IService1, new Service1()); let collection = new ServiceCollection();
service.addSingleton(IService2, new Service2()); collection.set(IService1, new Service1());
service.addSingleton(IService3, new Service3());
service.createInstance(ParameterTarget2, true); let service = new InstantiationService(collection);
service.createInstance(Target1Dep);
// no IService2
assert.throws(() => service.createInstance(Target2Dep));
service.invokeFunction(function (a) {
assert.ok(a.get(IService1));
assert.ok(!a.get(IService2));
});
collection.set(IService2, new Service2());
service.createInstance(Target2Dep);
service.invokeFunction(function (a) {
assert.ok(a.get(IService1));
assert.ok(a.get(IService2));
});
}); });
test('@Param - optional', function() { test('@Param - optional', function () {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new Service1()); let service = new InstantiationService(collection);
collection.set(IService1, new Service1());
// service.addSingleton(IService2, new Service2()); // service.addSingleton(IService2, new Service2());
service.createInstance(TargetOptional); service.createInstance(TargetOptional);
...@@ -169,8 +230,9 @@ suite('Instantiation Service', () => { ...@@ -169,8 +230,9 @@ suite('Instantiation Service', () => {
// }); // });
test('SyncDesc - no dependencies', function() { test('SyncDesc - no dependencies', function() {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new SyncDescriptor<IService1>(Service1)); let service = new InstantiationService(collection);
collection.set(IService1, new SyncDescriptor<IService1>(Service1));
let service1 = service.getInstance(IService1); let service1 = service.getInstance(IService1);
assert.ok(service1); assert.ok(service1);
...@@ -181,9 +243,10 @@ suite('Instantiation Service', () => { ...@@ -181,9 +243,10 @@ suite('Instantiation Service', () => {
}); });
test('SyncDesc - service with service dependency', function() { test('SyncDesc - service with service dependency', function() {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new SyncDescriptor<IService1>(Service1)); let service = new InstantiationService(collection);
service.addSingleton(IDependentService, new SyncDescriptor<IDependentService>(DependentService)); collection.set(IService1, new SyncDescriptor<IService1>(Service1));
collection.set(IDependentService, new SyncDescriptor<IDependentService>(DependentService));
let d = service.getInstance(IDependentService); let d = service.getInstance(IDependentService);
assert.ok(d); assert.ok(d);
...@@ -191,9 +254,10 @@ suite('Instantiation Service', () => { ...@@ -191,9 +254,10 @@ suite('Instantiation Service', () => {
}); });
test('SyncDesc - target depends on service future', function() { test('SyncDesc - target depends on service future', function() {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new SyncDescriptor<IService1>(Service1)); let service = new InstantiationService(collection);
service.addSingleton(IDependentService, new SyncDescriptor<IDependentService>(DependentService)); collection.set(IService1, new SyncDescriptor<IService1>(Service1));
collection.set(IDependentService, new SyncDescriptor<IDependentService>(DependentService));
let d = service.createInstance(DependentServiceTarget); let d = service.createInstance(DependentServiceTarget);
assert.ok(d instanceof DependentServiceTarget); assert.ok(d instanceof DependentServiceTarget);
...@@ -203,9 +267,10 @@ suite('Instantiation Service', () => { ...@@ -203,9 +267,10 @@ suite('Instantiation Service', () => {
}); });
test('SyncDesc - explode on loop', function() { test('SyncDesc - explode on loop', function() {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new SyncDescriptor<IService1>(ServiceLoop1)); let service = new InstantiationService(collection);
service.addSingleton(IService2, new SyncDescriptor<IService2>(ServiceLoop2)); collection.set(IService1, new SyncDescriptor<IService1>(ServiceLoop1));
collection.set(IService2, new SyncDescriptor<IService2>(ServiceLoop2));
assert.throws(() => service.getInstance(IService1)); assert.throws(() => service.getInstance(IService1));
assert.throws(() => service.getInstance(IService2)); assert.throws(() => service.getInstance(IService2));
...@@ -219,9 +284,10 @@ suite('Instantiation Service', () => { ...@@ -219,9 +284,10 @@ suite('Instantiation Service', () => {
}); });
test('Invoke - get services', function() { test('Invoke - get services', function() {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new Service1()); let service = new InstantiationService(collection);
service.addSingleton(IService2, new Service2()); collection.set(IService1, new Service1());
collection.set(IService2, new Service2());
function test(accessor: instantiation.ServicesAccessor) { function test(accessor: instantiation.ServicesAccessor) {
assert.ok(accessor.get(IService1) instanceof Service1); assert.ok(accessor.get(IService1) instanceof Service1);
...@@ -234,9 +300,10 @@ suite('Instantiation Service', () => { ...@@ -234,9 +300,10 @@ suite('Instantiation Service', () => {
}); });
test('Invoke - keeping accessor NOT allowed', function() { test('Invoke - keeping accessor NOT allowed', function() {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new Service1()); let service = new InstantiationService(collection);
service.addSingleton(IService2, new Service2()); collection.set(IService1, new Service1());
collection.set(IService2, new Service2());
let cached: instantiation.ServicesAccessor; let cached: instantiation.ServicesAccessor;
...@@ -253,9 +320,10 @@ suite('Instantiation Service', () => { ...@@ -253,9 +320,10 @@ suite('Instantiation Service', () => {
}); });
test('Invoke - throw error', function() { test('Invoke - throw error', function() {
let service = instantiationService.createInstantiationService(Object.create(null)); let collection = new ServiceCollection();
service.addSingleton(IService1, new Service1()); let service = new InstantiationService(collection);
service.addSingleton(IService2, new Service2()); collection.set(IService1, new Service1());
collection.set(IService2, new Service2());
function test(accessor: instantiation.ServicesAccessor) { function test(accessor: instantiation.ServicesAccessor) {
throw new Error(); throw new Error();
......
...@@ -4,11 +4,10 @@ ...@@ -4,11 +4,10 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import {Registry} from 'vs/platform/platform';
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import {IDisposable} from 'vs/base/common/lifecycle'; import {IDisposable} from 'vs/base/common/lifecycle';
import {ITimerEvent, nullEvent} from 'vs/base/common/timer'; import {ITimerEvent, nullEvent} from 'vs/base/common/timer';
import {createDecorator, ServiceIdentifier, IInstantiationService, IConstructorSignature0} from 'vs/platform/instantiation/common/instantiation'; import {createDecorator, ServiceIdentifier, IInstantiationService, ServicesAccessor, IConstructorSignature0} from 'vs/platform/instantiation/common/instantiation';
export const ITelemetryService = createDecorator<ITelemetryService>('telemetryService'); export const ITelemetryService = createDecorator<ITelemetryService>('telemetryService');
...@@ -37,12 +36,28 @@ export interface ITelemetryService { ...@@ -37,12 +36,28 @@ export interface ITelemetryService {
addTelemetryAppender(appender: ITelemetryAppender): IDisposable; addTelemetryAppender(appender: ITelemetryAppender): IDisposable;
} }
export const Extenstions = { export namespace Extenstions {
TelemetryAppenders: 'telemetry.appenders'
let _telemetryAppenderCtors: IConstructorSignature0<ITelemetryAppender>[] = [];
export const TelemetryAppenders = {
activate(accessor: ServicesAccessor): void {
const telemetryService = accessor.get(ITelemetryService);
const instantiationService = accessor.get(IInstantiationService);
for (let ctor of _telemetryAppenderCtors) {
const instance = instantiationService.createInstance(ctor);
telemetryService.addTelemetryAppender(instance);
}
// can only be done once
_telemetryAppenderCtors = undefined;
},
registerTelemetryAppenderDescriptor(ctor: IConstructorSignature0<ITelemetryAppender>): void {
_telemetryAppenderCtors.push(ctor);
}
};
}; };
export interface ITelemetryAppendersRegistry { export interface ITelemetryAppendersRegistry {
registerTelemetryAppenderDescriptor(ctor: IConstructorSignature0<ITelemetryAppender>): void;
activate(instantiationService: IInstantiationService): void; activate(instantiationService: IInstantiationService): void;
} }
...@@ -64,32 +79,6 @@ export interface ITelemetryAppender extends IDisposable { ...@@ -64,32 +79,6 @@ export interface ITelemetryAppender extends IDisposable {
log(eventName: string, data?: any): void; log(eventName: string, data?: any): void;
} }
export class TelemetryAppendersRegistry implements ITelemetryAppendersRegistry {
private _telemetryAppenderCtors: IConstructorSignature0<ITelemetryAppender>[];
constructor() {
this._telemetryAppenderCtors = [];
}
public registerTelemetryAppenderDescriptor(ctor: IConstructorSignature0<ITelemetryAppender>): void {
this._telemetryAppenderCtors.push(ctor);
}
public activate(instantiationService: IInstantiationService): void {
const service = instantiationService.getInstance(ITelemetryService);
for (let ctor of this._telemetryAppenderCtors) {
const instance = instantiationService.createInstance(ctor);
service.addTelemetryAppender(instance);
}
// can only be done once
this._telemetryAppenderCtors = undefined;
}
}
Registry.add(Extenstions.TelemetryAppenders, new TelemetryAppendersRegistry());
// --- util // --- util
export function anonymize(input: string): string { export function anonymize(input: string): string {
......
...@@ -8,7 +8,8 @@ import * as assert from 'assert'; ...@@ -8,7 +8,8 @@ import * as assert from 'assert';
import IdleMonitor = require('vs/base/browser/idleMonitor'); import IdleMonitor = require('vs/base/browser/idleMonitor');
import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService'; import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService';
import Telemetry = require('vs/platform/telemetry/common/telemetry'); import Telemetry = require('vs/platform/telemetry/common/telemetry');
import InstantiationService = require('vs/platform/instantiation/common/instantiationService'); import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import Errors = require('vs/base/common/errors'); import Errors = require('vs/base/common/errors');
import Timer = require('vs/base/common/timer'); import Timer = require('vs/base/common/timer');
import * as sinon from 'sinon'; import * as sinon from 'sinon';
...@@ -175,8 +176,7 @@ suite('TelemetryService', () => { ...@@ -175,8 +176,7 @@ suite('TelemetryService', () => {
test('TelemetryAppendersRegistry, activate', function() { test('TelemetryAppendersRegistry, activate', function() {
let registry = new Telemetry.TelemetryAppendersRegistry(); Telemetry.Extenstions.TelemetryAppenders.registerTelemetryAppenderDescriptor(TestTelemetryAppender);
registry.registerTelemetryAppenderDescriptor(TestTelemetryAppender);
let callCount = 0; let callCount = 0;
let telemetryService: Telemetry.ITelemetryService = <any> { let telemetryService: Telemetry.ITelemetryService = <any> {
...@@ -186,14 +186,13 @@ suite('TelemetryService', () => { ...@@ -186,14 +186,13 @@ suite('TelemetryService', () => {
} }
}; };
let instantiationService = InstantiationService.createInstantiationService(); let instantiationService = new InstantiationService(new ServiceCollection([Telemetry.ITelemetryService, telemetryService]));
instantiationService.addSingleton(Telemetry.ITelemetryService, telemetryService); instantiationService.invokeFunction(Telemetry.Extenstions.TelemetryAppenders.activate);
registry.activate(instantiationService);
assert.equal(callCount, 1); assert.equal(callCount, 1);
// registry is now active/read-only // registry is now active/read-only
assert.throws(() => registry.registerTelemetryAppenderDescriptor(TestTelemetryAppender)); assert.throws(() => Telemetry.Extenstions.TelemetryAppenders.registerTelemetryAppenderDescriptor(TestTelemetryAppender));
assert.throws(() => registry.activate(instantiationService)); assert.throws(() => instantiationService.invokeFunction(Telemetry.Extenstions.TelemetryAppenders.activate));
}); });
test('Disposing', sinon.test(function() { test('Disposing', sinon.test(function() {
......
...@@ -31,6 +31,7 @@ import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage' ...@@ -31,6 +31,7 @@ import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'
import {IContextMenuService} from 'vs/platform/contextview/browser/contextView'; import {IContextMenuService} from 'vs/platform/contextview/browser/contextView';
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 ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {IMessageService, Severity} from 'vs/platform/message/common/message'; import {IMessageService, Severity} from 'vs/platform/message/common/message';
import {IProgressService} from 'vs/platform/progress/common/progress'; import {IProgressService} from 'vs/platform/progress/common/progress';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
...@@ -176,10 +177,7 @@ export abstract class CompositePart<T extends Composite> extends Part { ...@@ -176,10 +177,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
let loaderPromise = this.compositeLoaderPromises[id]; let loaderPromise = this.compositeLoaderPromises[id];
if (!loaderPromise) { if (!loaderPromise) {
let progressService = new WorkbenchProgressService(this.eventService, this.progressBar, compositeDescriptor.id, isActive); let progressService = new WorkbenchProgressService(this.eventService, this.progressBar, compositeDescriptor.id, isActive);
let services = { let compositeInstantiationService = this.instantiationService.createChild(new ServiceCollection([IProgressService, progressService]));
progressService: progressService
};
let compositeInstantiationService = this.instantiationService.createChild(services);
loaderPromise = compositeInstantiationService.createInstance(compositeDescriptor).then((composite: Composite) => { loaderPromise = compositeInstantiationService.createInstance(compositeDescriptor).then((composite: Composite) => {
this.mapProgressServiceToComposite[composite.getId()] = progressService; this.mapProgressServiceToComposite[composite.getId()] = progressService;
......
...@@ -36,8 +36,10 @@ import {Position, POSITIONS} from 'vs/platform/editor/common/editor'; ...@@ -36,8 +36,10 @@ import {Position, POSITIONS} from 'vs/platform/editor/common/editor';
import {IStorageService} from 'vs/platform/storage/common/storage'; import {IStorageService} from 'vs/platform/storage/common/storage';
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 ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {IMessageService, IMessageWithAction, Severity} from 'vs/platform/message/common/message'; import {IMessageService, IMessageWithAction, Severity} from 'vs/platform/message/common/message';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IProgressService} from 'vs/platform/progress/common/progress';
const EDITOR_STATE_STORAGE_KEY = 'editorpart.editorState'; const EDITOR_STATE_STORAGE_KEY = 'editorpart.editorState';
...@@ -755,11 +757,10 @@ export class EditorPart extends Part implements IEditorPart { ...@@ -755,11 +757,10 @@ export class EditorPart extends Part implements IEditorPart {
} }
private createEditor(editorDescriptor: EditorDescriptor, editorDomNode: HTMLElement, position: Position): TPromise<BaseEditor> { private createEditor(editorDescriptor: EditorDescriptor, editorDomNode: HTMLElement, position: Position): TPromise<BaseEditor> {
let services = {
progressService: new WorkbenchProgressService(this.eventService, this.sideBySideControl.getProgressBar(position), editorDescriptor.getId(), true)
};
let editorInstantiationService = this.instantiationService.createChild(services); let progressService = new WorkbenchProgressService(this.eventService, this.sideBySideControl.getProgressBar(position), editorDescriptor.getId(), true);
let editorInstantiationService = this.instantiationService.createChild(new ServiceCollection([IProgressService, progressService]));
return editorInstantiationService.createInstance(editorDescriptor); return editorInstantiationService.createInstance(editorDescriptor);
} }
......
...@@ -32,6 +32,7 @@ import {IStorageService} from 'vs/platform/storage/common/storage'; ...@@ -32,6 +32,7 @@ import {IStorageService} from 'vs/platform/storage/common/storage';
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';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {IMessageService} from 'vs/platform/message/common/message'; import {IMessageService} from 'vs/platform/message/common/message';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IModeService} from 'vs/editor/common/services/modeService'; import {IModeService} from 'vs/editor/common/services/modeService';
...@@ -111,9 +112,7 @@ export class TextDiffEditor extends BaseTextEditor { ...@@ -111,9 +112,7 @@ export class TextDiffEditor extends BaseTextEditor {
}); });
// Create a special child of instantiator that will delegate all calls to openEditor() to the same diff editor if the input matches with the modified one // Create a special child of instantiator that will delegate all calls to openEditor() to the same diff editor if the input matches with the modified one
let diffEditorInstantiator = this.instantiationService.createChild({ let diffEditorInstantiator = this.instantiationService.createChild(new ServiceCollection([IWorkbenchEditorService, delegatingService]));
editorService: delegatingService
});
return diffEditorInstantiator.createInstance(DiffEditorWidget, parent.getHTMLElement(), this.getCodeEditorOptions()); return diffEditorInstantiator.createInstance(DiffEditorWidget, parent.getHTMLElement(), this.getCodeEditorOptions());
} }
......
...@@ -427,7 +427,7 @@ export class Workbench implements IPartService { ...@@ -427,7 +427,7 @@ export class Workbench implements IPartService {
<IWorkbenchContributionsRegistry>Registry.as(WorkbenchExtensions.Workbench).setInstantiationService(this.instantiationService); <IWorkbenchContributionsRegistry>Registry.as(WorkbenchExtensions.Workbench).setInstantiationService(this.instantiationService);
<IEditorRegistry>Registry.as(EditorExtensions.Editors).setInstantiationService(this.instantiationService); <IEditorRegistry>Registry.as(EditorExtensions.Editors).setInstantiationService(this.instantiationService);
Registry.as<{activate(s:IInstantiationService):void}>(TelemetryExtensions.TelemetryAppenders).activate(this.instantiationService); this.instantiationService.invokeFunction(TelemetryExtensions.TelemetryAppenders.activate);
} }
private initSettings(): void { private initSettings(): void {
......
...@@ -7,21 +7,13 @@ import * as fs from 'fs'; ...@@ -7,21 +7,13 @@ import * as fs from 'fs';
import platform = require('vs/base/common/platform'); import platform = require('vs/base/common/platform');
import { serve, Server, connect } from 'vs/base/node/service.net'; import { serve, Server, connect } from 'vs/base/node/service.net';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { createInstantiationService as createInstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
// Services // Services
import { IRequestService } from 'vs/platform/request/common/request'; import { IConfiguration } from 'vs/platform/workspace/common/workspace';
import { RequestService } from 'vs/workbench/services/request/node/requestService';
import { IWorkspaceContextService, IConfiguration } from 'vs/platform/workspace/common/workspace';
import { WorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; import { WorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService';
import { IEventService } from 'vs/platform/event/common/event';
import { EventService } from 'vs/platform/event/common/eventService'; import { EventService } from 'vs/platform/event/common/eventService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ConfigurationService } from 'vs/workbench/services/configuration/node/configurationService';
// Extra services // Extra services
import { IExtensionsService } from 'vs/workbench/parts/extensions/common/extensions';
import { ExtensionsService } from 'vs/workbench/parts/extensions/node/extensionsService'; import { ExtensionsService } from 'vs/workbench/parts/extensions/node/extensionsService';
interface IInitData { interface IInitData {
...@@ -51,19 +43,11 @@ function setupPlanB(parentPid: number): void { ...@@ -51,19 +43,11 @@ function setupPlanB(parentPid: number): void {
} }
function main(server: Server, initData: IInitData): void { function main(server: Server, initData: IInitData): void {
const eventService = new EventService(); const eventService = new EventService();
const contextService = new WorkspaceContextService(eventService, null, initData.configuration, initData.contextServiceOptions); const contextService = new WorkspaceContextService(eventService, null, initData.configuration, initData.contextServiceOptions);
const configurationService = new ConfigurationService(contextService, eventService); const extensionService = new ExtensionsService(contextService);
const requestService = new RequestService(contextService, configurationService);
const instantiationService = createInstantiationService();
instantiationService.addSingleton(IEventService, eventService);
instantiationService.addSingleton(IWorkspaceContextService, contextService);
instantiationService.addSingleton(IConfigurationService, configurationService);
instantiationService.addSingleton(IRequestService, requestService);
instantiationService.addSingleton(IExtensionsService, new SyncDescriptor(ExtensionsService));
const extensionService = <ExtensionsService> instantiationService.getInstance(IExtensionsService);
server.registerService('ExtensionService', extensionService); server.registerService('ExtensionService', extensionService);
// eventually clean up old extensions // eventually clean up old extensions
......
...@@ -17,14 +17,15 @@ import {IExtensionService, IExtensionDescription} from 'vs/platform/extensions/c ...@@ -17,14 +17,15 @@ import {IExtensionService, IExtensionDescription} from 'vs/platform/extensions/c
import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry'; import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry';
import {ExtHostAPIImplementation} from 'vs/workbench/api/node/extHost.api.impl'; import {ExtHostAPIImplementation} from 'vs/workbench/api/node/extHost.api.impl';
import {IMainProcessExtHostIPC} from 'vs/platform/extensions/common/ipcRemoteCom'; import {IMainProcessExtHostIPC} from 'vs/platform/extensions/common/ipcRemoteCom';
import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import InstantiationService = require('vs/platform/instantiation/common/instantiationService'); import InstantiationService = require('vs/platform/instantiation/common/instantiationService');
import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {ExtHostExtensionService} from 'vs/platform/extensions/common/nativeExtensionService'; import {ExtHostExtensionService} from 'vs/platform/extensions/common/nativeExtensionService';
import {IThreadService} from 'vs/platform/thread/common/thread';
import {ExtHostThreadService} from 'vs/platform/thread/common/extHostThreadService'; import {ExtHostThreadService} from 'vs/platform/thread/common/extHostThreadService';
import {RemoteTelemetryService} from 'vs/platform/telemetry/common/remoteTelemetryService'; import {RemoteTelemetryService} from 'vs/platform/telemetry/common/remoteTelemetryService';
import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService'; import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService';
import {ModeServiceImpl} from 'vs/editor/common/services/modeServiceImpl';
import {ExtensionScanner, MessagesCollector} from 'vs/workbench/node/extensionPoints'; import {ExtensionScanner, MessagesCollector} from 'vs/workbench/node/extensionPoints';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {Client} from 'vs/base/node/service.net'; import {Client} from 'vs/base/node/service.net';
...@@ -57,29 +58,22 @@ export function createServices(remoteCom: IMainProcessExtHostIPC, initData: IIni ...@@ -57,29 +58,22 @@ export function createServices(remoteCom: IMainProcessExtHostIPC, initData: IIni
let contextService = new BaseWorkspaceContextService(initData.contextService.workspace, initData.contextService.configuration, initData.contextService.options); let contextService = new BaseWorkspaceContextService(initData.contextService.workspace, initData.contextService.configuration, initData.contextService.options);
let threadService = new ExtHostThreadService(remoteCom); let threadService = new ExtHostThreadService(remoteCom);
threadService.setInstantiationService(InstantiationService.createInstantiationService({ threadService: threadService })); threadService.setInstantiationService(InstantiationService.createInstantiationService(new ServiceCollection([IThreadService, threadService])));
let telemetryService = new RemoteTelemetryService('pluginHostTelemetry', threadService); let telemetryService = new RemoteTelemetryService('pluginHostTelemetry', threadService);
let modelService = threadService.getRemotable(ExtHostModelService);
let services = new ServiceCollection();
let extensionService = new ExtHostExtensionService(threadService, telemetryService); services.set(IWorkspaceContextService, contextService);
let modeService = new ModeServiceImpl(threadService, extensionService); services.set(ITelemetryService, telemetryService);
let _services: any = { services.set(IThreadService, threadService);
contextService, services.set(IExtensionService, new ExtHostExtensionService(threadService, telemetryService));
modelService, services.set(IExtensionsService, sharedProcessClient.getService<IExtensionsService>('ExtensionService', ExtensionsService)); // Connect to shared process services
threadService,
modeService, let instantiationService = InstantiationService.createInstantiationService(services);
extensionService,
telemetryService
};
let instantiationService = InstantiationService.createInstantiationService(_services);
threadService.setInstantiationService(instantiationService); threadService.setInstantiationService(instantiationService);
// Create the monaco API // Create the monaco API
instantiationService.createInstance(ExtHostAPIImplementation); instantiationService.createInstance(ExtHostAPIImplementation);
// Connect to shared process services
instantiationService.addSingleton(IExtensionsService, sharedProcessClient.getService<IExtensionsService>('ExtensionService', ExtensionsService));
return instantiationService; return instantiationService;
} }
......
...@@ -10,6 +10,7 @@ import URI from 'vs/base/common/uri'; ...@@ -10,6 +10,7 @@ import URI from 'vs/base/common/uri';
import {join} from 'vs/base/common/paths'; import {join} from 'vs/base/common/paths';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput'; import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import {createInstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {ITextFileService} from 'vs/workbench/parts/files/common/files';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices'; import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {NullTelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {FileTracker} from 'vs/workbench/parts/files/browser/fileTracker'; import {FileTracker} from 'vs/workbench/parts/files/browser/fileTracker';
...@@ -42,8 +43,8 @@ suite('Files - FileEditorInput', () => { ...@@ -42,8 +43,8 @@ suite('Files - FileEditorInput', () => {
configurationService: new TestConfigurationService() configurationService: new TestConfigurationService()
}); });
let textFileServices = instantiationService.createInstance(<any>TextFileService); let textFileServices = <ITextFileService> instantiationService.createInstance(<any> TextFileService);
instantiationService.registerService('textFileService', textFileServices); instantiationService.addSingleton(ITextFileService, textFileServices);
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);
...@@ -133,8 +134,8 @@ suite('Files - FileEditorInput', () => { ...@@ -133,8 +134,8 @@ suite('Files - FileEditorInput', () => {
configurationService: new TestConfigurationService() configurationService: new TestConfigurationService()
}); });
let textFileServices = instantiationService.createInstance(<any>TextFileService); let textFileServices = <ITextFileService> instantiationService.createInstance(<any>TextFileService);
instantiationService.registerService('textFileService', textFileServices); instantiationService.addSingleton(ITextFileService, textFileServices);
let tracker = instantiationService.createInstance(FileTracker); let tracker = instantiationService.createInstance(FileTracker);
...@@ -177,8 +178,8 @@ suite('Files - FileEditorInput', () => { ...@@ -177,8 +178,8 @@ suite('Files - FileEditorInput', () => {
configurationService: new TestConfigurationService() configurationService: new TestConfigurationService()
}); });
let textFileServices = instantiationService.createInstance(<any>TextFileService); let textFileServices = <ITextFileService> instantiationService.createInstance(<any>TextFileService);
instantiationService.registerService('textFileService', textFileServices); instantiationService.addSingleton(ITextFileService, textFileServices);
let tracker = instantiationService.createInstance(FileTracker); let tracker = instantiationService.createInstance(FileTracker);
......
...@@ -15,7 +15,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat ...@@ -15,7 +15,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat
import {NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {NullTelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import {createInstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices'; import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {EventType} from 'vs/workbench/parts/files/common/files'; import {ITextFileService, EventType} from 'vs/workbench/parts/files/common/files';
import {TestFileService, TestLifecycleService, TestPartService, TestEditorService, TestConfigurationService, TestUntitledEditorService, TestStorageService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/browser/servicesTestUtils'; import {TestFileService, TestLifecycleService, TestPartService, TestEditorService, TestConfigurationService, TestUntitledEditorService, TestStorageService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/browser/servicesTestUtils';
import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils'; import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils';
...@@ -52,7 +52,7 @@ suite('Files - TextFileEditorModel', () => { ...@@ -52,7 +52,7 @@ suite('Files - TextFileEditorModel', () => {
textFileService = <TextFileService>baseInstantiationService.createInstance(<any>TextFileService); textFileService = <TextFileService>baseInstantiationService.createInstance(<any>TextFileService);
baseInstantiationService.registerService('textFileService', textFileService); baseInstantiationService.addSingleton(ITextFileService, textFileService);
}); });
teardown(() => { teardown(() => {
......
...@@ -5,9 +5,7 @@ ...@@ -5,9 +5,7 @@
'use strict'; 'use strict';
import Platform = require('vs/platform/platform'); import {Extenstions} from 'vs/platform/telemetry/common/telemetry';
import {Extenstions, ITelemetryAppendersRegistry} from 'vs/platform/telemetry/common/telemetry';
import AppInsightsTelemetryAppender = require('vs/workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender'); import AppInsightsTelemetryAppender = require('vs/workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender');
Platform.Registry.as<ITelemetryAppendersRegistry>(Extenstions.TelemetryAppenders) Extenstions.TelemetryAppenders.registerTelemetryAppenderDescriptor(AppInsightsTelemetryAppender.NodeAppInsightsTelemetryAppender);
.registerTelemetryAppenderDescriptor(AppInsightsTelemetryAppender.NodeAppInsightsTelemetryAppender); \ No newline at end of file
\ No newline at end of file
...@@ -16,6 +16,7 @@ import {StringEditorInput} from 'vs/workbench/common/editor/stringEditorInput'; ...@@ -16,6 +16,7 @@ import {StringEditorInput} from 'vs/workbench/common/editor/stringEditorInput';
import {StringEditorModel} from 'vs/workbench/common/editor/stringEditorModel'; 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 {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices'; import {TextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {TestEventService, TestLifecycleService, TestPartService, TestStorageService, TestConfigurationService, 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 {Viewlet} from 'vs/workbench/browser/viewlet';
...@@ -257,8 +258,8 @@ suite('Workbench UI Services', () => { ...@@ -257,8 +258,8 @@ suite('Workbench UI Services', () => {
}; };
let inst = createInstantiationService(services); let inst = createInstantiationService(services);
let textFileService = inst.createInstance(<any>TextFileService); let textFileService = <ITextFileService>inst.createInstance(<any>TextFileService);
inst.registerService('textFileService', textFileService); inst.addSingleton(ITextFileService, textFileService);
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);
...@@ -358,8 +359,8 @@ suite('Workbench UI Services', () => { ...@@ -358,8 +359,8 @@ suite('Workbench UI Services', () => {
}; };
let inst = createInstantiationService(services); let inst = createInstantiationService(services);
let textFileService = inst.createInstance(<any>TextFileService); let textFileService = <ITextFileService> inst.createInstance(<any>TextFileService);
inst.registerService('textFileService', textFileService); inst.addSingleton(ITextFileService, textFileService);
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);
......
...@@ -13,7 +13,8 @@ import * as types from 'vs/workbench/api/node/extHostTypes'; ...@@ -13,7 +13,8 @@ import * as types from 'vs/workbench/api/node/extHostTypes';
import * as EditorCommon from 'vs/editor/common/editorCommon'; import * as EditorCommon from 'vs/editor/common/editorCommon';
import {Model as EditorModel} from 'vs/editor/common/model/model'; import {Model as EditorModel} from 'vs/editor/common/model/model';
import {TestThreadService} from './testThreadService'; import {TestThreadService} from './testThreadService';
import {createInstantiationService as createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {MainProcessMarkerService} from 'vs/platform/markers/common/markerService'; import {MainProcessMarkerService} from 'vs/platform/markers/common/markerService';
import {IMarkerService} from 'vs/platform/markers/common/markers'; import {IMarkerService} from 'vs/platform/markers/common/markers';
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
...@@ -50,18 +51,19 @@ suite('ExtHostLanguageFeatureCommands', function() { ...@@ -50,18 +51,19 @@ suite('ExtHostLanguageFeatureCommands', function() {
originalErrorHandler = errorHandler.getUnexpectedErrorHandler(); originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
setUnexpectedErrorHandler(() => { }); setUnexpectedErrorHandler(() => { });
let instantiationService = createInstantiationService(); let services = new ServiceCollection();
let instantiationService = new InstantiationService(services);
threadService = new TestThreadService(instantiationService); threadService = new TestThreadService(instantiationService);
instantiationService.addSingleton(IKeybindingService, <IKeybindingService>{ services.set(IKeybindingService, <IKeybindingService>{
executeCommand(id, args): any { executeCommand(id, args): any {
let handler = KeybindingsRegistry.getCommands()[id]; let handler = KeybindingsRegistry.getCommands()[id];
return TPromise.as(instantiationService.invokeFunction(handler, args)); return TPromise.as(instantiationService.invokeFunction(handler, args));
} }
}); });
instantiationService.addSingleton(IMarkerService, new MainProcessMarkerService(threadService)); services.set(IMarkerService, new MainProcessMarkerService(threadService));
instantiationService.addSingleton(IThreadService, threadService); services.set(IThreadService, threadService);
instantiationService.addSingleton(IModelService, <IModelService>{ services.set(IModelService, <IModelService>{
serviceId: IModelService, serviceId: IModelService,
getModel(): any { return model; }, getModel(): any { return model; },
createModel(): any { throw new Error(); }, createModel(): any { throw new Error(); },
......
...@@ -12,7 +12,8 @@ import * as types from 'vs/workbench/api/node/extHostTypes'; ...@@ -12,7 +12,8 @@ import * as types from 'vs/workbench/api/node/extHostTypes';
import * as EditorCommon from 'vs/editor/common/editorCommon'; import * as EditorCommon from 'vs/editor/common/editorCommon';
import {Model as EditorModel} from 'vs/editor/common/model/model'; import {Model as EditorModel} from 'vs/editor/common/model/model';
import {TestThreadService} from './testThreadService'; import {TestThreadService} from './testThreadService';
import {createInstantiationService as createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import ServiceCollection from 'vs/platform/instantiation/common/serviceCollection';
import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {MainProcessMarkerService} from 'vs/platform/markers/common/markerService'; import {MainProcessMarkerService} from 'vs/platform/markers/common/markerService';
import {IMarkerService} from 'vs/platform/markers/common/markers'; import {IMarkerService} from 'vs/platform/markers/common/markers';
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
...@@ -54,10 +55,11 @@ suite('ExtHostLanguageFeatures', function() { ...@@ -54,10 +55,11 @@ suite('ExtHostLanguageFeatures', function() {
suiteSetup(() => { suiteSetup(() => {
let instantiationService = createInstantiationService(); let services = new ServiceCollection();
let instantiationService = new InstantiationService(services);
threadService = new TestThreadService(instantiationService); threadService = new TestThreadService(instantiationService);
instantiationService.addSingleton(IMarkerService, new MainProcessMarkerService(threadService)); services.set(IMarkerService, new MainProcessMarkerService(threadService));
instantiationService.addSingleton(IThreadService, threadService); services.set(IThreadService, threadService);
originalErrorHandler = errorHandler.getUnexpectedErrorHandler(); originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
setUnexpectedErrorHandler(() => { }); setUnexpectedErrorHandler(() => { });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册