Merge from vscode bead496a613e475819f89f08e9e882b841bc1fe8 (#14883)

* Merge from vscode bead496a613e475819f89f08e9e882b841bc1fe8

* Bump distro

* Upgrade GCC to 4.9 due to yarn install errors

* Update build image

* Fix bootstrap base url

* Bump distro

* Fix build errors

* Update source map file

* Disable checkbox for blocking migration issues (#15131)

* disable checkbox for blocking issues

* wip

* disable checkbox fixes

* fix strings

* Remove duplicate tsec command

* Default to off for tab color if settings not present

* re-skip failing tests

* Fix mocha error

* Bump sqlite version & fix notebooks search view

* Turn off esbuild warnings

* Update esbuild log level

* Fix overflowactionbar tests

* Fix ts-ignore in dropdown tests

* cleanup/fixes

* Fix hygiene

* Bundle in entire zone.js module

* Remove extra constructor param

* bump distro for web compile break

* bump distro for web compile break v2

* Undo log level change

* New distro

* Fix integration test scripts

* remove the "no yarn.lock changes" workflow

* fix scripts v2

* Update unit test scripts

* Ensure ads-kerberos2 updates in .vscodeignore

* Try fix unit tests

* Upload crash reports

* remove nogpu

* always upload crashes

* Use bash script

* Consolidate data/ext dir names

* Create in tmp directory

Co-authored-by: chlafreniere <hichise@gmail.com>
Co-authored-by: Christopher Suh <chsuh@microsoft.com>
Co-authored-by: chgagnon <chgagnon@microsoft.com>
This commit is contained in:
Karl Burtram
2021-04-27 14:01:59 -07:00
committed by GitHub
parent 7e1c0076ba
commit 867a963882
1817 changed files with 81812 additions and 50843 deletions

View File

@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-action-bar .action-item.menu-entry .action-label {
background-image: var(--menu-entry-icon-light);
display: inline-flex;
}
.vs-dark .monaco-action-bar .action-item.menu-entry .action-label,
.hc-black .monaco-action-bar .action-item.menu-entry .action-label {
background-image: var(--menu-entry-icon-dark);
}

View File

@@ -3,10 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createCSSRule, asCSSUrl, ModifierKeyEmitter } from 'vs/base/browser/dom';
import 'vs/css!./menuEntryActionViewItem';
import { asCSSUrl, createCSSRule, ModifierKeyEmitter } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { IAction, Separator } from 'vs/base/common/actions';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { IdGenerator } from 'vs/base/common/idGenerator'; // {{SQL CARBON EDIT}}
import { IDisposable, toDisposable, MutableDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; // {{SQL CARBON EDIT}}
import { localize } from 'vs/nls';
import { ICommandAction, IMenu, IMenuActionOptions, MenuItemAction, SubmenuItemAction, Icon } from 'vs/platform/actions/common/actions';
@@ -17,18 +18,20 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export function createAndFillInContextMenuActions(menu: IMenu, options: IMenuActionOptions | undefined, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, isPrimaryGroup?: (group: string) => boolean): IDisposable {
const groups = menu.getActions(options);
const useAlternativeActions = ModifierKeyEmitter.getInstance().keyStatus.altKey;
const modifierKeyEmitter = ModifierKeyEmitter.getInstance();
const useAlternativeActions = modifierKeyEmitter.keyStatus.altKey || ((isWindows || isLinux) && modifierKeyEmitter.keyStatus.shiftKey);
fillInActions(groups, target, useAlternativeActions, isPrimaryGroup);
return asDisposable(groups);
}
export function createAndFillInActionBarActions(menu: IMenu, options: IMenuActionOptions | undefined, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, isPrimaryGroup?: (group: string) => boolean): IDisposable {
export function createAndFillInActionBarActions(menu: IMenu, options: IMenuActionOptions | undefined, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, isPrimaryGroup?: (group: string) => boolean, primaryMaxCount?: number): IDisposable {
const groups = menu.getActions(options);
// Action bars handle alternative actions on their own so the alternative actions should be ignored
fillInActions(groups, target, false, isPrimaryGroup);
fillInActions(groups, target, false, isPrimaryGroup, primaryMaxCount);
return asDisposable(groups);
}
@@ -43,32 +46,43 @@ function asDisposable(groups: ReadonlyArray<[string, ReadonlyArray<MenuItemActio
}
// {{SQL CARBON EDIT}} add export modifier
export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuItemAction | SubmenuItemAction>]>, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, useAlternativeActions: boolean, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation'): void {
for (let tuple of groups) {
let [group, actions] = tuple;
export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuItemAction | SubmenuItemAction>]>, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, useAlternativeActions: boolean, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation', primaryMaxCount: number = Number.MAX_SAFE_INTEGER): void {
let primaryBucket: IAction[];
let secondaryBucket: IAction[];
if (Array.isArray(target)) {
primaryBucket = target;
secondaryBucket = target;
} else {
primaryBucket = target.primary;
secondaryBucket = target.secondary;
}
for (let [group, actions] of groups) {
if (useAlternativeActions) {
actions = actions.map(a => (a instanceof MenuItemAction) && !!a.alt ? a.alt : a);
}
if (isPrimaryGroup(group)) {
const to = Array.isArray(target) ? target : target.primary;
to.unshift(...actions);
primaryBucket.unshift(...actions);
} else {
const to = Array.isArray(target) ? target : target.secondary;
if (to.length > 0) {
to.push(new Separator());
if (secondaryBucket.length > 0) {
secondaryBucket.push(new Separator());
}
to.push(...actions);
secondaryBucket.push(...actions);
}
}
// overflow items from the primary group into the secondary bucket
if (primaryBucket !== secondaryBucket && primaryBucket.length > primaryMaxCount) {
const overflow = primaryBucket.splice(primaryMaxCount, primaryBucket.length - primaryMaxCount);
secondaryBucket.unshift(...overflow, new Separator());
}
}
const ids = new IdGenerator('menu-item-action-item-icon-');
const ids = new IdGenerator('menu-item-action-item-icon-'); // {{SQL CARBON EDIT}} - add back since custom toolbar menu is using below
const ICON_PATH_TO_CSS_RULES = new Map<string /* path*/, string /* CSS rule */>();
const ICON_PATH_TO_CSS_RULES = new Map<string /* path*/, string /* CSS rule */>(); // {{SQL CARBON EDIT}} - add back since custom toolbar menu is using below
export class MenuEntryActionViewItem extends ActionViewItem {
@@ -85,7 +99,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
this._altKey = ModifierKeyEmitter.getInstance();
}
protected get _commandAction(): IAction {
protected get _commandAction(): MenuItemAction {
return this._wantsAltCommand && (<MenuItemAction>this._action).alt || this._action;
}
@@ -93,12 +107,14 @@ export class MenuEntryActionViewItem extends ActionViewItem {
event.preventDefault();
event.stopPropagation();
this.actionRunner.run(this._commandAction, this._context)
.then(undefined, err => this._notificationService.error(err));
this.actionRunner
.run(this._commandAction, this._context)
.catch(err => this._notificationService.error(err));
}
render(container: HTMLElement): void {
super.render(container);
container.classList.add('menu-entry');
this._updateItemClass(this._action.item);
@@ -167,46 +183,39 @@ export class MenuEntryActionViewItem extends ActionViewItem {
protected _updateItemClass(item: ICommandAction): void { // {{SQL CARBON EDIT}} make it overwritable
this._itemClassDispose.value = undefined;
const { element, label } = this;
if (!element || !label) {
return;
}
const icon = this._commandAction.checked && (item.toggled as { icon?: Icon })?.icon ? (item.toggled as { icon: Icon }).icon : item.icon;
if (!icon) {
return;
}
if (ThemeIcon.isThemeIcon(icon)) {
// theme icons
const iconClass = ThemeIcon.asClassName(icon);
if (this.label && iconClass) {
this.label.classList.add(...iconClass.split(' '));
this._itemClassDispose.value = toDisposable(() => {
if (this.label) {
this.label.classList.remove(...iconClass.split(' '));
}
});
label.classList.add(...iconClass.split(' '));
this._itemClassDispose.value = toDisposable(() => {
label.classList.remove(...iconClass.split(' '));
});
} else {
// icon path/url
if (icon.light) {
label.style.setProperty('--menu-entry-icon-light', asCSSUrl(icon.light));
}
} else if (icon) {
// icon path
let iconClass: string;
if (icon.dark?.scheme) {
const iconPathMapKey = icon.dark.toString();
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
} else {
iconClass = ids.nextId();
createCSSRule(`.icon.${iconClass}`, `background-image: ${asCSSUrl(icon.light || icon.dark)}`);
createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: ${asCSSUrl(icon.dark)}`);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
if (this.label) {
this.label.classList.add('icon', ...iconClass.split(' '));
this._itemClassDispose.value = toDisposable(() => {
if (this.label) {
this.label.classList.remove('icon', ...iconClass.split(' '));
}
});
}
if (icon.dark) {
label.style.setProperty('--menu-entry-icon-dark', asCSSUrl(icon.dark));
}
label.classList.add('icon');
this._itemClassDispose.value = toDisposable(() => {
label.classList.remove('icon');
label.style.removeProperty('--menu-entry-icon-light');
label.style.removeProperty('--menu-entry-icon-dark');
});
}
}
}
@@ -215,30 +224,42 @@ export class SubmenuEntryActionViewItem extends DropdownMenuActionViewItem {
constructor(
action: SubmenuItemAction,
@INotificationService _notificationService: INotificationService,
@IContextMenuService _contextMenuService: IContextMenuService
@IContextMenuService contextMenuService: IContextMenuService
) {
let classNames: string | string[] | undefined;
super(action, { getActions: () => action.actions }, contextMenuService, {
menuAsChild: true,
classNames: ThemeIcon.isThemeIcon(action.item.icon) ? ThemeIcon.asClassName(action.item.icon) : undefined,
});
}
if (action.item.icon) {
if (ThemeIcon.isThemeIcon(action.item.icon)) {
classNames = ThemeIcon.asClassName(action.item.icon)!;
} else if (action.item.icon.dark?.scheme) {
const iconPathMapKey = action.item.icon.dark.toString();
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
classNames = ['icon', ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!];
} else {
const className = ids.nextId();
classNames = ['icon', className];
createCSSRule(`.icon.${className}`, `background-image: ${asCSSUrl(action.item.icon.light || action.item.icon.dark)}`);
createCSSRule(`.vs-dark .icon.${className}, .hc-black .icon.${className}`, `background-image: ${asCSSUrl(action.item.icon.dark)}`);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, className);
render(container: HTMLElement): void {
super.render(container);
if (this.element) {
container.classList.add('menu-entry');
const { icon } = (<SubmenuItemAction>this._action).item;
if (icon && !ThemeIcon.isThemeIcon(icon)) {
this.element.classList.add('icon');
if (icon.light) {
this.element.style.setProperty('--menu-entry-icon-light', asCSSUrl(icon.light));
}
if (icon.dark) {
this.element.style.setProperty('--menu-entry-icon-dark', asCSSUrl(icon.dark));
}
}
}
}
}
super(action, action.actions, _contextMenuService, { classNames: classNames, menuAsChild: true });
/**
* Creates action view items for menu actions or submenu actions.
*/
export function createActionViewItem(instaService: IInstantiationService, action: IAction): undefined | MenuEntryActionViewItem | SubmenuEntryActionViewItem {
if (action instanceof MenuItemAction) {
return instaService.createInstance(MenuEntryActionViewItem, action);
} else if (action instanceof SubmenuItemAction) {
return instaService.createInstance(SubmenuEntryActionViewItem, action);
} else {
return undefined;
}
}

View File

@@ -16,22 +16,36 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { UriDto } from 'vs/base/common/types';
import { Iterable } from 'vs/base/common/iterator';
import { LinkedList } from 'vs/base/common/linkedList';
import { CSSIcon } from 'vs/base/common/codicons';
export interface ILocalizedString {
/**
* The localized value of the string.
*/
value: string;
/**
* The original (non localized value of the string)
*/
original: string;
}
export interface ICommandActionTitle extends ILocalizedString {
/**
* The title with a mnemonic designation. && precedes the mnemonic.
*/
mnemonicTitle?: string;
}
export type Icon = { dark?: URI; light?: URI; } | ThemeIcon;
export interface ICommandAction {
id: string;
title: string | ILocalizedString;
title: string | ICommandActionTitle;
category?: string | ILocalizedString;
tooltip?: string | ILocalizedString;
tooltip?: string;
icon?: Icon;
precondition?: ContextKeyExpression;
toggled?: ContextKeyExpression | { condition: ContextKeyExpression, icon?: Icon, tooltip?: string | ILocalizedString };
toggled?: ContextKeyExpression | { condition: ContextKeyExpression, icon?: Icon, tooltip?: string; };
}
export type ISerializableCommandAction = UriDto<ICommandAction>;
@@ -45,7 +59,7 @@ export interface IMenuItem {
}
export interface ISubmenuItem {
title: string | ILocalizedString;
title: string | ICommandActionTitle;
submenu: MenuId;
icon?: Icon;
when?: ContextKeyExpression;
@@ -112,6 +126,7 @@ export class MenuId {
static readonly TunnelInline = new MenuId('TunnelInline');
static readonly TunnelTitle = new MenuId('TunnelTitle');
static readonly ViewItemContext = new MenuId('ViewItemContext');
static readonly ViewContainerTitle = new MenuId('ViewContainerTitle');
static readonly ViewContainerTitleContext = new MenuId('ViewContainerTitleContext');
static readonly ViewTitle = new MenuId('ViewTitle');
static readonly ViewTitleContext = new MenuId('ViewTitleContext');
@@ -141,6 +156,7 @@ export class MenuId {
static readonly TimelineTitle = new MenuId('TimelineTitle');
static readonly TimelineTitleContext = new MenuId('TimelineTitleContext');
static readonly AccountsContext = new MenuId('AccountsContext');
static readonly PanelTitle = new MenuId('PanelTitle');
readonly id: number;
readonly _debugName: string;
@@ -157,7 +173,7 @@ export interface IMenuActionOptions {
}
export interface IMenu extends IDisposable {
readonly onDidChange: Event<IMenu | undefined>;
readonly onDidChange: Event<IMenu>;
getActions(options?: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][];
}
@@ -182,7 +198,7 @@ export interface IMenuRegistry {
addCommand(userCommand: ICommandAction): IDisposable;
getCommand(id: string): ICommandAction | undefined;
getCommands(): ICommandsMap;
appendMenuItems(items: Iterable<{ id: MenuId, item: IMenuItem | ISubmenuItem }>): IDisposable;
appendMenuItems(items: Iterable<{ id: MenuId, item: IMenuItem | ISubmenuItem; }>): IDisposable;
appendMenuItem(menu: MenuId, item: IMenuItem | ISubmenuItem): IDisposable;
getMenuItems(loc: MenuId): Array<IMenuItem | ISubmenuItem>;
}
@@ -233,7 +249,7 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry {
return this.appendMenuItems(Iterable.single({ id, item }));
}
appendMenuItems(items: Iterable<{ id: MenuId, item: IMenuItem | ISubmenuItem }>): IDisposable {
appendMenuItems(items: Iterable<{ id: MenuId, item: IMenuItem | ISubmenuItem; }>): IDisposable {
const changedIds = new Set<MenuId>();
const toRemove = new LinkedList<Function>();
@@ -343,62 +359,76 @@ export class SubmenuItemAction extends SubmenuAction {
}
}
export class MenuItemAction extends ExecuteCommandAction {
// implements IAction, does NOT extend Action, so that no one
// subscribes to events of Action or modified properties
export class MenuItemAction implements IAction {
readonly item: ICommandAction;
readonly alt: MenuItemAction | undefined;
private readonly _options: IMenuActionOptions | undefined;
private _options: IMenuActionOptions;
readonly id: string;
// {{SQL CARBON EDIT}} -- remove readonly since notebook component sets these
label: string;
tooltip: string;
readonly class: string | undefined;
readonly enabled: boolean;
readonly checked: boolean;
readonly expanded: boolean = false;
constructor(
item: ICommandAction,
alt: ICommandAction | undefined,
options: IMenuActionOptions,
options: IMenuActionOptions | undefined,
@IContextKeyService contextKeyService: IContextKeyService,
@ICommandService commandService: ICommandService
@ICommandService private _commandService: ICommandService
) {
typeof item.title === 'string' ? super(item.id, item.title, commandService) : super(item.id, item.title.value, commandService);
this._cssClass = undefined;
this._enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition);
this._tooltip = item.tooltip ? typeof item.tooltip === 'string' ? item.tooltip : item.tooltip.value : undefined;
this.id = item.id;
this.label = typeof item.title === 'string' ? item.title : item.title.value;
this.tooltip = item.tooltip ?? '';
this.enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition);
this.checked = false;
if (item.toggled) {
const toggled = ((item.toggled as { condition: ContextKeyExpression }).condition ? item.toggled : { condition: item.toggled }) as {
condition: ContextKeyExpression, icon?: Icon, tooltip?: string | ILocalizedString
const toggled = ((item.toggled as { condition: ContextKeyExpression; }).condition ? item.toggled : { condition: item.toggled }) as {
condition: ContextKeyExpression, icon?: Icon, tooltip?: string | ILocalizedString;
};
this._checked = contextKeyService.contextMatchesRules(toggled.condition);
if (this._checked && toggled.tooltip) {
this._tooltip = typeof toggled.tooltip === 'string' ? toggled.tooltip : toggled.tooltip.value;
this.checked = contextKeyService.contextMatchesRules(toggled.condition);
if (this.checked && toggled.tooltip) {
this.tooltip = typeof toggled.tooltip === 'string' ? toggled.tooltip : toggled.tooltip.value;
}
}
this._options = options || {};
this.item = item;
this.alt = alt ? new MenuItemAction(alt, undefined, this._options, contextKeyService, commandService) : undefined;
this.alt = alt ? new MenuItemAction(alt, undefined, options, contextKeyService, _commandService) : undefined;
this._options = options;
if (ThemeIcon.isThemeIcon(item.icon)) {
this.class = CSSIcon.asClassName(item.icon);
}
}
dispose(): void {
if (this.alt) {
this.alt.dispose();
}
super.dispose();
// there is NOTHING to dispose and the MenuItemAction should
// never have anything to dispose as it is a convenience type
// to bridge into the rendering world.
}
run(...args: any[]): Promise<any> {
let runArgs: any[] = [];
if (this._options.arg) {
if (this._options?.arg) {
runArgs = [...runArgs, this._options.arg];
}
if (this._options.shouldForwardArgs) {
if (this._options?.shouldForwardArgs) {
runArgs = [...runArgs, ...args];
}
return super.run(...runArgs);
return this._commandService.executeCommand(this.id, ...runArgs);
}
}
export class SyncActionDescriptor {
@@ -411,7 +441,7 @@ export class SyncActionDescriptor {
private readonly _keybindingContext: ContextKeyExpression | undefined;
private readonly _keybindingWeight: number | undefined;
public static create<Services extends BrandedService[]>(ctor: { new(id: string, label: string, ...services: Services): Action },
public static create<Services extends BrandedService[]>(ctor: { new(id: string, label: string, ...services: Services): Action; },
id: string, label: string | undefined, keybindings?: IKeybindings, keybindingContext?: ContextKeyExpression, keybindingWeight?: number
): SyncActionDescriptor {
return new SyncActionDescriptor(ctor as IConstructorSignature2<string, string | undefined, Action>, id, label, keybindings, keybindingContext, keybindingWeight);
@@ -478,7 +508,7 @@ export interface IAction2Options extends ICommandAction {
/**
* One or many menu items.
*/
menu?: OneOrN<{ id: MenuId } & Omit<IMenuItem, 'command'>>;
menu?: OneOrN<{ id: MenuId; } & Omit<IMenuItem, 'command'>>;
/**
* One keybinding.
@@ -497,7 +527,7 @@ export abstract class Action2 {
abstract run(accessor: ServicesAccessor, ...args: any[]): any;
}
export function registerAction2(ctor: { new(): Action2 }): IDisposable {
export function registerAction2(ctor: { new(): Action2; }): IDisposable {
const disposables = new DisposableStore();
const action = new ctor();

View File

@@ -3,11 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { RunOnceScheduler } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IMenu, IMenuActionOptions, IMenuItem, IMenuService, isIMenuItem, ISubmenuItem, MenuId, MenuItemAction, MenuRegistry, SubmenuItemAction, ILocalizedString } from 'vs/platform/actions/common/actions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextKeyService, IContextKeyChangeEvent, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
import { IContextKeyService, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
export class MenuService implements IMenuService {
@@ -29,9 +30,11 @@ type MenuItemGroup = [string, Array<IMenuItem | ISubmenuItem>];
class Menu implements IMenu {
private readonly _onDidChange = new Emitter<IMenu | undefined>();
private readonly _dispoables = new DisposableStore();
private readonly _onDidChange = new Emitter<IMenu>();
readonly onDidChange: Event<IMenu> = this._onDidChange.event;
private _menuGroups: MenuItemGroup[] = [];
private _contextKeys: Set<string> = new Set();
@@ -45,19 +48,23 @@ class Menu implements IMenu {
// rebuild this menu whenever the menu registry reports an
// event for this MenuId
this._dispoables.add(Event.debounce(
Event.filter(MenuRegistry.onDidChangeMenu, set => set.has(this._id)),
() => { },
50
)(this._build, this));
const rebuildMenuSoon = new RunOnceScheduler(() => this._build(), 50);
this._dispoables.add(rebuildMenuSoon);
this._dispoables.add(MenuRegistry.onDidChangeMenu(e => {
if (e.has(_id)) {
rebuildMenuSoon.schedule();
}
}));
// when context keys change we need to check if the menu also
// has changed
this._dispoables.add(Event.debounce<IContextKeyChangeEvent, boolean>(
this._contextKeyService.onDidChangeContext,
(last, event) => last || event.affectsSome(this._contextKeys),
50
)(e => e && this._onDidChange.fire(undefined), this));
const fireChangeSoon = new RunOnceScheduler(() => this._onDidChange.fire(this), 50);
this._dispoables.add(fireChangeSoon);
this._dispoables.add(_contextKeyService.onDidChangeContext(e => {
if (e.affectsSome(this._contextKeys)) {
fireChangeSoon.schedule();
}
}));
}
dispose(): void {
@@ -88,25 +95,22 @@ class Menu implements IMenu {
// keep keys for eventing
Menu._fillInKbExprKeys(item.when, this._contextKeys);
// keep precondition keys for event if applicable
if (isIMenuItem(item) && item.command.precondition) {
Menu._fillInKbExprKeys(item.command.precondition, this._contextKeys);
}
// keep toggled keys for event if applicable
if (isIMenuItem(item) && item.command.toggled) {
const toggledExpression: ContextKeyExpression = (item.command.toggled as { condition: ContextKeyExpression }).condition || item.command.toggled as ContextKeyExpression; // {{SQL CARBON EDIT}} strict-null-checks
Menu._fillInKbExprKeys(toggledExpression, this._contextKeys);
if (isIMenuItem(item)) {
// keep precondition keys for event if applicable
if (item.command.precondition) {
Menu._fillInKbExprKeys(item.command.precondition, this._contextKeys);
}
// keep toggled keys for event if applicable
if (item.command.toggled) {
const toggledExpression: any = (item.command.toggled as { condition: ContextKeyExpression }).condition || item.command.toggled;
Menu._fillInKbExprKeys(toggledExpression, this._contextKeys);
}
}
}
this._onDidChange.fire(this);
}
get onDidChange(): Event<IMenu | undefined> {
return this._onDidChange.event;
}
getActions(options: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][] {
getActions(options?: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][] {
const result: [string, Array<MenuItemAction | SubmenuItemAction>][] = [];
for (let group of this._menuGroups) {
const [id, items] = group;