diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index 8d79cead5ca..65f8ba95f80 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -11,6 +11,7 @@ import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/platform/exten import { ViewLocation, ViewsRegistry, IViewDescriptor } from 'vs/workbench/browser/parts/views/viewsRegistry'; import { TreeView } from 'vs/workbench/browser/parts/views/treeView'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { coalesce, } from 'vs/base/common/arrays'; namespace schema { @@ -82,30 +83,48 @@ namespace schema { }; } -ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyViewDescriptor[] }>('views', [], schema.viewsContribution).setHandler(extensions => { - for (let extension of extensions) { - const { value, collector } = extension; +ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyViewDescriptor[] }>('views', [], schema.viewsContribution) + .setHandler((extensions) => { + for (let extension of extensions) { + const { value, collector } = extension; - forEach(value, entry => { - if (!schema.isValidViewDescriptors(entry.value, collector)) { - return; - } + forEach(value, entry => { + if (!schema.isValidViewDescriptors(entry.value, collector)) { + return; + } - const location = ViewLocation.getContributedViewLocation(entry.key); - if (!location) { - collector.warn(localize('locationId.invalid', "`{0}` is not a valid view location", entry.key)); - return; - } + const location = ViewLocation.getContributedViewLocation(entry.key); + if (!location) { + collector.warn(localize('locationId.invalid', "`{0}` is not a valid view location", entry.key)); + return; + } - const viewDescriptors = entry.value.map(item => ({ - id: item.id, - name: item.name, - ctor: TreeView, - location, - when: ContextKeyExpr.deserialize(item.when), - canToggleVisibility: true - })); - ViewsRegistry.registerViews(viewDescriptors); - }); - } -}); \ No newline at end of file + const registeredViews = ViewsRegistry.getViews(location); + const viewIds = []; + const viewDescriptors = coalesce(entry.value.map(item => { + const viewDescriptor = { + id: item.id, + name: item.name, + ctor: TreeView, + location, + when: ContextKeyExpr.deserialize(item.when), + canToggleVisibility: true + }; + + // validate + if (viewIds.indexOf(viewDescriptor.id) !== -1) { + collector.error(localize('duplicateView1', "Cannot register multiple views with same id {0} in the location {1}", viewDescriptor.id, viewDescriptor.location.id)); + return null; + } + if (registeredViews.some(v => v.id === viewDescriptor.id)) { + collector.error(localize('duplicateView2', "A view with {0} is already registered in the location {1}", viewDescriptor.id, viewDescriptor.location.id)); + return null; + } + + viewIds.push(viewDescriptor.id); + return viewDescriptor; + })); + ViewsRegistry.registerViews(viewDescriptors); + }); + } + }); \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/views/viewsRegistry.ts b/src/vs/workbench/browser/parts/views/viewsRegistry.ts index bb7bcce90d2..f8fc2f71cc0 100644 --- a/src/vs/workbench/browser/parts/views/viewsRegistry.ts +++ b/src/vs/workbench/browser/parts/views/viewsRegistry.ts @@ -6,6 +6,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ITreeViewDataProvider } from 'vs/workbench/common/views'; +import { localize } from 'vs/nls'; export class ViewLocation { @@ -94,6 +95,9 @@ export const ViewsRegistry: IViewsRegistry = new class { views = []; this._views.set(viewDescriptor.location, views); } + if (views.some(v => v.id === viewDescriptor.id)) { + throw new Error(localize('duplicateId', "A view with {0} is already registered in the location ${1}", viewDescriptor.id, viewDescriptor.location.id)); + } views.push(viewDescriptor); } this._onViewsRegistered.fire(viewDescriptors); @@ -117,7 +121,7 @@ export const ViewsRegistry: IViewsRegistry = new class { } registerTreeViewDataProvider(id: string, factory: ITreeViewDataProvider) { - if (!this.isViewRegistered(id)) { + if (!this.isDataProviderRegistered(id)) { // TODO: throw error } this._treeViewDataPoviders.set(id, factory); @@ -136,7 +140,7 @@ export const ViewsRegistry: IViewsRegistry = new class { return this._treeViewDataPoviders.get(id); } - private isViewRegistered(id: string): boolean { + private isDataProviderRegistered(id: string): boolean { let registered = false; this._views.forEach(views => registered = registered || views.some(view => view.id === id)); return registered;