/********************************************************************************
 * Copyright (C) 2017 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
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License v. 2.0 are satisfied: GNU General Public License, version 2
 * with the GNU Classpath Exception which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 ********************************************************************************/ import { interfaces } from 'inversify' ; import { ContributionFilterRegistry } from './contribution-filter' ; export const ContributionProvider = Symbol ( 'ContributionProvider' ) ; export interface ContributionProvider < T extends object > { param recursive getContributions ( recursive ? ) : T [ ] ; } class ContainerBasedContributionProvider < T extends object > implements ContributionProvider < T > { protected services : T [ ] | undefined ; constructor ( protected readonly serviceIdentifier , protected readonly container ) { } getContributions ( recursive ? ) { if ( this . services === undefined ) { const currentServices = [ ] ; let filterRegistry ; let currentContainer = this . container ; while ( currentContainer !== null ) { if ( currentContainer . isBound ( this . serviceIdentifier ) ) { try { currentServices . push ( ... currentContainer . getAll ( this . serviceIdentifier ) ) ; } catch ( error ) { console . error ( error ) ; } } if ( filterRegistry === undefined && currentContainer . isBound ( ContributionFilterRegistry ) ) { filterRegistry = currentContainer . get ( ContributionFilterRegistry ) ; } currentContainer = recursive === true ? currentContainer . parent : null ; } this . services = filterRegistry ? filterRegistry . applyFilters ( currentServices , this . serviceIdentifier ) : currentServices ; } return this . services ; } } export type Bindable = interfaces . Bind | interfaces . Container ; export namespace Bindable { export function isContainer ( arg ) { return typeof arg !== 'function' && ( 'guid' in arg || 'parent' in arg ) ; } } export function bindContributionProvider ( bindable , id ) { const bindingToSyntax = ( Bindable . isContainer ( bindable ) ? bindable . bind ( ContributionProvider ) : bindable ( ContributionProvider ) ) ; bindingToSyntax . toDynamicValue ( ctx => new ContainerBasedContributionProvider ( id , ctx . container ) ) . inSingletonScope ( ) . whenTargetNamed ( id ) ; } param bindable param service param contributions export function bindContribution ( bindable , service , contributions ) { const bind = Bindable . isContainer ( bindable ) ? bindable . bind . bind ( bindable ) : bindable ; for ( const contribution of contributions ) { bind ( contribution ) . toService ( service ) ; } }