Skip to content

Commit 29ee89a

Browse files
authored
support disposing keybinding registrations, esp when disposing Action2 instances (microsoft#159433)
1 parent 3cba0ec commit 29ee89a

File tree

2 files changed

+28
-17
lines changed

2 files changed

+28
-17
lines changed

src/vs/platform/actions/common/actions.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,18 +581,18 @@ export function registerAction2(ctor: { new(): Action2 }): IDisposable {
581581
// keybinding
582582
if (Array.isArray(keybinding)) {
583583
for (const item of keybinding) {
584-
KeybindingsRegistry.registerKeybindingRule({
584+
disposables.add(KeybindingsRegistry.registerKeybindingRule({
585585
...item,
586586
id: command.id,
587587
when: command.precondition ? ContextKeyExpr.and(command.precondition, item.when) : item.when
588-
});
588+
}));
589589
}
590590
} else if (keybinding) {
591-
KeybindingsRegistry.registerKeybindingRule({
591+
disposables.add(KeybindingsRegistry.registerKeybindingRule({
592592
...keybinding,
593593
id: command.id,
594594
when: command.precondition ? ContextKeyExpr.and(command.precondition, keybinding.when) : keybinding.when
595-
});
595+
}));
596596
}
597597

598598
return disposables;

src/vs/platform/keybinding/common/keybindingsRegistry.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { OperatingSystem, OS } from 'vs/base/common/platform';
99
import { CommandsRegistry, ICommandHandler, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
1010
import { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
1111
import { Registry } from 'vs/platform/registry/common/platform';
12+
import { combinedDisposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
13+
import { LinkedList } from 'vs/base/common/linkedList';
1214

1315
export interface IKeybindingItem {
1416
keybinding: (SimpleKeybinding | ScanCodeBinding)[];
@@ -69,20 +71,20 @@ export interface ICommandAndKeybindingRule extends IKeybindingRule {
6971
}
7072

7173
export interface IKeybindingsRegistry {
72-
registerKeybindingRule(rule: IKeybindingRule): void;
74+
registerKeybindingRule(rule: IKeybindingRule): IDisposable;
7375
setExtensionKeybindings(rules: IExtensionKeybindingRule[]): void;
74-
registerCommandAndKeybindingRule(desc: ICommandAndKeybindingRule): void;
76+
registerCommandAndKeybindingRule(desc: ICommandAndKeybindingRule): IDisposable;
7577
getDefaultKeybindings(): IKeybindingItem[];
7678
}
7779

7880
class KeybindingsRegistryImpl implements IKeybindingsRegistry {
7981

80-
private _coreKeybindings: IKeybindingItem[];
82+
private _coreKeybindings: LinkedList<IKeybindingItem>;
8183
private _extensionKeybindings: IKeybindingItem[];
8284
private _cachedMergedKeybindings: IKeybindingItem[] | null;
8385

8486
constructor() {
85-
this._coreKeybindings = [];
87+
this._coreKeybindings = new LinkedList();
8688
this._extensionKeybindings = [];
8789
this._cachedMergedKeybindings = null;
8890
}
@@ -108,13 +110,14 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry {
108110
return kb;
109111
}
110112

111-
public registerKeybindingRule(rule: IKeybindingRule): void {
113+
public registerKeybindingRule(rule: IKeybindingRule): IDisposable {
112114
const actualKb = KeybindingsRegistryImpl.bindToCurrentPlatform(rule);
115+
const result = new DisposableStore();
113116

114117
if (actualKb && actualKb.primary) {
115118
const kk = createKeybinding(actualKb.primary, OS);
116119
if (kk) {
117-
this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, 0, rule.when);
120+
result.add(this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, 0, rule.when));
118121
}
119122
}
120123

@@ -123,10 +126,11 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry {
123126
const k = actualKb.secondary[i];
124127
const kk = createKeybinding(k, OS);
125128
if (kk) {
126-
this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, -i - 1, rule.when);
129+
result.add(this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, -i - 1, rule.when));
127130
}
128131
}
129132
}
133+
return result;
130134
}
131135

132136
public setExtensionKeybindings(rules: IExtensionKeybindingRule[]): void {
@@ -151,9 +155,11 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry {
151155
this._cachedMergedKeybindings = null;
152156
}
153157

154-
public registerCommandAndKeybindingRule(desc: ICommandAndKeybindingRule): void {
155-
this.registerKeybindingRule(desc);
156-
CommandsRegistry.registerCommand(desc);
158+
public registerCommandAndKeybindingRule(desc: ICommandAndKeybindingRule): IDisposable {
159+
return combinedDisposable(
160+
this.registerKeybindingRule(desc),
161+
CommandsRegistry.registerCommand(desc)
162+
);
157163
}
158164

159165
private static _mightProduceChar(keyCode: KeyCode): boolean {
@@ -190,11 +196,11 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry {
190196
}
191197
}
192198

193-
private _registerDefaultKeybinding(keybinding: Keybinding, commandId: string, commandArgs: any, weight1: number, weight2: number, when: ContextKeyExpression | null | undefined): void {
199+
private _registerDefaultKeybinding(keybinding: Keybinding, commandId: string, commandArgs: any, weight1: number, weight2: number, when: ContextKeyExpression | null | undefined): IDisposable {
194200
if (OS === OperatingSystem.Windows) {
195201
this._assertNoCtrlAlt(keybinding.parts[0], commandId);
196202
}
197-
this._coreKeybindings.push({
203+
const remove = this._coreKeybindings.push({
198204
keybinding: keybinding.parts,
199205
command: commandId,
200206
commandArgs: commandArgs,
@@ -205,11 +211,16 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry {
205211
isBuiltinExtension: false
206212
});
207213
this._cachedMergedKeybindings = null;
214+
215+
return toDisposable(() => {
216+
remove();
217+
this._cachedMergedKeybindings = null;
218+
});
208219
}
209220

210221
public getDefaultKeybindings(): IKeybindingItem[] {
211222
if (!this._cachedMergedKeybindings) {
212-
this._cachedMergedKeybindings = (<IKeybindingItem[]>[]).concat(this._coreKeybindings).concat(this._extensionKeybindings);
223+
this._cachedMergedKeybindings = Array.from(this._coreKeybindings).concat(this._extensionKeybindings);
213224
this._cachedMergedKeybindings.sort(sorter);
214225
}
215226
return this._cachedMergedKeybindings.slice(0);

0 commit comments

Comments
 (0)