Skip to content

Commit

Permalink
Allow override of element registration in DI (#424)
Browse files Browse the repository at this point in the history
Signed-off-by: Guillaume Fontorbe <guillaume.fontorbe@typefox.io>
  • Loading branch information
gfontorbe authored Feb 9, 2024
1 parent 2cdca53 commit d5e7ff5
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 18 deletions.
27 changes: 20 additions & 7 deletions packages/sprotty/src/base/model/smodel-factory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2017-2018 TypeFox and others.
* Copyright (c) 2017-2024 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -34,13 +34,25 @@ export class SModelRegistry extends FactoryRegistry<SModelElementImpl, void> {
defaultFeatures = [];
if (defaultFeatures) {
const featureSet = createFeatureSet(defaultFeatures, registration.features);
this.register(registration.type, () => {
const element = new registration.constr();
element.features = featureSet;
return element;
});
if (registration.isOverride) {
this.override(registration.type, () => {
const element = new registration.constr();
element.features = featureSet;
return element;
});
} else {
this.register(registration.type, () => {
const element = new registration.constr();
element.features = featureSet;
return element;
});
}
} else {
this.register(registration.type, () => new registration.constr());
if (registration.isOverride) {
this.override(registration.type, () => new registration.constr());
} else {
this.register(registration.type, () => new registration.constr());
}
}
});
}
Expand Down Expand Up @@ -177,6 +189,7 @@ export interface SModelElementRegistration {
type: string
constr: SModelElementConstructor
features?: CustomFeatures
isOverride?: boolean
}

export interface SModelElementConstructor {
Expand Down
6 changes: 3 additions & 3 deletions packages/sprotty/src/base/model/smodel-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2017-2018 TypeFox and others.
* Copyright (c) 2017-2024 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -24,9 +24,9 @@ import { SModelElementRegistration, CustomFeatures } from "./smodel-factory";
* Register a model element constructor for an element type.
*/
export function registerModelElement(context: { bind: interfaces.Bind, isBound: interfaces.IsBound },
type: string, constr: new () => SModelElementImpl, features?: CustomFeatures): void {
type: string, constr: new () => SModelElementImpl, features?: CustomFeatures, isOverride?: boolean): void {
context.bind<SModelElementRegistration>(TYPES.SModelElementRegistration).toConstantValue({
type, constr, features
type, constr, features, isOverride
});
}

Expand Down
25 changes: 20 additions & 5 deletions packages/sprotty/src/base/views/view.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2017-2018 TypeFox and others.
* Copyright (c) 2017-2024 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -86,6 +86,7 @@ export interface RenderingContext {
export interface ViewRegistration {
type: string
factory: () => IView
isOverride?: boolean
}

export type ViewRegistrationFactory = () => ViewRegistration;
Expand All @@ -101,8 +102,13 @@ export class ViewRegistry extends InstanceRegistry<IView> {
constructor(@multiInject(TYPES.ViewRegistration) @optional() registrations: ViewRegistration[]) {
super();
this.registerDefaults();
registrations.forEach(registration =>
this.register(registration.type, registration.factory())
registrations.forEach(registration => {
if (registration.isOverride) {
this.override(registration.type, registration.factory());
} else {
this.register(registration.type, registration.factory());
}
}
);
}

Expand All @@ -125,12 +131,20 @@ export function configureModelElement(context: { bind: interfaces.Bind, isBound:
registerModelElement(context, type, modelConstr, features);
configureView(context, type, viewConstr);
}
export function overrideModelElement(context: {bind: interfaces.Bind, isBound: interfaces.IsBound},
type: string, modelConstr: new () => SModelElementImpl, viewConstr: interfaces.ServiceIdentifier<IView>,
features?: CustomFeatures): void {
registerModelElement(context, type, modelConstr, features, true);
configureView(context, type, viewConstr, true);
}



/**
* Utility function to register a view for a model element type.
*/
export function configureView(context: { bind: interfaces.Bind, isBound: interfaces.IsBound },
type: string, constr: interfaces.ServiceIdentifier<IView>): void {
type: string, constr: interfaces.ServiceIdentifier<IView>, isOverride?: boolean): void {
if (typeof constr === 'function') {
if (!isInjectable(constr)) {
throw new Error(`Views should be @injectable: ${constr.name}`);
Expand All @@ -141,7 +155,8 @@ export function configureView(context: { bind: interfaces.Bind, isBound: interfa
}
context.bind(TYPES.ViewRegistration).toDynamicValue(ctx => ({
type,
factory: () => ctx.container.get(constr)
factory: () => ctx.container.get(constr),
isOverride
}));
}

Expand Down
24 changes: 21 additions & 3 deletions packages/sprotty/src/utils/registry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2017-2018 TypeFox and others.
* Copyright (c) 2017-2024 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -60,7 +60,16 @@ export class FactoryRegistry<T, U> {
throw new Error('Key is undefined');
}
if (this.hasKey(key)) {
throw new Error('Key is already registered: ' + key);
throw new Error(`Key is already registered: ${key}. Use \`overrideModelElement\` instead.`);
}
this.elements.set(key, factory);
}

override(key: string, factory: (u: U) => T) {
if (key === undefined) {
throw new Error('Key is undefined');
} else if (!this.hasKey(key)) {
throw new Error(`Key is not registered: ${key}. Use \`configureModelElement\` instead.`);
}
this.elements.set(key, factory);
}
Expand Down Expand Up @@ -99,7 +108,16 @@ export class InstanceRegistry<T> {
throw new Error('Key is undefined');
}
if (this.hasKey(key)) {
throw new Error('Key is already registered: ' + key);
throw new Error(`Key is already registered: ${key}. Use \`overrideModelElement\` instead.`);
}
this.elements.set(key, instance);
}

override(key: string, instance: T) {
if (key === undefined) {
throw new Error('Key is undefined');
} else if (!this.hasKey(key)) {
throw new Error(`Key is not registered: ${key}. Use \`configureModelElement\` instead.`);
}
this.elements.set(key, instance);
}
Expand Down

0 comments on commit d5e7ff5

Please sign in to comment.