@@ -13,7 +13,7 @@ import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list
1313import { ElementsDragAndDropData , ListViewTargetSector } from 'vs/base/browser/ui/list/listView' ;
1414import { IAsyncDataSource , ITreeContextMenuEvent , ITreeDragAndDrop , ITreeDragOverReaction , ITreeNode , ITreeRenderer , TreeDragOverBubble } from 'vs/base/browser/ui/tree/tree' ;
1515import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults' ;
16- import { ActionRunner , IAction } from 'vs/base/common/actions' ;
16+ import { ActionRunner , IAction , Separator } from 'vs/base/common/actions' ;
1717import { timeout } from 'vs/base/common/async' ;
1818import { CancellationToken , CancellationTokenSource } from 'vs/base/common/cancellation' ;
1919import { Codicon } from 'vs/base/common/codicons' ;
@@ -1599,13 +1599,53 @@ class TreeMenus implements IDisposable {
15991599 this . contextKeyService = service ;
16001600 }
16011601
1602+ private filterNonUniversalActions ( groups : Map < string , IAction > [ ] , newActions : IAction [ ] ) {
1603+ const newActionsSet : Set < string > = new Set ( newActions . map ( a => a . id ) ) ;
1604+ for ( const group of groups ) {
1605+ const actions = group . keys ( ) ;
1606+ for ( const action of actions ) {
1607+ if ( ! newActionsSet . has ( action ) ) {
1608+ group . delete ( action ) ;
1609+ }
1610+ }
1611+ }
1612+ }
1613+
1614+ private buildMenu ( groups : Map < string , IAction > [ ] ) : IAction [ ] {
1615+ const result : IAction [ ] = [ ] ;
1616+ for ( const group of groups ) {
1617+ if ( group . size > 0 ) {
1618+ if ( result . length ) {
1619+ result . push ( new Separator ( ) ) ;
1620+ }
1621+ result . push ( ...group . values ( ) ) ;
1622+ }
1623+ }
1624+ return result ;
1625+ }
1626+
1627+ private createGroups ( actions : IAction [ ] ) : Map < string , IAction > [ ] {
1628+ const groups : Map < string , IAction > [ ] = [ ] ;
1629+ let group : Map < string , IAction > = new Map ( ) ;
1630+ for ( const action of actions ) {
1631+ if ( action instanceof Separator ) {
1632+ groups . push ( group ) ;
1633+ group = new Map ( ) ;
1634+ } else {
1635+ group . set ( action . id , action ) ;
1636+ }
1637+ }
1638+ groups . push ( group ) ;
1639+ return groups ;
1640+ }
1641+
16021642 private getActions ( menuId : MenuId , elements : ITreeItem [ ] , listen ?: DisposableStore ) : { primary : IAction [ ] ; secondary : IAction [ ] } {
16031643 if ( ! this . contextKeyService ) {
16041644 return { primary : [ ] , secondary : [ ] } ;
16051645 }
16061646
1607- const allowedPrimary = new Map < string , IAction > ( ) ;
1608- const allowedSecondary = new Map < string , IAction > ( ) ;
1647+ let primaryGroups : Map < string , IAction > [ ] = [ ] ;
1648+ let secondaryGroups : Map < string , IAction > [ ] = [ ] ;
16091649 for ( let i = 0 ; i < elements . length ; i ++ ) {
16101650 const element = elements [ i ] ;
16111651 const contextKeyService = this . contextKeyService . createOverlay ( [
@@ -1619,25 +1659,11 @@ class TreeMenus implements IDisposable {
16191659 const result = { primary, secondary, menu } ;
16201660 createAndFillInContextMenuActions ( menu , { shouldForwardArgs : true } , result , 'inline' ) ;
16211661 if ( i === 0 ) {
1622- for ( const action of result . primary ) {
1623- allowedPrimary . set ( action . id , action ) ;
1624- }
1625- for ( const action of result . secondary ) {
1626- allowedSecondary . set ( action . id , action ) ;
1627- }
1662+ primaryGroups = this . createGroups ( result . primary ) ;
1663+ secondaryGroups = this . createGroups ( result . secondary ) ;
16281664 } else {
1629- const primaryKeys = allowedPrimary . keys ( ) ;
1630- for ( const key of primaryKeys ) {
1631- if ( ! result . primary . some ( action => action . id === key ) ) {
1632- allowedPrimary . delete ( key ) ;
1633- }
1634- }
1635- const secondaryKeys = allowedSecondary . keys ( ) ;
1636- for ( const key of secondaryKeys ) {
1637- if ( ! result . secondary . some ( action => action . id === key ) ) {
1638- allowedSecondary . delete ( key ) ;
1639- }
1640- }
1665+ this . filterNonUniversalActions ( primaryGroups , result . primary ) ;
1666+ this . filterNonUniversalActions ( secondaryGroups , result . secondary ) ;
16411667 }
16421668 if ( listen && elements . length === 1 ) {
16431669 listen . add ( menu . onDidChange ( ( ) => this . _onDidChange . fire ( element ) ) ) ;
@@ -1647,7 +1673,7 @@ class TreeMenus implements IDisposable {
16471673 }
16481674 }
16491675
1650- return { primary : Array . from ( allowedPrimary . values ( ) ) , secondary : Array . from ( allowedSecondary . values ( ) ) } ;
1676+ return { primary : this . buildMenu ( primaryGroups ) , secondary : this . buildMenu ( secondaryGroups ) } ;
16511677 }
16521678
16531679 dispose ( ) {
0 commit comments